Począwszy od drugiego zatwierdzenia, każdy kod staje się starszy, ponieważ Początkowe pomysły zaczynają odbiegać od twardej rzeczywistości. Nie jest to ani dobre, ani złe, jest to fakt, z którym trudno polemizować i z którym należy żyć. Częścią tego procesu jest refaktoryzacja. Refaktoryzacja infrastruktury jako kodu. Zacznijmy od historii o tym, jak dokonać refaktoryzacji Ansible w ciągu roku i nie zwariować.
Narodziny dziedzictwa
Dzień nr 1: Pacjent Zero
Dawno, dawno temu istniał projekt warunkowy. Miał zespół programistów Dev i inżynierów operacyjnych. Rozwiązywali ten sam problem: jak wdrożyć serwery i uruchomić aplikację. Problem w tym, że każdy zespół rozwiązał ten problem na swój sposób. W projekcie zdecydowano się wykorzystać Ansible do synchronizacji wiedzy pomiędzy zespołami Dev i Ops.
Dzień #89: Narodziny dziedzictwa
Sami tego nie zauważając, chcieli to zrobić jak najlepiej, ale okazało się, że to już dziedzictwo. Jak to się stało?
Mamy tutaj pilne zadanie, zróbmy brudny hack, a potem go naprawmy.
Nie musisz pisać dokumentacji i wszystko jest jasne, co się tutaj dzieje.
Znam Ansible/Python/Bash/Terraform! Zobacz, jak potrafię robić uniki!
Jestem programistą Full Stack Overflow i skopiowałem to z stackoverflow, nie wiem, jak to działa, ale wygląda fajnie i rozwiązuje problem.
W rezultacie można otrzymać niezrozumiały typ kodu, dla którego nie ma dokumentacji, nie jest jasne, co on robi, czy jest potrzebny, ale problem jest taki, że trzeba go rozwinąć, zmodyfikować, dodać kule i podpory , co jeszcze bardziej pogarsza sytuację.
Pierwotnie wymyślony i wdrożony model IaC nie spełnia już wymagań użytkowników/biznesu/innych zespołów, a czas na wprowadzanie zmian w infrastrukturze przestaje być akceptowalny. W tym momencie przychodzi zrozumienie, że nadszedł czas, aby podjąć działania.
Refaktoryzacja IaC
Dzień #139: Czy naprawdę potrzebujesz refaktoryzacji?
Zanim przystąpisz do refaktoryzacji, musisz odpowiedzieć na kilka ważnych pytań:
Dlaczego potrzebujesz tego wszystkiego?
Czy masz czas?
Czy wiedza wystarczy?
Jeśli nie wiesz, jak odpowiedzieć na pytania, refaktoryzacja zakończy się, zanim w ogóle się rozpocznie, lub może się tylko pogorszyć. Ponieważ miał doświadczenie ( Czego nauczyłem się testując 200 000 linii kodu infrastruktury), wówczas projekt otrzymał prośbę o pomoc w naprawieniu ról i objęciu ich testami.
Dzień #149: Przygotowanie refaktoryzacji
Pierwszą rzeczą jest przygotowanie. Zdecyduj, co zrobimy. W tym celu komunikujemy się, znajdujemy obszary problematyczne i znajdujemy sposoby ich rozwiązania. Powstałe koncepcje w jakiś sposób rejestrujemy, np. artykuł w konfluencji, aby w przypadku pojawienia się pytania „co jest najlepsze?” lub „co jest poprawne?” Nie zgubiliśmy drogi. W naszym przypadku trzymaliśmy się pomysłu dziel i rządź: dzielimy infrastrukturę na małe kawałki/cegiełki. Takie podejście pozwala wziąć wyizolowany fragment infrastruktury, zrozumieć, co robi, objąć go testami i zmienić bez obawy, że cokolwiek zepsuje.
Okazuje się, że podstawą jest testowanie infrastruktury i w tym miejscu warto wspomnieć o piramidzie testowania infrastruktury. Dokładnie ten sam pomysł, który jest w fazie rozwoju, ale w przypadku infrastruktury: odchodzimy od tanich szybkich testów, które sprawdzają proste rzeczy, takie jak wcięcia, na rzecz drogich, pełnoprawnych testów, które wdrażają całą infrastrukturę.
Próby testowania Ansible
Zanim przejdę do opisania jak przeszliśmy testy Ansible w projekcie, opiszę próby i podejścia, które miałem okazję wcześniej zastosować, aby zrozumieć kontekst podjętych decyzji.
Dzień nr -997: Dostarczenie karty charakterystyki
Po raz pierwszy testowałem Ansible podczas projektu mającego na celu opracowanie SDS (Software Defined Storage). Jest na ten temat osobny artykuł Jak rozbijać rowery o kule podczas testowania dystrybucji, ale w skrócie skończyło się na odwróconej piramidzie testowania i testowaniu spędziliśmy 60-90 minut na jednej roli, czyli dużo czasu. Podstawą były testy e2e, czyli tzw. wdrożyliśmy pełną instalację, a następnie ją przetestowaliśmy. Jeszcze bardziej irytujące było wynalezienie własnego roweru. Ale muszę przyznać, że to rozwiązanie zadziałało i pozwoliło na stabilne wydanie.
Dzień # -701: Ansible i kuchnia testowa
Rozwinięciem idei testowania Ansible było wykorzystanie gotowych narzędzi, a mianowicie test Kitchen/ Kitchen-ci oraz inspec. O wyborze zadecydowała znajomość Ruby (więcej szczegółów w artykule o Habré: Czy programiści YML marzą o testowaniu Ansible?) pracowało szybciej, około 40 minut na 10 ról. Stworzyliśmy paczkę maszyn wirtualnych i przeprowadziliśmy w niej testy.
Ogólnie rzecz biorąc, roztwór działał, ale ze względu na niejednorodność występowały pewne osady. Kiedy liczbę testowanych osób zwiększono do 13 ról podstawowych i 2 meta ról łączących mniejsze role, nagle testy zaczęły trwać 70 minut, czyli prawie 2 razy dłużej. Trudno było mówić o praktykach XP (programowania ekstremalnego), ponieważ… nikt nie chce czekać 70 minut. To był powód zmiany podejścia
Dzień # -601: Ansible i molekuła
Koncepcyjnie jest to podobne do testkitchen, tyle że przenieśliśmy testowanie ról do okna dokowanego i zmieniliśmy stos. W rezultacie czas został skrócony do stabilnych 20-25 minut dla 7 ról.
Zwiększając liczbę testowanych ról do 17 i ustawiając 45 ról, uruchomiliśmy to w 28 minut na 2 niewolnikach Jenkinsa.
Dzień #167: Dodawanie testów Ansible do projektu
Najprawdopodobniej nie będzie możliwe wykonanie zadania refaktoryzacji w pośpiechu. Zadanie musi być mierzalne, abyś mógł je rozbić na małe kawałki i zjadać słonia kawałek po kawałku łyżeczką. Konieczne jest zrozumienie, czy zmierzasz we właściwym kierunku i ile czasu Ci to zajmie.
Generalnie nie ma znaczenia jak to zostanie zrobione, możesz napisać na kartce papieru, możesz przykleić naklejki na szafę, możesz tworzyć zadania w Jira, albo możesz otworzyć Dokumenty Google i spisać aktualny stan Tam. Nogi rosną od tego, że proces nie jest natychmiastowy, będzie długi i żmudny. Jest mało prawdopodobne, aby ktokolwiek chciał, abyś podczas refaktoryzacji wypalił się, zmęczył i poczuł się przytłoczony.
Refaktoryzacja jest prosta:
Jeść.
Spać.
Kod.
Test IAC.
powtarzać
i powtarzamy to aż do osiągnięcia zamierzonego celu.
Być może nie da się od razu rozpocząć testowania wszystkiego, więc naszym pierwszym zadaniem było zacząć od lintingu i sprawdzenia składni.
Dzień #181: Mistrz zielonego budowania
Linting to mały pierwszy krok w kierunku Green Build Master. Nie zepsuje to prawie niczego, ale pozwoli ci debugować procesy i tworzyć zielone kompilacje w Jenkins. Ideą jest wyrobienie w zespole nawyków:
Czerwone testy są złe.
Przyszedłem coś naprawić i jednocześnie sprawić, że kod będzie trochę lepszy niż był przed tobą.
Dzień #193: Od lintingu do testów jednostkowych
Po zbudowaniu procesu wprowadzania kodu do mastera można rozpocząć proces stopniowego doskonalenia - zastępując linting rolami uruchamiającymi, można to zrobić nawet bez idempotencji. Musisz zrozumieć, jak stosować role i jak one działają.
Dzień #211: Od testów jednostkowych do integracyjnych
Kiedy większość ról jest objęta testami jednostkowymi i wszystko jest zaśmiecone, możesz przejść do dodawania testów integracyjnych. Te. testowanie nie pojedynczej cegły w infrastrukturze, ale ich kombinacji, np. pełnej konfiguracji instancji.
Używając Jenkinsa, wygenerowaliśmy wiele etapów, które równolegle łączyły role/podręczniki, następnie testy jednostkowe w kontenerach, a na koniec testy integracyjne.
Jenkins + Docker + Ansible = Testy
Sprawdź repozytorium i wygeneruj etapy kompilacji.
Uruchom równolegle etapy podręcznika Lint.
Uruchom równolegle etapy roli lint.
Uruchom równolegle etapy roli sprawdzania składni.
Uruchom równolegle etapy roli testowej.
Rola kłaczków.
Sprawdź zależność od innych ról.
Sprawdź składnię.
Utwórz instancję dokera
Uruchom molekułę/default/playbook.yml.
Sprawdź idempotencję.
Uruchom testy integracyjne
koniec
Dzień #271: Faktor autobusowy
Początkowo refaktoryzację przeprowadzała niewielka grupa dwóch lub trzech osób. Przejrzeli kod w masterze. Z biegiem czasu zespół rozwinął wiedzę na temat pisania kodu, a jego recenzja przyczyniła się do upowszechnienia wiedzy o infrastrukturze i sposobie jej działania. Najważniejszym wydarzeniem było to, że recenzenci byli wybierani pojedynczo, według harmonogramu, tj. z pewnym prawdopodobieństwem wejdziesz na nowy element infrastruktury.
I tutaj powinno być wygodnie. Wygodnie jest zrobić przegląd, zobaczyć w ramach jakiego zadania zostało wykonane i historię dyskusji. Zintegrowaliśmy jenkins + bitbucket + jira.
Ale jako taka recenzja nie jest panaceum; w jakiś sposób dotarliśmy do kodu głównego, co spowodowało, że testy wypadły na flopie:
Z biegiem czasu testów było coraz więcej, kompilacje działały wolniej, w najgorszym przypadku do godziny. Na jednym z retro było zdanie w stylu „dobrze, że są testy, ale są powolne”. W rezultacie porzuciliśmy testy integracyjne na maszynach wirtualnych i dostosowaliśmy je do Dockera, aby było to szybsze. Zastąpiliśmy także testinfra weryfikatorem ansible, aby zmniejszyć liczbę używanych narzędzi.
Ściśle mówiąc, istniał zestaw środków:
Przejdź do okna dokowanego.
Usuń testowanie ról, które jest zduplikowane ze względu na zależności.
Zwiększ liczbę niewolników.
Kolejność uruchomienia testowego.
Możliwość linczowania WSZYSTKO lokalnie za pomocą jednego polecenia.
W rezultacie ujednolicono także Pipeline na Jenkinsie
Generuj etapy kompilacji.
Lint wszystko równolegle.
Uruchom równolegle etapy roli testowej.
Zakończ.
Wyciągnięte wnioski
Unikaj zmiennych globalnych
Ansible używa zmiennych globalnych, w formularzu istnieje częściowe obejście private_role_vars, ale to nie jest panaceum.
Zabawne jest to, że wynik podręczników będzie zależał od rzeczy, które nie zawsze są oczywiste, takich jak kolejność wymieniania ról. Taka jest niestety natura Ansible i najlepsze co można zrobić to zastosować jakąś umowę, np. w ramach roli używać tylko zmiennej opisanej w tej roli.
Zgodziliśmy się na stosowanie przedrostków zmiennych, nie będzie zbyteczne sprawdzenie, czy są one zdefiniowane zgodnie z naszymi oczekiwaniami i czy nie zostały np. nadpisane pustą wartością
DOBRY: Sprawdź zmienne.
- 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
Unikaj słowników zawierających skróty, używaj płaskiej struktury
Jeśli rola oczekuje skrótu/słownika w jednym ze swoich parametrów, to jeśli chcemy zmienić jeden z parametrów podrzędnych, będziemy musieli zastąpić cały skrót/słownik, co zwiększy złożoność konfiguracji.
Role i scenariusze muszą być idempotentne, ponieważ zmniejsza dryf konfiguracji i strach przed uszkodzeniem czegoś. Ale jeśli używasz cząsteczki, jest to zachowanie domyślne.
Unikaj używania modułów powłoki poleceń
Użycie modułu powłoki skutkuje paradygmatem opisu imperatywnego zamiast deklaratywnego, który jest rdzeniem Ansible.
Przetestuj swoje role za pomocą cząsteczki
Cząsteczka to bardzo elastyczna rzecz, spójrzmy na kilka scenariuszy.
Cząsteczka Wiele instancji
В molecule.yml w sekcji platforms możesz opisać wiele hostów, które możesz wdrożyć.
W molekule można użyć ansible, aby sprawdzić, czy instancja została poprawnie skonfigurowana, co więcej, jest to ustawienie domyślne od wersji 3. Nie jest tak elastyczny jak testinfra/inspec, ale możemy sprawdzić, czy zawartość pliku odpowiada naszym oczekiwaniom:
Możesz też wdrożyć usługę, poczekać, aż stanie się dostępna i wykonać test dymny:
---
- 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
Umieść złożoną logikę w modułach i wtyczkach
Ansible opowiada się za podejściem deklaratywnym, więc gdy wykonujesz rozgałęzienia kodu, transformację danych i moduły powłoki, kod staje się trudny do odczytania. Aby temu zaradzić i zapewnić prostotę zrozumienia, nie będzie zbędne zwalczanie tej złożoności poprzez tworzenie własnych modułów.
Nie możesz po prostu przejść do refaktoryzacji infrastruktury w projekcie, nawet jeśli masz IaC. Jest to długi proces wymagający cierpliwości, czasu i wiedzy.
UPD1 2020.05.01 20:30 — Do podstawowego profilowania podręczników, których możesz użyć callback_whitelist = profile_tasks aby zrozumieć, co dokładnie działa przez długi czas. Potem przechodzimy Klasyka akceleracji Ansible. Możesz też spróbować mitogen UPD2 2020.05.03 16:34 - angielska wersja