Пачынальна з другога комміта любы код становіцца legacy, т.я. першапачатковыя задумкі пачынаюць разыходзіцца з суровай рэальнасцю. Гэта не добра і не дрэнна, гэта дадзенасць з якой складана спрачацца і неабходна ўжывацца. Часткай гэтага працэсу з'яўляецца рэфактарынг. Рэфактарынг Infrastructure as Code. Ды пачнецца гісторыя як адрэфактарыць Ansible за год і не зляцець з шпулек.
Зараджэнне Legacy
Дзень № 1: Нулявы пацыент
Жыл быў умоўны праект. На ім была каманда Dev распрацоўкі і Ops інжынеры. Яны вырашалі адну і тую ж задачу: як разгарнуць сервера і запусціць праграму. Праблема была ў тым, што кожная каманда вырашала гэтую задачу па-свойму. На праекце было прынятае рашэнне выкарыстоўваць Ansible для сінхранізацыі ведаў паміж камандамі Dev і Ops.
Дзень № 89: Зараджэнне Legacy
Самі таго не заўважыўшы, хацелі зрабіць як мага лепей, а атрымалася legacy. Як так атрымоўваецца?
У нас тут тэрміновая цяга, зробім брудны хак - потым выправім.
Дакументацыю можна не пісаць і так усё зразумела, што тут адбываецца.
Я ведаю Ansible / Python / Bash / Terraform! Глядзіце як я магу перакруціцца!
Я Full Stack Overflow Developer скапіяваў гэта са stackoverflow, не ведаю як гэта працуе, але выглядае прыкольна і вырашае задачу.
У выніку можна атрымаць код незразумелага выгляду, на які няма дакументацыі, невядома што ён робіць, ці патрэбен ён, але праблема ў тым, што вам неабходна яго развіваць, дапрацоўваць, дадаваць мыліцы з падпоркамі, робячы сітуацыю толькі яшчэ горш.
Першапачаткова задуманая і рэалізаваная мадэль IaC перастае адказваць рэчаіснасці з запытамі карыстальнікаў / бізнесу / іншых каманд, час унясенне змяненняў у інфраструктуру перастае быць прымальным. У гэты момант прыходзіць разуменне, што час прымаць меры.
Рэфактарынг IaC
Дзень № 139: А вам сапраўды патрэбен рэфакторынг?
Перш чым кідацца рэфактарыць вы павінны адказаць на шэраг важных пытанняў:
Нашто вам усё гэта?
Ці ёсць у вас час?
Ці дастаткова ведаў?
Калі вы не ведаеце як адказаць на пытанні, то рэфактарынг скончыцца так і не пачаўшыся ці можа атрымацца толькі горш. Т.к. быў вопыт( Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода), то ад праекта прыйшоў запыт дапамогі выправіць ролі і пакрыць іх тэстамі.
Дзень № 149: Падрыхтоўка рэфактарынгу
Першачарговае гэта трэба падрыхтавацца. Вызначыцца, што будзем рабіць. Для гэтага маем зносіны, знаходзім праблемныя кропкі і мяркуем шляхі іх рашэння. Атрыманыя канцэпты неяк фіксуем, напрыклад артыкул у confluence, каб пры з'яўленні пытання "як лепш?" або "як правільней?" мы не збіліся з курса. У нашым выпадку мы прытрымліваліся ідэі падзяляй і пануй: дробім інфраструктуру на маленькія кавалачкі / цаглінкі. Такі падыход дазваляе ўзяць ізаляваны кавалак інфраструктуры, зразумець што ён робіць, пакрыць яго тэстамі і змяніць не пабаяўшыся што-небудзь зламаць.
Атрымліваецца, што тэсціраванне інфраструктуры становіцца краевугольным каменем і тут варта згадаць піраміду тэсціравання інфраструктуры. Роўна таксама ідэя, што ў распрацоўцы, але для інфраструктуры: ідзем ад танных хуткіх тэстаў якія правяраюць простыя рэчы, напрыклад водступы, да дарагіх паўнавартасных тэстамі разгортваюць суцэльную інфраструктуру.
Спробы тэсціравання Ansible
Перш чым пойдзем апісваць як пакрывалі тэстамі Ansible на праекце, апішу спробы і падыходы якія давялося выкарыстоўваць раней, каб зразумець кантэкст прыманых рашэнняў.
Дзень №997: SDS provision
Першы раз тэставаць Ansible давялося на праекце па распрацоўцы SDS (Software Defined Storage). Ёсць асобны артыкул на гэтую тэму Як наламаць ровараў па-над мыліцамі пры тэставанні свайго дыстрыбутыва, Але калі коратка, то ў нас атрымалася перавернутая піраміда тэсціравання і тэсціраванне мы марнавалі 60-90 хвілін на адну ролю, што ёсць доўга. Аснова была e2e тэсты, г.зн. мы разгортвалі паўнавартасную ўсталёўку, і потым яе тэставалі. Яшчэ абцяжваючым было вынаходства свайго ровара. Але гэтае рашэнне працавала і дазваляла стабільна рэлізавацца.
Дзень № -701: Ansible і test kitchen
Развіццём ідэі тэставання Ansible стала выкарыстанне гатовых прылад, а менавіта test kitchen/kitchen-ci і inspec. Выбар быў абумоўлены веданнем Ruby ( падрабязней у артыкуле на хабры: Ці мараць YML праграмісты аб тэсціраванні ansible?) працавала хутчэй каля 40 хвілін на 10 роляў. Мы стваралі пачак віртуальных машын і ўсярэдзіне ганялі тэсты.
У цэлым рашэнне працавала, але быў асадачак з-за неаднароднасці. Калі ж павялічылі колькасць тэстоўваных да 13 базавых роляў і 2 мета роляў камбінуючыя драбнейшыя ролі, то раптам тэсты сталі бегчы 70 хвілін, што амаль у 2 разы даўжэй. Аб XP (extreme programming) практыках было складана казаць т.к. ніхто не захоча чакаць 70 хвілін. Гэта стала падставай для змены падыходу
Дзень № -601: Ansible і molecule
Канцэптуальна гэта падобна на testkitchen, толькі мы перавялі тэсціраванне роляў у docker і змянілі стэк. Вынікам, час скарацілася да стабільных 20-25 хвілін для 7 роляў.
Павялічыўшы колькасць тэстырумых роляў да 17 і лінтоўку 45 роляў мы праганялі гэта за 28 хвілін на 2 jenkins slave.
Дзень № 167: Дадаем на праект тэсты Ansible
З наскоку задачу рэфактарынгу, хутчэй за ўсё зрабіць не атрымаецца. Задача павінна быць вымерна, што б вы маглі яе разбіць на дробныя кавалачкі і з'есці слана па частках чайнай лыжкай. Павінна быць разуменне ў ці правільным вы кірунку ідзе рух, ці доўга яшчэ ісці.
У цэлым не іста важна як гэта будзе зроблена, можна пісаць на паперку, можна ляпіць стыкеры на шафу, можна ствараць цягі ў jira, а можна завесці google docs І туды запісваць бягучы статут. Ногі растуць з таго, што працэс не імгненны, ён будзе доўгі і нудны. Малаверагодна, што нехта хоча, каб за час рэфактарынгу вы перагарэлі ідэй, стаміліся і забілі.
Рэфакторынг просты:
Ешце.
Sleep.
Кодэкс.
IaC test.
Паўтараць
і так паўтараем пакуль не дасягнем вызначанай мэты.
Усё адразу пачаць тэставаць можа не атрымаецца, таму ў нас першай задачай было пачаць з лінтоўкі і праверкі сінтаксісу.
Дзень №181: Green Build Master
Лінтоўка гэта невялікі першы крок да Green Build Master. Гэта амаль нічога не зламае, але дазволіць адладзіць працэсы і зрабіць зялёненькія білды ў jenkins. Ідэя ў тым, каб выпрацаваць звычкі ў каманды:
Чырвоныя тэсты дрэнна.
Прыйшоў выправіць нешта заадно зрабі код крыху лепш, чым ён быў да цябе.
Дзень № 193: Ад лінтоўкі да unit тэстаў
Выбудаваўшы працэс траплення кода ў майстар можна пачынаць працэс паэтапнага паляпшэння - замяняючы лінтоўку на запуск роляў, можна нават без ідэмпатэнтнасці. Неабходна зразумець як прымяняць ролі, як яны працуюць.
Дзень № 211: Ад unit да integration тэстам
Калі unit тэстамі пакрыта большасць роляў і ўсё лінтуецца, можна пераходзіць да дадання інтэграцыйных тэстаў. Г.зн. тэсціраванню не асобнай цаглінкі ў інфраструктуры, а іх камбінацыі, напрыклад паўнавартасную канфігурацыю інстанса.
На jenkins мы генеравалі мноства стадый, якія ў паралель лінтавалі ролі / плэйбукі, потым юніт тэсты ў кантэйнерах і ў канцы інтэграцыйныя тэсты.
Jenkins + Docker + Ansible = Tests
Checkout repo and generate build stages.
Run lint playbook stages in parallel.
Run lint role stages in parallel.
Run syntax check role stages in parallel.
Run test role stages in parallel.
Lint role.
Check dependency on other roles.
Check syntax.
Create docker instance
Run molecule/default/playbook.yml.
Check idempotency.
Run integration tests
Заканчэнне
Дзень № 271: Bus Factor
Першым часам рэфактарынгам займалася невялікая група людзей у пару-тройку чалавек. Яны рабілі рэўю кода ў майстры. З часам у камандзе выпрацавалася веданне як пісаць код і code review спрыяла распаўсюджванню ведаў аб інфраструктуры і тым як яна ўладкована. Разыначкай тут было, што рэўюверы выбіраліся па чарзе, па графіку, г.зн. з некаторай доляй верагоднасці ты залезеш у новы ўчастак інфраструктуры.
І тут мусіць быць зручна. Зручна рабіць рэўю, бачыць у рамках якой задачы яно зроблена, гісторыю абмеркаванняў. Мы інтэгравалі jenkins + bitbucket + jira.
Але як такое рэўю не панацэя, неяк, у нас пралез у майстар код, які зрабіў нам якія пляпаюць тэсты:
З хлуснем тэстаў рабілася больш, білды беглі павольней да гадзіны ў дрэнным выпадку. На адным з рэтра была фраза па тыпе "добра, што ёсць тэсты, але яны павольныя". У выніку мы адмовіліся ад інтэграцыйных тэстаў на віртуальных машынах і адаптавалі пад docker, каб было хутчэй. Гэтак жа замянілі testinfra на ansible verifier што б паменшыць кол-ць выкарыстоўваных прылад.
Строга кажучы тут быў комплекс мер:
Пераход на docker.
Прыбраць тэсціраванне роляў, якое дублюецца за кошт залежнасцяў.
Павялічыць кол-ць слэйваў.
Парадак запуску тэстаў.
Магчымасць лінтаваць УСЕ лакальна адной камандай.
У выніку Pipeline на jenkins таксама ўніфікаваўся
Generate build stages.
Lint all in parallel.
Run test role stages in parallel.
Гатова.
Урокі, вынятыя
Пазбягайце глабальных зменных
Ansible выкарыстоўвае глабальныя зменныя, есць частковы workaround ў выглядзе private_role_vars, Але гэта не панацэя.
Пацешная рэч, што вынік працы плэйбукаў будзе залежаць ад не заўсёды відавочных рэчаў, напрыклад чарговасці пераліку роляў. Нажаль гэта ў натуры 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
Avoid hashes slovies, use flat structure
Калі роля чакае hash/dictionary у адным з параметраў, то калі мы захочам паправіць адзін з даччыных параметраў, нам трэба будзе перавызначаць увесь hash/dictionary, што падвысіць складанасць канфігуравання.
Ролі і плэйбукі павінны быць ідэмпатэнтнымі, т.я. памяншае configuration drift і страх зламаць нешта. Але калі вы карыстаецеся molecule, тыя гэтыя паводзіны па змаўчанні.
Avoid using command shell modules
Выкарыстанне shell модуля прыводзіць да імператыўнай парадыгме апісання, замест дэкларатыўнай, якая з'яўляецца асноўнай Ansible.
Test your roles via molecule
Molecule дазваляе вельмі гнуткая штука, давай паглядзім некалькі сцэнарыяў.
Molecule Multiple instances
В molecule.yml у секцыі platforms можна апісаць мноства хастоў якія разгортваць.
У molecule ёсць магчымасць выкарыстоўваць ansible Для праверкі таго, што інстанс быў наладжаны правільна, нават гэта па змаўчанні з 3 рэлізу. Гэта не так гнутка як testinfra/inspec, але можна правяраць, што змесціва файла адпавядае нашым чаканням:
Або разгарнуць сэрвіс, дачакацца яго даступнасці і зрабіць smoke test:
---
- 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
Put complex logic у modules & plugins
Ansible прапаведуе дэкларатыўны падыход, таму калі вы робіце галінаванне кода, трансфармацыю дадзеных, shell модулі, то код становіцца складана чытаным. Каб змагацца з гэтым і пакінуць яго простым для разумення, не будзе лішнім, змагацца з гэтай складанасцю шляхам стварэння сваіх модуляў.
Summarize Tips & Tricks
Avoid Global Variables.
Prefix role variables.
Use loop control variable.
Check input variables.
Avoid hashes dictionaries, use flat structure.
Create idempotent playbooks & roles.
Avoid using command shell modules.
Test your roles via molecule.
Put complex logic у modules & plugins.
Заключэнне
Нельга проста так узяць і адрэфактарыць інфраструктуру на праекце, нават калі ў вас IaC. Гэта доўгі працэс, які патрабуе цярпення, часу і ведаў.
UPD1 2020.05.01 20:30 - Для першаснага прафілявання плэйбукаў можна выкарыстоўваць callback_whitelist = profile_tasks што б зразумець, што менавіта доўга працуе. Пасля чаго праходзімся па класіцы паскарэння ansible. Можна паспрабаваць mitogen UPD2 2020.05.03 16:34 - ангельская версія