Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

падыход IaC (Infrastructure as Code) складаецца не толькі з кода, які захоўваецца ў рэпазітары, але яшчэ людзей і працэсаў, якія гэты код атачаюць. Ці можна перавыкарыстоўваць падыходы з распрацоўкі ПЗ ва ўпраўленне і апісанне інфраструктуры? Будзе не лішнім памятаць гэтую ідэю, пакуль будзеце чытаць артыкул.

ангельская версія

Гэта расшыфроўка майго выступы на DevopsConf 2019-05-28.

Slides and videos

Infrastructure as bash history

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Дапусцім прыходзьце вы на новы праект, а вам кажуць: «у нас Інфраструктура як кодэкс“. У рэальнасці аказваецца, Infrastructure as bash history ці напрыклад Documentation as bash history. Гэта цалкам рэальная сітуацыя, напрыклад, падобны выпадак апісваў Дзяніс Лысенка ў выступ Як замяніць усю інфраструктуру і пачаць спаць спакойна, Ён распавёў як з bash history яны атрымалі зграбную інфраструктуру на праекце.

Пры некаторым жаданне, можна сказаць, што Infrastructure as bash history гэта як код:

  1. ўзнаўляльнасць: вы можаце ўзяць bash history, выканаць каманды адтуль, магчыма, дарэчы, вы атрымаеце працоўную канфігурацыю на выхадзе.
  2. версіяванне: вы ведаеце хто заходзіў і што рабіў, зноў жа не факт, што гэта вас прывядзе да працоўнай канфігурацыі на выхадзе.
  3. гісторыя: гісторыя хто і што зрабіў. толькі вы не зможаце ёй карыстацца, калі страціце сервер.

Што ж рабіць?

Інфраструктура як кодэкс

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Нават такі дзіўны выпадак як Infrastructure as bash history можна прыцягнуць за вушы да Інфраструктура як кодэкс, Але калі мы захочам зрабіць што-небудзь больш складанае, чым стары добры LAMPавы сервер, мы прыйдзем да таго, што гэты код неабходна неяк мадыфікаваць, змяняць, дапрацоўваць. Далей хацелася мы будзем разглядаць паралелі паміж Інфраструктура як кодэкс і распрацоўкай ПЗ.

DRY

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

На праекце па распрацоўцы СГД, была падзадача перыядычна наладжваць SDS: выпускаем новы рэліз - яго неабходна раскатаць, для далейшага тэсціравання. Задача лімітава простая:

  • сюды зайдзі па ssh і выканай каманду.
  • туды скапіюй файлік.
  • тут падпраў канфіг.
  • там запусці сэрвіс
  • ...
  • PROFIT!

Для апісанай логікі больш за досыць bash, асабліва на ранніх стадыях праекту, калі ён толькі стартуе. Гэта не дрэнна што вы карыстаецеся bash, Але з часам з'яўляюцца запыты разгарнуць нешта падобнае, але крыху адрозныя. Першае, што прыходзіць у галаву: copy-paste. І вось у нас ужо два вельмі падобныя скрыпты, якія робяць амаль тое ж самае. З часам колькасць скрыптоў вырасла, і мы сутыкнуліся з тым, што ёсць нейкая бізнэс логіка разгортвання інсталяцыі, якую неабходна сінхранізаваць паміж рознымі скрыптамі, гэта досыць складана.

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Аказваецца, ёсць такая практыка DRY (Do not Repeat Yourself). Ідэя ў тым, каб перавыкарыстоўваць існуючы код. Гучыць проста, але дашлі да гэтага не адразу. У нашым выпадку гэта была банальная ідэя: адлучыць канфігі ад скрыптоў. Г.зн. бізнес логіка як разгортваецца інсталяцыя асобна, канфігі асобна.

SOLID for CFM

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

З часам праект рос і натуральным працягам стала з'яўленне Ansible. Асноўная прычына з'яўлення яго - гэта наяўнасць экспертызы ў камандзе і што bash не прызначаны для складанай логікі. Ansible таксама стаў змяшчаць складаную логіку. Для таго каб складаная логіка не ператваралася ў хаос, у распрацоўцы ПА існуюць прынцыпы арганізацыі кода SOLID Гэтак жа, напрыклад, Рыгора Пятроў у дакладзе «Навошта айцішніку асабісты брэнд» закрануў пытанне, што чалавек, так уладкованы, што яму прасцей апераваць нейкімі сацыяльнымі сутнасцямі, у распрацоўцы ПА гэта аб'екты. Калі аб'яднаць гэтыя дзве ідэі працягнуць развіваць іх, то можна заўважыць, што ў апісанні інфраструктуры таксама можна выкарыстоўваць SOLID што б у далейшым было прасцей падтрымліваць і мадыфікаваць гэтую логіку.

The Single Responsibility Principle

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Кожны клас выконвае толькі адну задачу.

Не трэба змешваць код і рабіць маналітныя боскія макаронныя монстры. Інфраструктура павінна складацца з простых цаглінак. Аказваецца, што калі раздрабніць Ansible playbook на невялікія кавалачкі, чытай Ansible ролі, то іх прасцей падтрымліваць.

The Open Closed Principle

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Прынцып адкрытасці/закрытасці.

  • Адкрыты для пашырэння: азначае, што паводзіны сутнасці могуць быць пашыраныя шляхам стварэння новых тыпаў сутнасцяў.
  • Зачыненыя для змены: у выніку пашырэння паводзін сутнасці, не павінны ўносіцца змены ў код, які гэтыя сутнасці выкарыстоўвае.

Першапачаткова мы разгортвалі тэставую інфраструктуру на віртуальных машынах, але за рахунак таго, што бізнэс логіка разгортвання была асобна ад рэалізацыі, мы без праблем дадалі раскочванне на baremetall.

The Liskov Substitution Principle

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Прынцып падстаноўкі Барбары Ліскаў. аб'екты ў праграме павінны быць заменнымі на асобнікі іх падтыпаў без змены правільнасці выканання праграмы

Калі паглядзець шырэй, то не асаблівасць нейкага канкрэтнага праекту, што там можна ўжыць SOLID, яно ў цэлым пра CFM, напрыклад, на іншым праекце неабходна разгортваць скрыначны Java дадатак па-над рознымі Java, сервераў прыкладанняў, баз дадзеных, OS, ітд. На гэтым прыкладзе я буду разглядаць далейшыя прынцыпы. SOLID

У нашым выпадку ў рамках інфраструктурнай каманды ёсць дамоўленасць, што калі мы ўсталявалі ролю imbjava ці oraclejava, то ў нас ёсць бінарны выканальны файл java. Гэта неабходна т.к. вышэйстаячае ролі залежаць ад гэтых паводзін, яны чакаюць наяўнасць java. У той жа час гэта нам дазваляе замяняць адну рэалізацыю/версію java на іншую пры гэтым не змяняючы логіку разгортвання прыкладання.

Праблема тут крыецца ў тым, што ў Ansible нельга рэалізаваць такое, як следства ў рамках каманды з'яўляюцца нейкія дамоўленасці.

The Interface Segregation Principle

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Прынцып падзелу інтэрфейсу «шмат інтэрфейсаў, спецыяльна прызначаных для кліентаў, лепш, чым адзін інтэрфейс агульнага прызначэння.

Першапачаткова мы спрабавалі складаць усю варыятыўнасць разгортвання прыкладання ў адзін Ansible playbook, але гэта было складана падтрымліваць, а падыход, калі ў нас спецыфікаваны інтэрфейс вонкі (кліент чакае 443 порт) то пад пэўную рэалізацыю можна кампанаваць інфраструктуру з асобных цаглін.

The Dependency Inversion Principle

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Прынцып інверсіі залежнасцяў. Модулі верхніх узроўняў не павінны залежаць ад модуляў ніжніх узроўняў. Абодва тыпу модуляў павінны залежаць ад абстракцый. Абстракцыі не павінны залежаць ад дэталяў. Дэталі павінны залежаць ад абстракцый.

Тут прыклад будзе заснаваны на антыпатэрне.

  1. У аднаго з замоўцаў было прыватнае воблака.
  2. Унутры аблокі мы заказвалі віртуальныя машыны.
  3. Але ў выглядзе асаблівасцяў аблокі, разгортванне прыкладання было прывязана да таго, на які гіпервізор патрапіла ВМ.

Г.зн. высокаўзроўневая логіка разгортвання прыкладання, залежнасцямі працякала на ніжэйлеглыя ўзроўні гіпервізара, і гэта азначала праблемы пры перавыкарыстанне гэтай логікі. Ня трэба так.

Узаемадзеянне

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Інфраструктура як код - гэта не толькі пра код, але яшчэ і пра адносіны паміж кодам і чалавекам, пра ўзаемадзеяння паміж распрацоўшчыкамі інфраструктуры.

Bus factor

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Дапусцім, што ў вас на праекце ёсць Вася. Вася ўсё ведае пра вашу інфраструктуру, што будзе, калі Вася раптам знікне? Гэта цалкам рэальная сітуацыя, бо яго можа збіць аўтобус. Часам такое здараецца. Калі такое здарыцца і веданне аб кодзе, яго структуры, як ён працуе, яўках і паролях, не размеркаваны ў камандзе, то можна сутыкнуцца з шэрагам непрыемных сітуацый. Каб мінімізаваць гэтыя рызыкі і размеркаваць веды ў рамках каманды можна выкарыстоўваць розныя падыходы

Pair Devopsing

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Гэта не як жартам, Што адміны пілі піва, паролі мянялі, а аналаг парнага праграмавання. Г.зн. два інжынеры садзяцца за адзін кампутар, адну клавіятуру і пачынаюць разам наладжваць вашу інфраструктуру: сервер наладжваць, Ansible ролю пісаць, ітд. Гучыць хораша, але ў нас не спрацавала. Але вось прыватныя выпадкі гэтай практыкі працавалі. Прыйшоў новы супрацоўнік, яго настаўнік разам з ім бярэ рэальную задачу, працуе - перадае веданне.

Іншы прыватны выпадак, гэта incident call. Падчас праблемы збіраецца група дзяжурных і датычных, прызначаецца адзін вядучы, які расшорвае свой экран і агучвае ход думкі. Іншыя ўдзельнікі ідуць за думкай вядучага, падглядваюць трукі з кансолі, правяраюць што не прапусціў радок у логу, даведаюцца новае аб сістэме. Такі падыход хутчэй працаваў, чым не.

Агляд кода

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Суб'ектыўна, больш эфектыўна распаўсюджванне ведаў аб інфраструктуры і тым як яна ўладкованая праходзіла пры дапамозе code review:

  • Інфраструктура апісана кодам у рэпазітары.
  • Змены адбываюцца ў асобнай галінцы.
  • Пры мерджы рэквест можна ўбачыць дэльту змяненняў інфраструктуру.

Разыначкай тут было, што рэўюверы выбіраліся па чарзе, па графіку, г.зн. з некаторай доляй верагоднасці ты залезеш у новы ўчастак інфраструктуры.

Стыль кода

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

З часам сталі з'яўляцца звады падчас рэўю, т.к. у ревьюверов быў свой стыль і ратаванасці ревьюверов стыкавала іх з рознымі стылямі: 2 прабела ці 4, camelCase ці snake_case. Укараніць гэта атрымалася не адразу.

  • Першай ідэй было рэкамендацыйна параіць выкарыстоўваць linter, бо ўсё ж інжынеры, усе разумныя. Але розныя рэдактары, АС, не зручна
  • Гэта эвалюцыянавала ў робата, які па кожным праблеме праблему пісаў у slack, і прыкладваў выснову linter. Але ў большасці выпадкаў знаходзіліся важнейшыя справы і код заставаўся не выпраўленым.

Green Build Master

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Час ідзе, і прыйшлі да таго, што нельга пускаць у майстар коміты, якія не праходзяць нейкія тэсты. Вуаля! мы вынайшлі Green Build Master які ўжо даўным-даўно практыкуецца ў распрацоўцы ПЗ:

  • Распрацоўка ідзе ў асобнай галінцы.
  • Па гэтай галінцы ганяюцца тэсты.
  • Калі тэсты не праходзяць, то код не патрапіць у майстар.

Прыняцце гэтага рашэння было вельмі балючым, т.я. выклікала мноства спрэчак, але яно таго каштавала, т.я. на раўью сталі прыходзіць запыты на зліццё без рознагалоссяў па стылі і з часам кол-у праблемных месцаў стала памяншацца.

IaC Testing

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Акрамя праверкі стылю можна выкарыстоўваць і іншыя рэчы, напрыклад, правяраць, што ваша інфраструктура сапраўды можа разгарнуцца. Або правяраць, што змены ў інфраструктуры не прывядуць да страты грошай. Нашто гэта можа спатрэбіцца? Пытанне складанае і філасофскае, адказаць лепш байкай, што неяк быў auto-scaler на Powershell які, не правяраў памежныя ўмовы => стварылася больш ВМ чым трэба => кліент выдаткаваў грошай больш чым планаваў. Прыемнага мала, але гэтую памылку цалкам рэальна было б адлавіць на больш ранніх стадыях.

Можна спытаць, а навошта рабіць складаную інфраструктуру яшчэ больш складана? Тэсты для інфраструктуры, гэтак жа, як і для кода, гэта не пра спрашчэнне, а пра веданне як ваша інфраструктура павінна працаваць.

IaC Testing Pyramid

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

IaC Testing: Static Analysis

Калі адразу разгортваць усю інфраструктуру і правяраць, што яна працуе, тое можа апынуцца, што гэта займае плойму часу і патрабуе кучу часу. Таму ў аснове павінна быць нешта хутка якое працуе, яго шмат, і яно пакрываюць мноства прымтыўных месцаў.

Bash is tricky

Вось разгледзім банальны прыклад. выбраць усе файлы ў бягучай дырэкторыі і скапіяваць у іншае месца. Першае што прыходзіць у галаву:

for i in * ; do 
    cp $i /some/path/$i.bak
done

А што калі ў імені файла прабел ёсць? Ну ок, мы ж разумныя, умеем карыстацца двукоссямі:

for i in * ; do cp "$i" "/some/path/$i.bak" ; done

Малайцы? не! Што калі ў дырэкторыі няма нічога, г.зн. глобінг не спрацуе.

find . -type f -exec mv -v {} dst/{}.bak ;

Цяпер то малайцы? неа… Забыліся што ў імені файла можа быць n.

touch x
mv x  "$(printf "foonbar")"
find . -type f -print0 | xargs -0 mv -t /path/to/target-dir

Static analysis tools

Праблему з папярэдняга кроку можна было адлавіць калі мы забыліся двукоссі, для гэтага ў прыродзе існуе мноства сродак Shellcheck, наогул іх шмат, і хутчэй за ўсё вы зможаце знайсці пад сваю IDE лінтэр для вашага стэка.

мова
Інструмент

біць
Shellcheck

лал
RuboCop

пітон
Пілінт

адказны
Ansible Lint

IaC Testing: Unit Tests

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Як мы пераканаліся з папярэдняга прыкладу, лінтэры не ўсемагутныя і не могуць паказаць на ўсе праблемныя месцы. Далей па аналогіі з тэставаннем у распрацоўцы ПЗ можна ўспомніць пра unit tests. Тут адразу на розум прыходзяць shunit, джуніт, rspec, пітэст. Але што рабіць з ansible, chef, saltstack і што з імі?

У самым пачатку мы казалі пра SOLID і тое, што наша інфраструктура павінна складацца з маленькіх цаглінак. Нетутэйша іх час.

  1. Інфраструктура дробніцца на невялікія цаглінкі, да прыкладу, Ansible ролі.
  2. Разгортваецца нейкае асяроддзе, няхай гэта будзе docker або ВМ.
  3. На гэта тэставае асяроддзе ўжываем нашу Ansible роля.
  4. Правяраем што ўсё адпрацавала як мы чакаем (праганяем тэсты).
  5. Вырашаем ок ці не ок.

IaC Testing: Unit Testing tools

Пытанне, а што такое тэсты для CFM? можна банальна запускаць скрыпт, а можна выкарыстоўваць гатовыя рашэнні для гэтага:

CFM
Інструмент

анзибль
Testinfra

Шэф-повар
інспекцыя

Шэф-повар
Serverspec

саляная кладка
Гос

Прыклад для testinfra, правяраем што карыстачы test1, test2 існуюць і складаюцца ў групе sshusers:

def test_default_users(host):
    users = ['test1', 'test2' ]
    for login in users:
        assert host.user(login).exists
        assert 'sshusers' in host.user(login).groups

Што абраць? пытанне складанае і не адназначнае, вось прыклад змены ў праектах на github за 2018-2019 гады:

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

IaC Testing frameworks

Узнікае як гэта ўсё сабраць разам і запусціць? Можна узяць і зрабіць усё самому пры наяўнасці дастатковай кол-ць інжынераў. А можна ўзяць гатовыя рашэнні, праўда іх не вельмі і шмат:

CFM
Інструмент

анзибль
малекула

Шэф-повар
Тэставая кухня

Terraform
Terratest

Прыклад змены ў праектах на github за 2018-2019 гады:

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Molecule vs. Testkitchen

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Першапачаткова мы спрабавалі выкарыстоўваць testkitchen:

  1. Стварыць ВМ у паралель.
  2. Ужыць Ansible ролі.
  3. Праганяць inspec.

Для 25-35 роляў гэта працавала 40-70 хвілін, што было доўга.

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Наступным крокам стаў пераход на jenkins/docker/ansible/molecule. Ідыялагічна ўсё тое самае

  1. Пралінтаваць плэйбукі.
  2. Пралінтаваць ролі.
  3. Запусціць кантэйнер
  4. Ужыць Ansible ролі.
  5. Праганяць testinfra.
  6. Праверыць ідэмпатэнтнасць.

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Лінтоўка для 40 роляў і тэсты для дзясятка сталі займаць каля 15 хвілін.

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Што абраць залежыць ад мноства фактараў, як тое выкарыстоўваны стэк, экспертыза ў камандзе ітд. тут кожны вырашае сам як закрываць пытанне Unit тэсціравання

IaC Testing: Integration Tests

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

На наступнай прыступцы піраміды тэсціравання інфраструктуры з'яўляюцца інтэграцыйныя тэсты. Яны падобныя на Unit тэсты:

  1. Інфраструктура дробніцца на невялікія цаглінкі, да прыкладу Ansible ролі.
  2. Разгортваецца нейкае асяроддзе, няхай гэта будзе docker або ВМ.
  3. На гэта тэставае асяроддзе прымяняецца мноства Ansible роляў.
  4. Правяраем што ўсё адпрацавала як мы чакаем (праганяем тэсты).
  5. Вырашаем ок ці не ок.

Грубіянска кажучы, мы не правяраем працаздольнасць асобнага элемента сістэмы як у unit тэстах, мы правяраем як сервер сканфігураваны ў цэлым.

IaC Testing: Завяршыце тэставанне

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

На вяршыні піраміды нас сустракаюць End to End тэсты. Г.зн. мы не правяраем працаздольнасць асобнага сервера, асобнага скрыпту, асобнай цаглінкі нашай інфраструктуры. Мы правяраем што мноства сервераў, аб'яднаных разам, наша інфраструктура працуе, як мы гэтага чакаем. Нажаль гатовых скрыначных рашэнняў, мне не даводзілася бачыць, мусіць т.к. інфраструктура за частую ўнікальная і яе складана шаблонізаваць і зрабіць фрэймворк для яе тэставання. Як вынік усё ствараюць свае ўласныя рашэнні. Попыт ёсць, а вось адказу няма. Таму, раскажу што ёсць, каб наштурхнуць іншых на разумныя думкі або ткнуць мяне носам, што ўсё даўно вынайдзена да нас.

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Праект з багатай гісторыяй. Выкарыстоўваецца ў вялікіх арганізацыях і верагодна кожны з вас ускосна перасякаўся. Прыкладанне падтрымлівае мноства баз дадзеных, інтэграцый ітд ітп. Веды пра тое, як інфраструктура можа выглядаць гэтае мноства docker-compose файлаў, а веданне таго, якія тэсты ў якім асяроддзе запускаць — гэта jenkins.

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Гэтая схема дастаткова доўга працавала, пакуль у рамках даследаванні мы не паспрабавалі гэта перанесці ў Openshift. Кантэйнеры засталіся таксама, а вось асяроддзе запуску змянілася (прывітанне DRY зноў).

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Думка даследавання пайшла далей, і ў openshift знайшлася такая штука APB (Ansible Playbook Bundle), якая дазваляе ў кантэйнер запакаваць веданне як разгортваць інфраструктуру. Г.зн. ёсць прайграваная, якая тэстуецца кропка веды, як разгарнуць інфраструктуру.

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Усё гэта гучала добра, пакуль не уткнуліся ў гетэрагенную інфраструктуру: нам для тэстаў патрэбна Windows. У выніку веданне аб тым што, дзе як разгарнуць, і пратэставаць сядзіць у jenkins.

заключэнне

Што я даведаўся, пратэставаўшы 200 000 радкоў інфраструктурнага кода

Infrastructure as Code гэта

  • Код у рэпазітары.
  • Узаемадзеянне людзей.
  • Тэсціраванне інфраструктуры.

сувязі

Крыніца: habr.com

Дадаць каментар