Какво узнах, тествал 200 000 реда инфраструктурен код

Какво узнах, тествал 200 000 реда инфраструктурен код

Подход IaC (Infrastructure as Code) се състои не само от кода, който се съхранява в репозитория, но и от хората и процесите, които обгръщат този код. Може ли да се повторят подходите от разработката на софтуер в управлението и описанието на инфраструктурата? Няма да е ненужно да запомните тази идея, докато четете статията.

English version

Това е разшифровката на моя изказването на DevopsConf 2019-05-28.

Слайдове и видеа

Инфраструктура като bash history

Какво узнах, тествал 200 000 реда инфраструктурен код

Предположим, че идвате на нов проект, а ви казват: «имаме Инфраструктура като код«. В действителност се оказва, Инфраструктура като bash history или например Документация като bash history. Това е напълно реална ситуация, например, подобен случай описваше Денис Лисенко в своето изказване Как да заменим цялата инфраструктура и да започнем да спим спокойно, той разказа как от bash history са получили стройна инфраструктура в проекта.

При известно желание, може да се каже, че Инфраструктура като bash history это как код:

  1. възпроизводимост: можете да вземете bash history, да изпълните командите оттам, възможно е, между другото, да получите работна конфигурация на изхода.
  2. версиониране: знаете кой е влизал и какво е правил, пак не е факт, че това ще ви доведе до работна конфигурация на изхода.
  3. история: история кой и какво е направил. само не можете да я използвате, ако загубите сървъра.

Какво да правим?

Инфраструктура като код

Какво узнах, тествал 200 000 реда инфраструктурен код

Дори и този странен случай като Инфраструктура като bash history може да се свърже с Инфраструктура като код, но когато искаме да направим нещо по-сложно от стария добър LAMP сървър, ще стигнем до това, че този код трябва да се модифицира по някакъв начин, да се променя, да се доработва. По-нататък ще разглеждаме паралелите между Инфраструктура като код и разработката на софтуер.

D.R.Y.

Какво узнах, тествал 200 000 реда инфраструктурен код

В проекта за разработка на СХД, имаше подзадача периодично да конфигурираме SDS: издаваме нов релиз — необходимо е да го развъртим за по-нататъшно тестване. Задачата е напълно проста:

  • влез тук по ssh и изпълни командата.
  • скопирай файла там.
  • направи конфигурацията тук.
  • стартни услугата там
  • …
  • ПЕЧАЛБА!

За описаната логика е повече от достатъчно bash, особено в ранните етапи на проекта, когато той току-що стартира. Това не е зле, че използвате bash, но с времето се появяват заявки да се разшири нещо подобно, но леко различаващо се. Първото, което идва на ум: копиране и поставяне. И ето, вече имаме два много подобни скрипта, които почти вършат същото. С времето количеството на скриптовете нарасна и се сблъскахме с факта, че съществува определена бизнес логика за разгръщане на инсталацията, която трябва да се синхронизира между различни скриптове, което е доста сложно.

Какво узнах, тествал 200 000 реда инфраструктурен код

Оказва се, че съществува такава практика D.R.Y. (Не повтаряй себе си). Идеята е да се преизползва съществуващия код. Звучи просто, но не стигнахме до това веднага. В нашия случай това беше банална идея: да отделим конфигурациите от скриптовете. Т.е. бизнес логиката как се разгръща инсталацията отделно, конфигурациите отделно.

S.O.L.I.D. за CFM

Какво узнах, тествал 200 000 реда инфраструктурен код

С времето проектът растеше и естественото продължение стана появата на Ansible. Основната причина за неговото поява е наличието на експертиза в екипа и фактът, че bash не е предназначен за сложна логика. Ansible също започна да съдържа сложна логика. За да не се превръща сложната логика в хаос, в разработката на софтуер съществуват принципи за организация на кода. S.O.L.I.D. Също така, например, Григорий Петров в доклада „Защо на IT специалиста му е нужен личен бранд“ засегна въпроса, че човек, по природа, му е по-лесно да оперира с някакви социални единици, в разработката на софтуер това са обекти. Ако обединим тези две идеи и продължим да ги развиваме, можем да забележим, че в описанието на инфраструктурата също може да се използва S.O.L.I.D. за да бъде по-лесно в бъдеще да се поддържа и модифицира тази логика.

Принципът за единствена отговорност

Какво узнах, тествал 200 000 реда инфраструктурен код

Всеки клас изпълнява само една задача.

Не трябва да смесваме код и да правим монолитни божествени макарони-удвоявачи. Инфраструктурата трябва да се състои от прости тухли. Оказва се, че ако разчленим Ansible playbook на малки парчета, т.е. Ansible роли, те са по-лесни за поддръжка.

Принципът за отвореност/затвореност.

Какво узнах, тествал 200 000 реда инфраструктурен код

Отворени за разширение: означава, че поведението на единицата може да бъде разширено чрез създаване на нови типове единици.

  • Затворени за промяна: в резултат на разширяване на поведението на единицата, не трябва да се внасят промени в кода, който използва тези единици.
  • Затворени за промяна: в резултат на разширяване на поведението на сущността, не трябва да се внасят промени в кода, който използва тези сущности.

Първоначално разгръщахме тестова инфраструктура на виртуални машини, но тъй като бизнес логиката за разгръщане беше отделена от реализацията, без проблем добавихме разгръщането на bare metal.

Принцип на подмяна на Лисков

Какво узнах, тествал 200 000 реда инфраструктурен код

Принципът на подмяна на Барбара Лисков. Обектите в програмата трябва да могат да бъдат заменени с екземпляри на техните подтипове, без да се променя правилността на изпълнението на програмата.

Ако погледнем по-широко, не е особеност само на конкретен проект, че там може да се приложи. S.O.L.I.D., става въпрос за CFM, например, в друг проект е необходимо да се разгръща стандартно Java приложение над различни Java, сървъри на приложения, бази данни, операционни системи и т.н. На този пример ще разглеждам по-нататъшните принципи. S.O.L.I.D.

В нашия случай в рамките на инфраструктурния екип има уговорка, че ако инсталираме ролята imbjava или oraclejava, то имаме бинарен изпълняем файл java. Това е необходимо, тъй като по-висшите роли зависят от това поведение, те очакват наличието на java. В същото време това ни позволява да заменяме една реализация/версия на java с друга, без да променяме логиката на разгръщане на приложението.

Проблемът тук е, че в Ansible не може да се реализира такова, което води до появата на определени уговорки в екипа.

Принцип на разделяне на интерфейса

Какво узнах, тествал 200 000 реда инфраструктурен код

Принципът на разделяне на интерфейса: „много интерфейси, специално проектирани за клиенти, са по-добри от един общ интерфейс.

Първоначално опитвахме да съберем цялата вариативност на разгръщането на приложението в един Ansible playbook, но това беше трудно за поддържане, а подходът, при който имаме специфициран интерфейс навън (клиентът очаква порт 443), ни позволява да сглобим инфраструктурата от отделни блокчета за конкретната реализация.

Принцип на инверсия на зависимостите

Какво узнах, тествал 200 000 реда инфраструктурен код

Принципът на инверсия на зависимостите. Модулите от по-високо ниво не трябва да зависят от модулите от по-ниско ниво. И двата типа модули трябва да зависят от абстракции. Абстракциите не трябва да зависят от детайлите. Детайлите трябва да зависят от абстракциите.

Тук примерът ще се основава на антипатерн.

  1. Един от клиентите имаше частно облако.
  2. В рамките на облака поръчвахме виртуални машини.
  3. Но поради особеностите на облака, разгръщането на приложението беше свързано с това, на кой хипервизор попадна ВМ.

Т.е. високото ниво на логиката за разгръщане на приложението, зависимостите протичаха на по-долните нива на хипервизора, и това означаваше проблеми при повторната употреба на тази логика. Не прави така.

Взаимодействие

Какво узнах, тествал 200 000 реда инфраструктурен код

Инфраструктурата като код не е само за кода, а и за отношенията между кода и човека, за взаимодействията между разработчиците на инфраструктура.

Bus фактор

Какво узнах, тествал 200 000 реда инфраструктурен код

Да предположим, че в проекта ви работи Васил. Васил знае всичко за вашата инфраструктура, какво ще стане, ако той из plötzlich изчезне? Това е напълно реална ситуация, тъй като той може да бъде блъснат от автобус. Понякога това се случва. Ако такова нещо се случи и знанието за кода, неговата структура, как работи, наименованията и паролите не са разпределени в екипа, може да се сблъскате с редица неприятни ситуации. За да минимизирате тези рискове и да разпределите знанието в рамките на екипа, можете да използвате различни подходи.

Двойно Devops-ване

Какво узнах, тествал 200 000 реда инфраструктурен код

Не е като в шегата, за администраторите, които пият бира, сменят пароли, а аналог на парната програмиране. Т.е. двама инженери сядат на един компютър, една клавиатура и започват заедно да настроят вашата инфраструктура: настройка на сървър, написване на Ansible роля и т.н. Звучи добре, но при нас не се получи. Но частни случаи на тази практика проработиха. Нов служител, неговият наставник взема реална задача и работи — предава знанието.

Друг частен случай е инцидентния разговор. По време на проблема се събира екип от дежурни и ангажирани, назначава се един водещ, който споделя екрана си и озвучава мисловния процес. Другите участници следват мисълта на водещия, шпионират трикове от конзолата, проверяват какво не е пропуснато в логовете, научават нови неща за системата. Такъв подход по-скоро работеше, отколкото не.

Code Review

Какво узнах, тествал 200 000 реда инфраструктурен код

Субективно, по-ефективното разпространение на знанията за инфраструктурата и как е организирана, преминаваше чрез code review:

  • Инфраструктурата е описана с код в хранилището.
  • Промените се извършват в отделен клон.
  • При сливане на заявка може да се види дельтата на промените в инфраструктурата.

Изюминката тук беше, че рецензентите се избираха по ред и по график, т.е. с известна вероятност ще влезете в нов участък от инфраструктурата.

Стил на кода

Какво узнах, тествал 200 000 реда инфраструктурен код

С времето се появиха конфликти по време на ревютата, тъй като ревюърите имаха свой собствен стил и ротацията на ревюърите ги сблъскваше с различни стилове: 2 интервала или 4, camelCase или snake_case. Внедряването на това не стана веднага.

  • Първоначалната идея беше да се препоръча използването на linter, все пак инженерите са умни хора. Но различните редактори, операционни системи, това не е удобно.
  • Това еволюира в бот, който по всеки проблемен комит пишеше в Slack и прикачваше изхода от linter. Но в повечето случаи имаше по-важни неща и кодът оставаше неизправен.

Green Build Master

Какво узнах, тествал 200 000 реда инфраструктурен код

Времето минава и стигнахме до заключението, че не можем да допуснем в master комити, които не преминават определени тестове. Ето ни! Придобихме Green Build Master, който отдавна се практикува в разработката на ПО:

  • Разработката става в отделен клон.
  • Тестовете се изпълняват по този клон.
  • Ако тестовете не преминат, кодът няма да попадне в master.

Приемането на това решение беше доста болезнено, тъй като предизвика много спорове, но си заслужаваше, тъй като на ревютата започнаха да идват искания за сливане без разногласия по стил и с времето броят на проблемните места започна да намалява.

IaC Testing

Какво узнах, тествал 200 000 реда инфраструктурен код

Освен проверката на стила, могат да се използват и други неща, например, да проверим дали вашата инфраструктура наистина може да се разрази. Или да проверим, че измененията в инфраструктурата няма да доведат до загуба на пари. Защо е нужно това? Въпросът е сложен и философски, по-добре е да отговорим с басня, че веднъж имало auto-scaler на Powershell, който не е проверил гранични условия => създадени са повече ВМ, отколкото трябва => клиентът е похарчил повече пари, отколкото е планирал. Неприятно е, но тази грешка можеше да бъде заловена на по-ранен етап.

Може да се запитате, защо да правим сложната инфраструктура още по-сложна? Тестовете за инфраструктура, както и за код, не са за опростяване, а за знание как вашата инфраструктура трябва да работи.

IaC Testing Pyramid

Какво узнах, тествал 200 000 реда инфраструктурен код

IaC Testing: Static Analysis

Ако веднага разгръщате цялата инфраструктура и проверявате, че тя работи, може да се окаже, че това отнема много време и изисква куп време. Затова в основата трябва да има нещо бързо работещо, което да е много и да покрива множество примитивни места.

Bash е сложен

Нека да разгледаме един банален пример. да изберем всички файлове в текущата директория и да ги копираме на друго място. Първото, което идва на ум:

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

Инструменти за статичен анализ

Проблемът от предишната стъпка можеше да бъде уловен, когато забравихме кавичките; за това в природата съществуват множество средства Shellcheck, всъщност те са много, и вероятно ще можете да намерите линтер за вашата IDE в зависимост от вашия стек.

Език
Инструмент

bash
Shellcheck

Ruby
RuboCop

python
Pylint

ansible
Ansible Lint

IaC Тестиране: Юнит тестове

Какво узнах, тествал 200 000 реда инфраструктурен код

Както видяхме от предишния пример, линтерите не са всемогъщи и не могат да посочат всички проблемни места. В съответствие с аналогията с тестването на софтуер можем да си спомним за юнит тестовете. Веднага наум идват shunit, junit, rspec, pytest. Но какво да правим с ansible, chef, saltstack и подобни?

В самото начало говорехме за S.O.L.I.D. и че нашата инфраструктура трябва да се състои от малки тухли. Време е за тях.

  1. Инфраструктурата се разбива на малки тухли, например роли на Ansible.
  2. Разгръща се някакво окръжение, било то docker или ВМ.
  3. На това тестово окръжение прилагаме нашата роля на Ansible.
  4. Проверяваме дали всичко е работило, както очакваме (изпълняваме тестовете).
  5. Решаваме дали е ОК или не.

IaC Тестиране: Инструменти за юнит тестване

Въпросът е, какво представляват тестовете за CFM? Може да пуснете скрипт, но можете да използвате и готови решения за това:

CFM
Инструмент

Ansible
Testinfra

Chef
Inspec

Chef
Serverspec

saltstack
Goss

Пример за 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 Тестиране: рамки

Как да сглобим всичко заедно и да го стартираме? Може да вземете и да направите всичко сами при наличие на достатъчно количество инженери. Или можете да вземете готови решения, въпреки че не са много:

CFM
Инструмент

Ansible
Molecule

Chef
Test Kitchen

Terraform
Terratest

Пример за промените в проектите в GitHub за 2018-2019 година:

Какво узнах, тествал 200 000 реда инфраструктурен код

Molecule срещу 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 тестване: Интеграционни тестове.

Какво узнах, тествал 200 000 реда инфраструктурен код

На следващото ниво на пирамидата за тестване на инфраструктурата се появяват интеграционни тестове. Те са подобни на Unit тестовете:

  1. Инфраструктурата се разделя на малки елементи, например Ansible роли.
  2. Разгръща се някакво окръжение, било то docker или ВМ.
  3. Тези тестови среди се прилагат много Ansible роли.
  4. Проверяваме дали всичко е проработило, както очакваме (изпълняваме тестовете).
  5. Решаваме дали е ОК или не.

Грубо казано, не проверяваме работоспособността на отделен елемент на системата, както в unit тестовете, а проверяваме как е конфигуриран сървърът като цяло.

IaC тестване: End to End тестове.

Какво узнах, тествал 200 000 реда инфраструктурен код

На върха на пирамидата ни посрещат End to End тестовете. Т.е. не проверяваме работоспособността на отделен сървър, отделен скрипт, отделен елемент от нашата инфраструктура. Проверяваме дали множество сървъри, свързани заедно, нашата инфраструктура работи, както очакваме. За съжаление не съм виждал готови решения, вероятно защото инфраструктурата често е уникална и е трудно да се шаблонира и направи фреймворк за тестването ѝ. Както и да е, всички създават свои собствени решения. Има търсене, но няма отговор. Затова ще разкажа какво има, за да подтикна другите към разумни идеи или да ми натресат, че всичко е изобретено преди нас.

Какво узнах, тествал 200 000 реда инфраструктурен код

Проект с дълга история. Използва се в големи организации и вероятно всеки от вас е имал косвени срещи с него. Приложението поддържа множество бази данни, интеграции и т.н. Знанието как може да изглежда инфраструктурата включва множество docker-compose файлове, а знанието какви тестове да се пускат в каква среда е jenkins.

Какво узнах, тествал 200 000 реда инфраструктурен код

Тази схема работеше дълго време, докато в рамките на изследване не опитахме да я прехвърлим в Openshift. Контейнерите останаха същите, а средата за изпълнение се промени (привет отново D.R.Y.).

Какво узнах, тествал 200 000 реда инфраструктурен код

Изследването напредна и в OpenShift открихме нещо наречено APB (Ansible Playbook Bundle), което позволява да опаковаме знанията как да разгръщаме инфраструктура в контейнер. Т.е. имаме воспроизводима, тестируема точка на знание как да разгръщаме инфраструктура.

Какво узнах, тествал 200 000 реда инфраструктурен код

Всичко това звучеше добре, докато не се сблъскахме с хетерогенна инфраструктура: за тестовете ни е необходим Windows. В крайна сметка знанието за това какво, къде и как да разгръщаме и тестваме, остава в Jenkins.

Заключение

Какво узнах, тествал 200 000 реда инфраструктурен код

Инфраструктура като код е

  • Код в репозиторий.
  • Взаимодействие между хора.
  • Тестване на инфраструктурата.

линкове

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster