Започвайки от втория комит, всеки код става наследен, защото първоначалните идеи започват да се разминават със суровата реалност. Това не е нито добро, нито лошо, това е даденост, с която трудно се спори и трябва да се живее. Част от този процес е рефакторингът. Рефакторинг на инфраструктурата като код. Нека историята започне с това как да преработим Ansible за една година и да не полудеем.
Раждането на наследството
Ден #1: Нулев пациент
Имало едно време един условен проект. Имаше екип за разработка на Dev и инженери на Ops. Те решаваха същия проблем: как да разположат сървъри и да стартират приложение. Проблемът беше, че всеки отбор реши този проблем по свой начин. По време на проекта беше решено да се използва Ansible за синхронизиране на знанията между екипите Dev и Ops.
Ден #89: Раждането на наследството
Без да го забелязват, те искаха да го направят възможно най-добре, но се оказа, че е наследство. как става това
Имаме спешна задача тук, нека направим мръсен хак и след това да го поправим.
Не е нужно да пишете документация и всичко е ясно какво се случва тук.
Знам Ansible/Python/Bash/Terraform! Вижте как мога да избягвам!
Аз съм разработчик на Full Stack Overflow и копирах това от stackoverflow, не знам как работи, но изглежда страхотно и решава проблема.
В резултат на това можете да получите неразбираем тип код, за който няма документация, не е ясно какво прави, дали е необходим, но проблемът е, че трябва да го разработите, модифицирате, добавите патерици и опори , което прави ситуацията още по-лоша.
Първоначално замисленият и внедрен IaC модел вече не отговаря на изискванията на потребителите / бизнеса / други екипи и времето за извършване на промени в инфраструктурата престава да бъде приемливо. В този момент идва разбирането, че е време да се действа.
IaC рефакторинг
Ден #139: Наистина ли имате нужда от рефакторинг?
Преди да се втурнете да преработвате, трябва да отговорите на няколко важни въпроса:
Защо ти трябва всичко това?
Имаш ли време?
Знанието достатъчно ли е?
Ако не знаете как да отговорите на въпросите, тогава рефакторингът ще приключи, преди дори да започне, или може само да се влоши. защото имаше опит( Какво научих от тестването на 200 000 реда инфраструктурен код), тогава проектът получи молба за помощ за коригиране на ролите и покриването им с тестове.
Ден #149: Подготовка на рефакторинга
Първото нещо е да се подготвите. Решете какво ще правим. За да направим това, ние общуваме, намираме проблемни области и измисляме начини за разрешаването им. Ние записваме получените концепции по някакъв начин, например статия в сливане, така че когато възникне въпросът „кое е най-добро?“ или "кое е правилното?" Не сме се изгубили. В нашия случай се придържахме към идеята разделяй и владей: разбиваме инфраструктурата на малки парчета/тухли. Този подход ви позволява да вземете изолирана част от инфраструктурата, да разберете какво прави, да я покриете с тестове и да я промените, без да се страхувате, че ще счупите нещо.
Оказва се, че тестването на инфраструктурата става крайъгълен камък и тук си струва да споменем пирамидата за тестване на инфраструктура. Абсолютно същата идея, която е в процес на разработка, но за инфраструктура: преминаваме от евтини бързи тестове, които проверяват прости неща, като отстъп, към скъпи пълноценни тестове, които разгръщат цялата инфраструктура.
Ansible тестови опити
Преди да започнем да описваме как покрихме Ansible тестовете по проекта, ще опиша опитите и подходите, които имах възможността да използвам по-рано, за да разбера контекста на взетите решения.
Ден № -997: Предоставяне на SDS
Първият път, когато тествах Ansible, беше по проект за разработване на SDS (софтуерно дефинирано съхранение). Има отделна статия по тази тема Как да счупите велосипеди с патерици, когато тествате разпределението си, но накратко, завършихме с обърната тестова пирамида и тествайки прекарахме 60-90 минути на една роля, което е много време. Основата беше e2e тестове, т.е. внедрихме пълноценна инсталация и след това я тествахме. Това, което беше още по-утежняващо, беше изобретяването на собствения му велосипед. Но трябва да призная, че това решение проработи и позволи стабилно издание.
Ден # -701: Ansible и тестова кухня
Развитието на идеята за тестване на Ansible беше използването на готови инструменти, а именно test kitchen / kitchen-ci и inspec. Изборът се определя от познаването на Ruby (за повече подробности вижте статията на Habré: YML програмистите мечтаят ли да тестват Ansible?) работи по-бързо, около 40 минути за 10 роли. Създадохме пакет от виртуални машини и проведохме тестове вътре.
Като цяло решението работи, но имаше известна утайка поради разнородност. Когато броят на тестваните хора беше увеличен до 13 основни роли и 2 мета роли, комбиниращи по-малки роли, изведнъж тестовете започнаха да се изпълняват за 70 минути, което е почти 2 пъти повече. Беше трудно да се говори за практики на XP (екстремно програмиране), защото... никой не иска да чака 70 минути. Това беше причината за промяна на подхода
Ден # -601: Анзибъл и молекула
Концептуално това е подобно на testkitchen, само че преместихме ролевото тестване в docker и променихме стека. В резултат на това времето беше намалено до стабилни 20-25 минути за 7 роли.
Чрез увеличаване на броя на тестваните роли до 17 и линтинг на 45 роли, ние изпълнихме това за 28 минути на 2 дженкинс подчинени устройства.
Ден #167: Добавяне на Ansible тестове към проекта
Най-вероятно няма да е възможно да изпълните задачата за рефакторинг набързо. Задачата трябва да е измерима, за да можете да я натрошите на малки парчета и да изядете слона парче по парче с чаена лъжичка. Трябва да има разбиране дали се движите в правилната посока, колко дълго да вървите.
Като цяло, няма значение как ще се направи, можете да пишете на лист хартия, можете да поставите стикери на шкафа, можете да създавате задачи в Jira или можете да отворите Google Docs и да запишете текущото състояние там. Краката растат от факта, че процесът не е незабавен, ще бъде дълъг и досаден. Малко вероятно е някой да иска да изгорите от идеи, да се уморите и да бъдете претоварени по време на рефакторинг.
Рефакторингът е прост:
Яжте.
Спете.
Код.
IaC тест.
Повтарям
и повтаряме това, докато достигнем желаната цел.
Може да не е възможно да започнем да тестваме всичко веднага, така че първата ни задача беше да започнем с линтинг и проверка на синтаксиса.
Ден #181: Майстор на екологичното строителство
Linting е малка първа стъпка към Green Build Master. Това няма да счупи почти нищо, но ще ви позволи да дебъгвате процеси и да правите зелени компилации в jenkins. Идеята е да се развият навици сред екипа:
Червените тестове са лоши.
Дойдох да поправя нещо и в същото време да направя кода малко по-добър, отколкото беше преди вас.
Ден #193: От линтинг до модулни тестове
След като изградите процеса на въвеждане на кода в главния код, можете да започнете процеса на подобрение стъпка по стъпка - замяна на linting с стартиращи роли, можете дори да го направите без идемпотентност. Трябва да разберете как да прилагате роли и как работят.
Ден #211: От модулни към интеграционни тестове
Когато повечето роли са покрити с модулни тестове и всичко е разпръснато, можете да преминете към добавяне на интеграционни тестове. Тези. тестване не на отделна тухла в инфраструктурата, а на комбинация от тях, например пълна конфигурация на инстанция.
Използвайки jenkins, ние генерирахме много етапи, които паралелно написваха роли/книги за игри, след това тестове на модули в контейнери и накрая тестове за интеграция.
Jenkins + Docker + Ansible = Тестове
Checkout repo и генериране на етапи на изграждане.
Изпълнявайте паралелно етапите на lint playbook.
Изпълнете успоредно етапите на ролята на мъх.
Изпълнете успоредно етапите на ролята за проверка на синтаксиса.
Изпълнете успоредно етапите на тестовата роля.
Роля на мъх.
Проверете зависимостта от други роли.
Проверете синтаксиса.
Създайте докер екземпляр
Стартирайте molecule/default/playbook.yml.
Проверете идемпотентността.
Изпълнете интеграционни тестове
завършеност
Ден #271: Автобусен фактор
Първоначално рефакторингът се извършваше от малка група от двама или трима души. Те прегледаха кода в мастера. С течение на времето екипът разви знания за това как да пише код и прегледът на кода допринесе за разпространението на знания за инфраструктурата и как тя работи. Акцентът тук беше, че рецензентите се избираха един по един, по график, т.е. с известна степен на вероятност ще се изкачите в нова част от инфраструктурата.
И тук трябва да е удобно. Удобно е да направите преглед, да видите в рамките на каква задача е изпълнена и историята на дискусиите. Имаме интегрирани jenkins + bitbucket + jira.
Но като такъв прегледът не е панацея; някак си попаднахме в главния код, което ни накара да направим провалени тестове:
С течение на времето имаше повече тестове, компилациите вървяха по-бавно, до час в най-лошия случай. На едно от ретротата имаше фраза като „добре е, че има тестове, но те са бавни“. В резултат на това изоставихме интеграционните тестове на виртуални машини и ги адаптирахме за Docker, за да го направим по-бърз. Също така заменихме testinfra с ansible verifier, за да намалим броя на използваните инструменти.
Строго погледнато, имаше набор от мерки:
Превключете към докер.
Премахнете ролевото тестване, което се дублира поради зависимости.
Увеличете броя на робите.
Ред за пробно изпълнение.
Възможност за мъх ВСИЧКО локално с една команда.
В резултат на това Pipeline on jenkins също беше унифициран
Генерирайте етапи на изграждане.
Линт всички паралелно.
Изпълнете успоредно етапите на тестовата роля.
Завършек.
Поуки
Избягвайте глобалните променливи
Ansible използва глобални променливи, във формата има частично решение private_role_varis, но това не е панацея.
Нека ви дам един пример. Нека имаме role_a и role_b
Смешното е, че резултатът от книгите за игри ще зависи от неща, които не винаги са очевидни, като например реда, в който са изброени ролите. За съжаление, това е природата на Ansible и най-доброто нещо, което може да се направи, е да се използва някакъв вид споразумение, например в рамките на роля, използвайте само променливата, описана в тази роля.
Съгласихме се да използваме променливи префикси; не би било излишно да проверим дали те са дефинирани както очакваме и например не са заменени от празна стойност
ДОБРА: Проверете променливите.
- name: "Verify that required string variables are defined"
assert:
that: ahs_var is defined and ahs_var | length > 0 and ahs_var != None
fail_msg: "{{ ahs_var }} needs to be set for the role to work "
success_msg: "Required variables {{ ahs_var }} is defined"
loop_control:
loop_var: ahs_var
with_items:
- ahs_item1
- ahs_item2
- ahs_item3
Избягвайте хеш речници, използвайте плоска структура
Ако дадена роля очаква хеш/речник в един от своите параметри, тогава, ако искаме да променим един от дъщерните параметри, ще трябва да заменим целия хеш/речник, което ще увеличи сложността на конфигурацията.
Ролите и книгите трябва да са идемпотентни, защото намалява отклоненията в конфигурацията и страха от счупване на нещо. Но ако използвате молекула, това е поведението по подразбиране.
Избягвайте използването на модули на командната обвивка
Използването на шел модул води до императивна парадигма на описание, вместо декларативна, която е ядрото на Ansible.
Тествайте ролите си чрез молекула
Молекулата е много гъвкаво нещо, нека да разгледаме няколко сценария.
Молекула Множество инстанции
В molecule.yml в раздел platforms можете да опишете много хостове, които можете да внедрите.
В molecule е възможно да се използва ansible, за да се провери дали екземплярът е конфигуриран правилно, освен това това е по подразбиране от версия 3. Не е толкова гъвкав като testinfra/inspec, но можем да проверим дали съдържанието на файла отговаря на нашите очаквания:
Или внедрите услугата, изчакайте да стане достъпна и направете тест за дим:
---
- name: Verify
hosts: solr
tasks:
- command: /blah/solr/bin/solr start -s /solr_home -p 8983 -force
- uri:
url: http://127.0.0.1:8983/solr
method: GET
status_code: 200
register: uri_result
until: uri_result is not failed
retries: 12
delay: 10
- name: Post documents to solr
command: /blah/solr/bin/post -c master /exampledocs/books.csv
Поставете сложна логика в модули и добавки
Ansible се застъпва за декларативен подход, така че когато правите разклоняване на кода, трансформация на данни, шел модули, кодът става труден за четене. За да се борите с това и да го поддържате лесен за разбиране, не би било излишно да се борите с тази сложност, като създадете свои собствени модули.
UPD1 2020.05.01 20:30 — За първично профилиране на книги за игри, които можете да използвате callback_whitelist = profile_tasks да разбере какво точно работи за дълго време. След това минаваме Класически анзибилни ускорения. Можете също да опитате митоген UPD2 2020.05.03 16:34 - Angielski версия