Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Podejście IaC (Infrastructure as Code) składa się nie tylko z kodu przechowywanego w repozytorium, ale także z ludzi i procesów otaczających ten kod. Czy możliwe jest ponowne wykorzystanie podejść od tworzenia oprogramowania po zarządzanie i opis infrastruktury? Dobrze byłoby mieć to na uwadze podczas czytania artykułu.

angielska wersja

To jest transkrypcja mojego występy na Konferencja Devops 2019.

Slajdy i filmy

Infrastruktura jako historia basha

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Załóżmy, że przychodzisz do nowego projektu i mówią ci: „mamy Infrastruktura jako kod„. W rzeczywistości okazuje się Infrastruktura jako historia basha lub na przykład Dokumentacja jako historia basha. To bardzo realna sytuacja, np. podobny przypadek opisał w swoim przemówieniu Denis Łysenko Jak wymienić całą infrastrukturę i zacząć spać spokojnie, opowiedział, jak z historii basha uzyskali spójną infrastrukturę dla projektu.

Z pewnym pragnieniem możemy to powiedzieć Infrastruktura jako historia basha to jest jak kod:

  1. odtwarzalność: Możesz pobrać historię basha, uruchomić stamtąd polecenia, a przy okazji możesz otrzymać działającą konfigurację jako wynik.
  2. wersjonowanie: wiesz, kto wszedł i co zrobił, znowu nie jest faktem, że doprowadzi cię to do działającej konfiguracji przy wyjściu.
  3. historia: historia tego, kto co zrobił. tylko nie będziesz mógł z niego korzystać, jeśli stracisz serwer.

Co robić?

Infrastruktura jako kod

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Nawet tak dziwny przypadek jak Infrastruktura jako historia basha można go ciągnąć za uszy Infrastruktura jako kod, ale gdy będziemy chcieli zrobić coś bardziej skomplikowanego niż stary, dobry serwer LAMP, to dojdziemy do wniosku, że ten kod trzeba jakoś zmodyfikować, zmienić, ulepszyć. Następnie chcielibyśmy rozważyć podobieństwa między Infrastruktura jako kod i rozwoju oprogramowania.

SUCHY

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

W przypadku projektu rozwoju systemu pamięci masowej istniało podzadanie okresowo konfiguruj SDS: wypuszczamy nową wersję - należy ją wdrożyć w celu dalszych testów. Zadanie jest niezwykle proste:

  • zaloguj się tutaj przez ssh i wykonaj polecenie.
  • skopiuj tam plik.
  • popraw konfigurację tutaj.
  • uruchom tam usługę
  • ...
  • ZYSK!

Dla opisanej logiki bash jest więcej niż wystarczający, zwłaszcza na wczesnych etapach projektu, kiedy dopiero się on rozpoczyna. Ten nie jest źle, że używasz basha, ale z biegiem czasu pojawiają się prośby o wdrożenie czegoś podobnego, ale nieco innego. Pierwsze co mi przychodzi na myśl to kopiuj-wklej. A teraz mamy już dwa bardzo podobne skrypty, które robią prawie to samo. Z biegiem czasu liczba skryptów rosła i stanęliśmy przed faktem, że istnieje pewna logika biznesowa dotycząca wdrażania instalacji, która wymaga synchronizacji między różnymi skryptami, jest to dość skomplikowane.

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Okazuje się, że istnieje taka praktyka jak DRY (Nie powtarzaj się). Pomysł polega na ponownym wykorzystaniu istniejącego kodu. Brzmi prosto, ale nie od razu do tego doszliśmy. W naszym przypadku był to banalny pomysł: oddzielenie konfiguracji od skryptów. Te. logika biznesowa dotycząca oddzielnego wdrażania instalacji, konfiguracja odbywa się osobno.

SOLIDNE dla CFM

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Z czasem projekt się rozrósł i naturalna kontynuacja było pojawienie się Ansible. Głównym powodem jego pojawienia się jest to, że zespół ma wiedzę specjalistyczną i że bash nie jest przeznaczony do stosowania złożonej logiki. Ansible również zaczął zawierać złożoną logikę. Aby zapobiec przekształceniu złożonej logiki w chaos, istnieją zasady organizacji kodu podczas tworzenia oprogramowania SOLIDNY Również na przykład Grigorij Pietrow w swoim raporcie „Dlaczego informatyk potrzebuje marki osobistej” postawił pytanie, czy dana osoba jest zaprojektowana w taki sposób, aby łatwiej było jej współpracować z niektórymi podmiotami społecznymi, przy tworzeniu oprogramowania te są przedmiotami. Jeśli połączymy te dwa pomysły i będziemy je dalej rozwijać, zauważymy, że również możemy je zastosować SOLIDNY aby ułatwić utrzymanie i modyfikowanie tej logiki w przyszłości.

Zasada jednolitej odpowiedzialności

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Każda klasa wykonuje tylko jedno zadanie.

Nie ma potrzeby mieszania kodu i tworzenia monolitycznych boskich potworów spaghetti. Infrastruktura powinna składać się z prostych cegieł. Okazuje się, że jeśli podzielisz podręcznik Ansible na małe części, przeczytasz role Ansible, łatwiej będzie je utrzymać.

Zasada otwartego zamkniętego

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Zasada otwarty/zamknięty.

  • Otwarty na rozszerzenie: oznacza, że ​​zachowanie obiektu można rozszerzyć poprzez utworzenie nowych typów obiektów.
  • Zamknięte na zmiany: w wyniku rozszerzenia zachowania encji nie należy wprowadzać żadnych zmian w kodzie korzystającym z tych encji.

Początkowo infrastrukturę testową wdrażaliśmy na maszynach wirtualnych, jednak ze względu na to, że logika biznesowa wdrożenia była oddzielona od wdrożenia, bez problemu dodaliśmy wdrożenie do baremetall.

Zasada podstawienia Liskowa

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Zasada substytucji Barbary Liskov. obiekty w programie muszą być zastępowalne przez instancje ich podtypów, bez zmiany poprawności wykonania programu

Jeśli spojrzeć na to szerzej, nie jest to cecha konkretnego projektu, którą można tam zastosować SOLIDNY, ogólnie chodzi o CFM, na przykład w innym projekcie konieczne jest wdrożenie pudełkowej aplikacji Java na różnych Java, serwerach aplikacji, bazach danych, systemie operacyjnym itp. Na tym przykładzie rozważę dalsze zasady SOLIDNY

W naszym przypadku w zespole ds. infrastruktury panuje zgoda co do tego, że jeśli zainstalowaliśmy rolę imbjava lub oraclejava, wówczas będziemy mieli binarny plik wykonywalny Java. Jest to konieczne, ponieważ Role nadrzędne zależą od tego zachowania; oczekują Java. Jednocześnie pozwala to na zastąpienie jednej implementacji/wersji Java inną, bez zmiany logiki wdrażania aplikacji.

Problem tutaj polega na tym, że nie da się tego zaimplementować w Ansible, w efekcie czego w zespole pojawiają się pewne porozumienia.

Zasada segregacji interfejsów

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Zasada separacji interfejsów: „Wiele interfejsów specyficznych dla klienta jest lepszych niż jeden interfejs ogólnego przeznaczenia.

Początkowo próbowaliśmy umieścić całą różnorodność wdrażania aplikacji w jednym podręczniku Ansible, ale było to trudne do obsługi, a podejście, gdy mamy określony interfejs zewnętrzny (klient oczekuje portu 443), to infrastrukturę można złożyć z indywidualnych cegły pod konkretną realizację.

Zasada odwrócenia zależności

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Zasada inwersji zależności. Moduły na wyższych poziomach nie powinny zależeć od modułów na niższych poziomach. Obydwa typy modułów muszą zależeć od abstrakcji. Abstrakcje nie powinny zależeć od szczegółów. Szczegóły muszą zależeć od abstrakcji.

Tutaj przykład będzie oparty na antywzorze.

  1. Jeden z klientów posiadał chmurę prywatną.
  2. Zamówiliśmy maszyny wirtualne w chmurze.
  3. Jednak ze względu na charakter chmury wdrażanie aplikacji było powiązane z tym, który hypervisor był włączony na maszynie wirtualnej.

Te. Logika wdrażania aplikacji wysokiego poziomu przepływała z zależnościami do niższych poziomów hypervisora, co oznaczało problemy przy ponownym wykorzystaniu tej logiki. Nie rób tego.

Wzajemne oddziaływanie

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Infrastruktura jako kod to nie tylko kod, ale także relacja pomiędzy kodem a ludźmi, interakcje pomiędzy twórcami infrastruktury.

Czynnik autobusowy

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Załóżmy, że masz Vasyę w swoim projekcie. Vasya wie wszystko o Twojej infrastrukturze. Co się stanie, jeśli Vasya nagle zniknie? To bardzo realna sytuacja, bo mógł zostać potrącony przez autobus. Czasami tak bywa. Jeśli tak się stanie, a wiedza o kodzie, jego strukturze, działaniu, wyglądzie i hasłach nie będzie rozproszona pomiędzy zespołem, to możesz spotkać się z szeregiem nieprzyjemnych sytuacji. Aby zminimalizować te ryzyka i dystrybuować wiedzę w zespole, można zastosować różne podejścia

Rozbieranie par

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

To nie jest tak jako żart, że admini wypili piwo, zmienili hasła i analogię programowania w parach. Te. dwóch inżynierów siada przy jednym komputerze, jednej klawiaturze i wspólnie rozpoczynają konfigurowanie infrastruktury: konfigurowanie serwera, pisanie roli Ansible itp. Brzmi nieźle, ale u nas to nie zadziałało. Ale szczególne przypadki tej praktyki zadziałały. Przychodzi nowy pracownik, jego mentor podejmuje się wraz z nim realnego zadania, pracuje i przekazuje wiedzę.

Kolejnym szczególnym przypadkiem jest wezwanie incydentalne. Kiedy pojawia się problem, zbiera się grupa dyżurnych i osób zaangażowanych, wyznaczany jest jeden lider, który udostępnia swój ekran i wyraża tok myślenia. Pozostali uczestnicy śledzą myśli lidera, szpiegują sztuczki z konsoli, sprawdzają, czy nie pominęli żadnej linijki w logu i dowiadują się nowych rzeczy o systemie. To podejście sprawdzało się częściej niż nie.

Przegląd kodu

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Subiektywnie bardziej efektywne było upowszechnianie wiedzy o infrastrukturze i jej działaniu za pomocą przeglądu kodu:

  • Infrastruktura jest opisana kodem w repozytorium.
  • Zmiany zachodzą w osobnej gałęzi.
  • Podczas żądania połączenia możesz zobaczyć różnicę zmian w infrastrukturze.

Najważniejszym wydarzeniem było to, że recenzenci byli wybierani pojedynczo, według harmonogramu, tj. z pewnym prawdopodobieństwem wejdziesz na nowy element infrastruktury.

Styl kodu

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Z biegiem czasu podczas recenzji zaczęły pojawiać się sprzeczki, bo... recenzenci mieli swój własny styl, a rotacja recenzentów układała je w różne style: 2 spacje lub 4, camelCase lub Snake_case. Nie można było tego od razu wdrożyć.

  • Pierwszym pomysłem było zalecenie używania lintera, wszak każdy jest inżynierem, każdy jest mądry. Ale różne edytory, OS, nie są wygodne
  • To przekształciło się w bota, który zapisywał Slack dla każdego problematycznego zatwierdzenia i dołączał dane wyjściowe lintera. Jednak w większości przypadków były ważniejsze rzeczy do zrobienia i kod pozostał nienaprawiony.

Mistrz zielonego budowania

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Czas mija i doszliśmy do wniosku, że commity, które nie przejdą pewnych testów, nie mogą zostać dopuszczone do mastera. Voila! Wymyśliliśmy Green Build Master, który od dawna jest praktykowany w tworzeniu oprogramowania:

  • Rozwój trwa w osobnej branży.
  • Trwają testy tego wątku.
  • Jeśli testy się nie powiodą, kod nie trafi do mastera.

Podjęcie tej decyzji było bardzo bolesne, ponieważ... wywołało wiele kontrowersji, ale było warto, bo... Do recenzji zaczęły docierać prośby o fuzje bez różnic w stylu, a z biegiem czasu liczba obszarów problematycznych zaczęła się zmniejszać.

Testowanie IaC

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Oprócz sprawdzania stylu możesz użyć innych rzeczy, na przykład aby sprawdzić, czy Twoja infrastruktura faktycznie może zostać wdrożona. Lub sprawdź, czy zmiany w infrastrukturze nie doprowadzą do utraty pieniędzy. Dlaczego może to być potrzebne? Pytanie jest złożone i filozoficzne, lepiej odpowiedzieć historią, że jakimś cudem na PowerShell był autoskaler, który nie sprawdzał warunków brzegowych => utworzono więcej maszyn wirtualnych niż było to konieczne => klient wydał więcej pieniędzy niż planował. Nie jest to zbyt przyjemne, ale całkiem możliwe byłoby wyłapanie tego błędu na wcześniejszych etapach.

Ktoś mógłby zapytać, po co komplikować złożoną infrastrukturę jeszcze bardziej? Testy infrastruktury, podobnie jak kodu, nie polegają na uproszczeniu, ale na poznaniu, jak powinna działać Twoja infrastruktura.

Piramida testowania IaC

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Testowanie IaC: analiza statyczna

Jeśli od razu wdrożysz całą infrastrukturę i sprawdzisz, czy działa, może się okazać, że zajmuje to dużo czasu i wymaga dużo czasu. Dlatego podstawą musi być coś, co działa szybko, jest tego dużo i obejmuje wiele prymitywnych miejsc.

Basha jest trudny

Spójrzmy na banalny przykład. wybierz wszystkie pliki w bieżącym katalogu i skopiuj do innej lokalizacji. Pierwsza rzecz, która przychodzi na myśl:

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

A co jeśli w nazwie pliku jest spacja? No cóż, jesteśmy mądrzy, umiemy używać cudzysłowów:

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

Dobrze zrobiony? NIE! A co jeśli w katalogu nie ma nic, tj. globbing nie zadziała.

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

Dobra robota, teraz? Nie... Zapomniałem, co może zawierać nazwa pliku n.

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

Narzędzia analizy statycznej

Problem z poprzedniego kroku można uchwycić, gdy zapomnimy o cudzysłowie, ponieważ istnieje wiele środków zaradczych Kontrola powłoki, ogólnie jest ich dużo i najprawdopodobniej możesz znaleźć linter dla swojego stosu w swoim IDE.

Wybierz język
Narzędzie

bash
Kontrola powłoki

Rubin
RuboCop

pyton
Pylint

ansible
Ansible Linta

Testowanie IaC: testy jednostkowe

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Jak widzieliśmy na poprzednim przykładzie, linters nie jest wszechmocny i nie jest w stanie wskazać wszystkich obszarów problematycznych. Dalej, analogicznie do testowania w tworzeniu oprogramowania, możemy przywołać testy jednostkowe. To, co od razu przychodzi na myśl, to unikaj, junita, rspec, test. Ale co zrobić z ansiblem, szefem kuchni, saltstackem i innymi podobnymi?

Na samym początku rozmawialiśmy o SOLIDNY i że nasza infrastruktura powinna składać się z małych cegiełek. Nadszedł ich czas.

  1. Infrastruktura jest podzielona na małe cegiełki, na przykład role Ansible.
  2. Wdraża się jakiś rodzaj środowiska, czy to okno dokowane, czy maszyna wirtualna.
  3. Stosujemy naszą rolę Ansible w tym środowisku testowym.
  4. Sprawdzamy, czy wszystko zadziałało tak, jak oczekiwaliśmy (przeprowadzamy testy).
  5. Decydujemy, czy jest ok, czy nie.

Testowanie IaC: narzędzia do testowania jednostkowego

Pytanie, czym są testy na CFM? Możesz po prostu uruchomić skrypt lub skorzystać z gotowych rozwiązań:

CFM
Narzędzie

Wiarygodne
Testinfra

Szef kuchni
Sprawdź

Szef kuchni
Specyfikacja serwera

solniczka
Goss

Przykład dla testinfra, sprawdzający, czy użytkownicy test1, test2 istnieją i są w grupie 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

Co wybrać? Pytanie jest złożone i niejednoznaczne, oto przykład zmian w projektach na githubie na lata 2018-2019:

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Ramy testowania IaC

Powstaje pytanie: jak to wszystko poskładać i uruchomić? Móc weź to i zrób to sam jeśli będzie wystarczająca liczba inżynierów. Możesz też skorzystać z gotowych rozwiązań, chociaż nie ma ich zbyt wiele:

CFM
Narzędzie

Wiarygodne
Cząsteczka

Szef kuchni
Testuj kuchnię

Terraform
Terratest

Przykład zmian w projektach na githubie na lata 2018-2019:

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Cząsteczka kontra. Kuchnia testowa

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Początkowo my próbowałem użyć testkitchen:

  1. Utwórz maszynę wirtualną równolegle.
  2. Zastosuj role Ansible.
  3. Uruchom inspekcję.

Na 25–35 ról pracowało to 40–70 minut, czyli długo.

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Następnym krokiem było przejście do jenkins/docker/ansible/molecule. Idiologicznie wszystko jest takie samo

  1. Podręczniki Lint.
  2. Ułóżcie role.
  3. Uruchom kontener
  4. Zastosuj role Ansible.
  5. Uruchom testinfra.
  6. Sprawdź idempotencję.

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Linting dla 40 ról i testy dla kilkunastu zaczęły zajmować około 15 minut.

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

To, co wybrać, zależy od wielu czynników, takich jak zastosowany stos, doświadczenie zespołu itp. tutaj każdy sam decyduje, jak zamknąć pytanie dotyczące testów jednostkowych

Testowanie IaC: Testy integracyjne

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Kolejnym krokiem w piramidzie testów infrastruktury będą testy integracyjne. Są one podobne do testów jednostkowych:

  1. Infrastruktura jest podzielona na małe cegiełki, na przykład role Ansible.
  2. Wdraża się jakiś rodzaj środowiska, czy to okno dokowane, czy maszyna wirtualna.
  3. Do tego środowiska testowego stosuje się zestaw Role Ansibla.
  4. Sprawdzamy, czy wszystko zadziałało tak, jak oczekiwaliśmy (przeprowadzamy testy).
  5. Decydujemy, czy jest ok, czy nie.

Z grubsza nie sprawdzamy wydajności pojedynczego elementu systemu jak w testach jednostkowych, tylko sprawdzamy jak skonfigurowany jest serwer jako całość.

Testowanie IaC: Testy kompleksowe

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Na szczycie piramidy witają nas testy End to End. To jest Nie sprawdzamy wydajności osobnego serwera, osobnego skryptu, czy osobnej kostki naszej infrastruktury. Sprawdzamy, czy wiele serwerów jest ze sobą połączonych, nasza infrastruktura działa tak, jak tego oczekujemy. Niestety nigdy nie spotkałem się z gotowymi rozwiązaniami pudełkowymi, pewnie dlatego, że... Infrastruktura jest często unikalna i trudna do szablonowania i tworzenia ram do testowania. Dzięki temu każdy tworzy własne rozwiązania. Jest żądanie, ale nie ma odpowiedzi. Dlatego opowiem Wam, co tu jest, żeby nakłonić innych do rozsądnych przemyśleń albo potrzeć nos, że wszystko zostało wymyślone dawno przed nami.

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Projekt z bogatą historią. Jest stosowany w dużych organizacjach i zapewne każdy z Was pośrednio się z nim spotkał. Aplikacja obsługuje wiele baz danych, integracji itp. Znajomość tego, jak może wyglądać infrastruktura, wymaga wielu plików komponowanych w oknie dokowanym, a wiedza, które testy należy uruchomić w jakim środowisku, to Jenkins.

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Ten schemat działał przez dość długi czas, aż do wewnątrz Badania nie próbowaliśmy przenieść tego na Openshift. Kontenery pozostają takie same, ale środowisko uruchamiania uległo zmianie (witaj ponownie DRY).

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Pomysł badawczy poszedł dalej i w openshift znaleźli coś takiego jak APB (Ansible Playbook Bundle), który pozwala spakować wiedzę o tym, jak wdrożyć infrastrukturę w kontenerze. Te. istnieje powtarzalny i możliwy do przetestowania poziom wiedzy na temat wdrażania infrastruktury.

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Wszystko to brzmiało dobrze, dopóki nie natknęliśmy się na heterogeniczną infrastrukturę: potrzebowaliśmy systemu Windows do testów. W rezultacie wiedza o tym, co, gdzie, jak wdrożyć i przetestować, znajduje się w Jenkinsie.

Wnioski

Czego nauczyłem się testując 200 000 linii kodu infrastruktury

Infrastruktura taka, jaka jest

  • Kod w repozytorium.
  • Interakcja międzyludzka.
  • Testowanie infrastruktury.

linki

Źródło: www.habr.com

Dodaj komentarz