Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Wydawać by się mogło, że deweloperzy Terraform oferują wystarczająco wygodne najlepsze praktyki do pracy z infrastrukturą AWS. Tylko jest jeden szczegół. Z czasem liczba środowisk rośnie, każde ma swoje szczegóły. Pojawia się praktycznie kopia stosu aplikacji w sąsiednim regionie. A kod Terraformu trzeba starannie skopiować i edytować zgodnie z nowymi wymaganiami lub zrobić płatek śniegu.

Mój wykład dotyczy wzorców w Terraform, które pomagają w walce z chaosem i ręcznymi czynnościami w dużych, długoterminowych projektach.

Wideo:

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Mam 40 lat, 20 lat w IT. Pracuję w firmie Ixtens od 12 lat. Zajmujemy się rozwojem opartym na e-commerce. I od 5 lat praktykuję praktyki DevOps.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Moja opowieść będzie dotyczyć doświadczenia w projekcie w firmie, której nazwy nie podam, powołując się na umowę o poufności.

Cyfry na slajdzie są podane po to, aby zrozumieć skalę projektu. A wszystko, co dalej powiem, będzie związane z Amazonem.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Dołączyłem do tego projektu 4 lata temu. I w chwili szczytowej przechodziłem przez refaktoryzację infrastruktury, ponieważ projekt się rozrastał. Wzorce, które były stosowane, już nie pasowały. I biorąc pod uwagę cały planowany wzrost projektu, trzeba było wymyślić coś nowego.

Dziękuję Matviejowi, który wczoraj opowiedział, co działo się w Dodo Pizzy. To, co działo się u nas 4 lata temu.

Przyszli deweloperzy i zaczęli pisać kod infrastruktury.

Najbardziej oczywiste powody, dla których to było konieczne, to potrzeba szybkiego wprowadzenia na rynek. Należało tak zorganizować, aby zespół DevOps nie był wąskim gardłem podczas wypuszczania. Oprócz tego na samym początku używano Terraform i Puppet.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Terraform to projekt open source firmy HashiCorp. A dla tych, którzy w ogóle nie wiedzą, co to jest, kilka następnych slajdów.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Infrastruktura jako kod oznacza, że możemy opisać naszą infrastrukturę i poprosić jakieś roboty, aby stworzyły zasoby, które opisaliśmy.

Na przykład potrzebujemy maszyna wirtualna. Opiszemy to, dodamy kilka obowiązkowych parametrów.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Następnie w konsoli skonfigurujemy dostęp do Amazona. I poprosimy Terraform o plan. Terraform plan powie: "Ok, dla Twojego zasobu możemy zrobić takie rzeczy". I przynajmniej jeden zasób zostanie dodany. I nie przewiduje się żadnych zmian.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Po tym, jak wszystko Cię zadowoli, możesz poprosić Terraform o zastosowanie, a Terraform utworzy dla Ciebie instancję i otrzymasz maszynę wirtualną w chmurze.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Nasz projekt się rozwija. Dodajemy do niego różne zmiany. Prosimy o dodatkowe instancje, dodajemy 53 wpisy.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

I powtarzamy. Prosimy o plan. Widzimy, jakie zmiany są planowane. Wprowadzamy je. W ten sposób nasza infrastruktura rośnie.

Terraform używa tzw. plików stanu. To znaczy, że wszystkie zmiany, które są wysyłane do Amazonu, są zapisywane w pliku, w którym dla każdego opisanego zasobu znajdują się odpowiadające zasoby, które zostały utworzone w Amazonie. W ten sposób, przy zmianie opisu jakiegoś zasobu, Terraform dokładnie wie, co należy zmienić w Amazonie.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Te pliki stanu początkowo były po prostu plikami. Przechowywaliśmy je w Gicie, co było bardzo niewygodne. Ktoś zawsze zapominał o zatwierdzeniu zmian, co prowadziło do wielu konfliktów.

Obecnie można używać backendu, tzn. Terraform wskazuje, w którym koszyku i pod jakim kluczem należy zapisać plik stanu. Terraform sam zadba o to, by pobrać ten plik stanu, przeprowadzić wszystkie operacje i złożyć z powrotem ostateczny wynik.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Nasza infrastruktura rośnie. Oto nasz kod. Teraz nie chcemy tylko tworzyć maszyny wirtualnej, chcemy mieć środowisko testowe.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Terraform pozwala na stworzenie modułu, tzn. można to samo opisać w odpowiednim folderze.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Na przykład, w testach można wywołać ten moduł i uzyskać to samo, jakbyśmy wykonali Terraform apply w samym module. Kod do testowania będzie wyglądał tak.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Dla produkcji możemy wysłać tam pewne zmiany, ponieważ w testach nie potrzebujemy dużych instancji, w produkcji duże instancje będą bardzo przydatne.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Teraz wrócę do projektu. Było to trudne zadanie, infrastruktura miała być bardzo duża. Konieczne było umiejscowienie całego kodu w taki sposób, aby było to wygodne dla wszystkich: zarówno dla osób zajmujących się utrzymaniem tego kodu, jak i dla tych, którzy wprowadzają zmiany. Planowano, że każdy programista może podejść i poprawić infrastrukturę według potrzeb swojej części platformy.

To drzewo katalogów, które jest zalecane przez samą firmę HashiCorp, jeśli macie duży projekt i jest sens podzielić całą infrastrukturę na mniejsze kawałki, a każdy z nich opisać w osobnym folderze.

Majac obszerną bibliotekę zasobów można w testach i w produkcji wywoływać mniej więcej to samo.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

W naszym przypadku to nie do końca pasowało, ponieważ testowy stos dla deweloperów lub do testowania musiał być prostszy do uzyskania. Nie chciało się chodzić po folderach i stosować je w odpowiedniej kolejności, martwiąc się, że baza zostanie uruchomiona, a potem zostanie uruchomiony instancja, która tę bazę wykorzystuje. Dlatego cały test uruchamiano z jednego folderu. Tam wywoływano te same moduły, ale wszystko odbywało się w jednym przebiegu.

Terraform dba o wszystkie zależności. Zawsze tworzy zasoby w takiej kolejności, aby można było uzyskać adres IP, na przykład, z świeżo utworzonej instancji, i uzyskać ten adres IP w zapisie route53.

Poza tym platforma jest bardzo rozbudowana. Uruchomienie testowego stosu, nawet na godzinę, nawet na 8 godzin – to dość drogie przedsięwzięcie.

Zautomatyzowaliśmy ten proces. Job Jenkins pozwalał na uruchamianie stosu. Należało tam uruchomić pull request z zmianami, które deweloper chciał przetestować, oraz wskazać wszystkie potrzebne opcje, komponenty i rozmiary. Jeśli chciał testowania wydajności, mógł wziąć więcej instancji. Jeśli potrzebował tylko sprawdzić, czy formularz się otwiera, mógł go uruchomić na minimalnych ustawieniach. Mógł również wskazać, czy potrzebny jest klaster, czy nie, itd.

Następnie Jenkins uruchamiał skrypt powłoki, który nieco modyfikował kod w folderze Terraform. Usuwał niepotrzebne pliki, dodawał potrzebne pliki. A potem jednym przebiegiem Terraform apply, stos był uruchamiany.

A potem szły już inne kroki, w które nie chcę się zagłębiać.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Z uwagi na to, że do testowania potrzebowaliśmy nieco więcej opcji niż w produkcji, musieliśmy tworzyć kopie modułów, aby w tych kopiach dodać te funkcje, które są potrzebne tylko w testowaniu.

I tak się stało, że w testach chciano przetestować te zmiany, które w końcu trafią do produkcji. Ale tak naprawdę testowano jedną rzecz, a w produkcji stosowano nieco inną. Istniała mała rozbieżność, że w produkcji wszystkie zmiany były stosowane przez zespół operacyjny. Czasami zdarzało się, że zmiany, które miały przejść z testów do produkcji, pozostawały w innej wersji.

Oprócz tego istniał problem z dodawaniem nowej usługi, która nieco różniła się od już istniejącej. Zamiast modyfikować istniejący moduł, konieczne było stworzenie jego kopii i wprowadzenie niezbędnych zmian.

W zasadzie Terraform to nie jest prawdziwy język. To deklaracja. Jeśli musimy coś zadeklarować, to to deklarujemy. I to wszystko działa.

W pewnym momencie, gdy omawiano jeden z moich pull requestów, jeden z kolegów powiedział, że nie należy mnożyć śnieżynek. Zainteresowałem się, co ma na myśli. Jest taki fakt naukowy, że na świecie nie ma dwóch identycznych śnieżynek, wszystkie się od siebie nieco różnią. I gdy tylko to usłyszałem, natychmiast poczułem ciężar kodu Terraform. Ponieważ, gdy konieczne było przechodzenie z wersji na wersję, Terraform wymagał wprowadzenia breaking chain zmian, tzn. kod nie był już kompatybilny z następną wersją. Konieczne było złożenie pull requestu, który obejmował prawie połowę plików w infrastrukturze, aby dostosować infrastrukturę do następnej wersji Terraform.

I po pojawieniu się takiej śnieżynki, cały kod Terraform, który mieliśmy, stawał się wielką, wielką kupą śniegu.

Dla zewnętrznego dewelopera, który działa poza operacjami, nie ma to dużego znaczenia, ponieważ złożył pull request, jego zasób uruchomił się. I to wszystko, dalej nie jest to jego troska. Zespół DevOps, który dba o to, aby wszystko było w porządku, musi wprowadzić wszystkie te zmiany. A koszty tych zmian znacznie wzrastały z każdą dodatkową śnieżynką.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Jest taka historia o tym, jak student na seminarium rysuje kredą na tablicy dwa idealne okręgi. Nauczyciel dziwi się, jak udało mu się tak równo narysować bez cyrkla. Student odpowiada: „Bardzo prosto, przez dwa lata w armii kręciłem maszynkę do mięsa”.

Z tych czterech lat, w których biorę udział w tym projekcie, przez około dwa lata zajmuję się Terraform. I oczywiście mam pewne sztuczki, pewne porady, jak uprościć kod Terraform, pracować z nim jak z językiem programowania i zmniejszyć obciążenie dla deweloperów, którzy muszą utrzymywać ten kod w aktualnym stanie.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Pierwszą rzeczą, od której chciałbym zacząć, są Symlinks. Terraform ma wiele powtarzającego się kodu. Na przykład, wywołanie dostawcy praktycznie w każdym miejscu, gdzie tworzymy kawałek infrastruktury, jest takie samo. Dlatego logiczne jest wyodrębnienie go do osobnego folderu. A wszędzie tam, gdzie potrzebny jest dostawca, twórzmy symlinki do tego pliku.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Przykładowo, w produkcji używacie assume role, które pozwala wam uzyskać dostęp do jakiegoś zewnętrznego konta Amazon. Zmieniając jeden plik, wszystkie pozostałe w drzewie zasobów będą miały wymagane uprawnienia, aby Terraform wiedział, do którego segmentu Amazon się odwołać.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Gdzie symlinks nie działają? Jak już wspomniałem, w Terraformie są pliki stanu. I są one naprawdę super. Problem w tym, że Terraform inicjalizuje backend w pierwszej kolejności. I nie może używać w tych parametrach żadnych zmiennych, zawsze trzeba pisać tekstem.

W rezultacie, gdy ktoś tworzy nowy zasób, kopiuje część kodu z innych folderów. Może pomylić się z kluczem lub bucketem. Na przykład, tworzy coś w sandboxie, a potem robi w produkcji. I może się okazać, że bucket w produkcji będzie używany z sandboxu. Oczywiście, to szybko zauważą. Można to jakoś naprawić, ale mimo wszystko to strata czasu i w pewnym sensie zasobów.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Co możemy zrobić dalej? Przed rozpoczęciem pracy z Terraformem należy go zainicjalizować. W momencie inicjalizacji Terraform pobiera wszystkie wtyczki. W pewnym momencie z monolitu rozdzielono je na bardziej mikroserwisową architekturę. Zawsze trzeba wykonać Terraform init, aby pobrał wszystkie moduły i wtyczki.

Można używać skryptu shell, który, po pierwsze, może zebrać wszystkie zmienne. Skrypt shell jest nieograniczony. A po drugie, ścieżki. Jeśli zawsze używamy tej samej ścieżki, która w repozytorium jest kluczem do pliku stanu, to błąd w tym przypadku będzie wykluczony.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Skąd zdobyć dane? Plik JSON. Terraform pozwala zapisywać infrastrukturę nie tylko w hcl (HashiCorp Configuration Language), ale także w JSON.

JSON można łatwo odczytać ze skryptu shell. W związku z tym, można umieścić plik konfiguracyjny z bucketem w jakimś miejscu. I używać tego bucketu zarówno w kodzie Terraform, jak i w skrypcie shell do inicjalizacji.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Dlaczego ważne jest posiadanie bucketu dla Terraform? Ponieważ istnieje coś takiego jak zdalne pliki stanu. T. j. kiedy uruchamiam jakiś zasób, muszę powiedzieć Amazonowi: „Proszę, uruchom instance”, muszę wskazać wiele obowiązkowych parametrów.

I te identyfikatory są przechowywane w jakiś innych folderach. Mogę powiedzieć: „Terraform, pobiegnij, proszę, do pliku stanu tego zasobu i przynieś mi te identyfikatory”. W ten sposób powstaje pewna unifikacja między różnymi regionami czy środowiskami.

Nie zawsze można używać zdalnego pliku stanu. Na przykład, stworzyłeś VPC ręcznie. A kod Terraform, który tworzy VPC, tworzy tak różny VPC, że będziesz musiał spędzić dużo czasu na dostosowywaniu jednego do drugiego, więc można użyć następującego podejścia.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

T. j. zrobić moduł, który jakby tworzy VPC i jakby zwraca ci identyfikatory, a tak naprawdę jest tylko plik z zakodowanymi wartościami, który można wykorzystać do utworzenia tej samej instance.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Nie zawsze trzeba przechowywać plik stanu w chmurze. Na przykład, gdy testowane są moduły, można użyć inicjalizacji backendu, kiedy plik będzie przechowywany po prostu na dysku w czasie testowania.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Teraz trochę o testowaniu. Co można testować w Terraform? Pewnie wiele, ale ja będę mówił o tych 4 rzeczach.

HashiCorp ma zrozumienie, jak należy formatować kod Terraform. I Terraform fmt pozwala ci sformatować kod, który edytujesz zgodnie z tym przekonaniem. Zatem testy muszą koniecznie sprawdzić, czy formatowanie odpowiada temu, co zostawił HashiCorp, aby nie trzeba było zmieniać położenia nawiasów itd.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Następny to Terraform validate. On robi trochę więcej niż sprawdzenie składni – czyli, czy wszystkie nawiasy są parzyste. Co jest ważne? Nasza infrastruktura jest bardzo rozgałęziona. Jest w niej bardzo wiele różnych folderów. I w każdym z nich należy uruchomić Terraform validate.

Zatem, aby przyspieszyć testowanie, uruchamiamy kilka procesów równolegle, korzystając z równoległości.

Równoległość to bardzo fajna rzecz, korzystajcie.

Jednak za każdym razem, gdy inicjalizowany jest Terraform, udaje się on do HashiCorp i pyta: „Jakie są najnowsze wersje wtyczek? A ta wtyczka, którą mam w pamięci podręcznej – jest ona aktualna czy nie?”. I to na każdym kroku powodowało spowolnienie.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Jeśli podamy Terraform informację, gdzie znajdują się wtyczki, to powie: „Ok, prawdopodobnie to jest najnowsze, co mam. Nie będę nigdzie chodził, od razu zacznę weryfikować twój kod Terraform.”

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Aby zaopatrzyć folder w potrzebne wtyczki, mamy bardzo prosty kod Terraform, który wystarczy zainicjować. Oczywiście, należy wskazać wszystkich dostawców, którzy biorą udział w twoim kodzie, w przeciwnym razie Terraform powie: „Nie znam tego dostawcy, ponieważ go nie ma w pamięci podręcznej.”

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Następnie – Terraform plan. Jak już wspomniałem, rozwój jest cykliczny. Tworzymy kod z zmianami. A potem trzeba dowiedzieć się, jakie zmiany są planowane w infrastrukturze.

Gdy infrastruktura jest bardzo, bardzo duża, można zmienić jeden moduł, naprawić jakieś środowisko testowe lub konkretny region i zepsuć jakąś sąsiednią część. Dlatego Terraform plan powinien być tworzony dla całej infrastruktury i pokazywać, jakie zmiany są planowane.

Można to robić w mądry sposób. Na przykład napisaliśmy skrypt w Pythonie, który rozwiązuje zależności. W zależności od tego, co zostało zmienione: moduł Terraform lub po prostu jakiś konkretny komponent, tworzy plany dla wszystkich zależnych folderów.

Terraform plan powinien być wykonywany na żądanie. Przynajmniej to robimy my.

Testy, oczywiście, warto robić dla każdej zmiany, każdego commitu, ale plany – to dość kosztowna rzecz. I w prośbie o pull mówimy: „Proszę, daj mi plany”. Robot się uruchamia. I przesyła w komentarzach lub załącznikach wszystkie plany, które są przewidziane na podstawie twoich zmian.

Plan to dość kosztowna rzecz. Zajmuje czas, ponieważ Terraform udaje się do Amazonu i pyta: „Czy ten instance jeszcze istnieje? A te parametry autoskalowania są na pewno takie same?”. Aby to przyspieszyć, można użyć takiego parametru, jak refresh=false. To oznacza, że Terraform wyciągnie stan z S3. I uwierzy, że stan będzie dokładnie odpowiadał temu, co znajduje się w Amazonie.

Taki plan Terraform przebiega znacznie szybciej, ale stan musi odpowiadać twojej infrastrukturze, tzn. gdzieś, kiedyś musi być uruchomiony Terraform refresh. Terraform refresh robi dokładnie to, aby stan odpowiadał temu, co znajduje się w rzeczywistej infrastrukturze.

I trzeba powiedzieć o bezpieczeństwie. Od tego trzeba było zacząć. Tam, gdzie uruchamiasz Terraform i Terraform pracuje z twoją infrastrukturą, istnieje luka. Tzn. w zasadzie wykonujesz kod. I jeśli pull request zawiera jakiś złośliwy kod, to może on być wykonany w infrastrukturze, która ma zbyt dużo dostępu. Dlatego bądź ostrożny, gdzie uruchamiasz Terraform plan.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Następna rzecz, o której chciałbym mówić, to testowanie user-data.

Czym jest user-data? W Amazonie, gdy tworzymy instancję, możemy wysłać pewnego rodzaju wiadomość – metadane. Kiedy instancja się uruchamia, zwykle cloud init zawsze jest obecny na tych instancjach. Cloud init odczytuje tę wiadomość i mówi: „Ok, dzisiaj jestem load balancerem”. I zgodnie z tymi obietnicami wykonuje pewne działania.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Niestety, gdy wykonujemy Terraform plan i Terraform apply, user-data wygląda jak taka kasza z cyfr. Tzn. on po prostu wysyła ci hasz. I wszystko, co możesz zobaczyć w planie, to czy będą jakieś zmiany, czy hasz pozostanie ten sam.

I jeśli nie zwrócisz na to uwagi, to na Amazonie na rzeczywistą infrastrukturę może trafić jakiś zepsuty plik tekstowy.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Możesz również przy wykonywaniu określić tylko template, a w kodzie powiedzieć: „Proszę, wyświetl mi ten template”. W rezultacie możesz uzyskać wydruk, jak będą wyglądać twoje dane na Amazonie.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Inna opcja to użycie modułu do generowania user-data. Zastosujesz ten moduł. Otrzymasz plik na dysku. Porównasz go z referencyjnym. I w ten sposób, jeśli jakiś junior zdecyduje się nieco poprawić user-data, to twoje testy powiedzą: „Ok, tutaj i tutaj są jakieś zmiany – to w porządku”.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Następna rzecz, o której chciałbym mówić, to Automate Terraform apply.

Oczywiście, wystarczająco przerażające jest robienie Terraform apply w trybie automatycznym, ponieważ, kto wie, jakie zmiany zostały wprowadzone i jak mogą być szkodliwe dla żywej infrastruktury.

Dla środowiska testowego jest to całkiem w porządku. To znaczy, że zadanie, które tworzy środowisko testowe, jest tym, czego potrzebują wszyscy deweloperzy. A takie wyrażenie jak „u mnie wszystko działało” — to nie jest zabawny mem, lecz dowód na to, że osoba się z tym przyłożyła, uruchomiła stos, przeprowadziła na nim jakieś testy. I upewniła się, że wszystko jest w porządku, mówiąc: „Ok, ten kod, który wypuszczam, został przetestowany.”

W środowisku produkcyjnym, sandbox i innych środowiskach, które są bardziej istotne dla biznesu, można bezpiecznie stosować niektóre zasoby częściowo, ponieważ nie prowadzi to do sytuacji, w której ktoś umiera. To: grupy autoskalowania, grupy bezpieczeństwa, role, route53 i lista może być całkiem długa. Ale obserwuj, co się dzieje, czytaj raporty o automatycznych zastosowaniach.

Tam, gdzie stosowanie jest niebezpieczne lub budzi obawy, na przykład w przypadku zasobów z persistent i baz danych, należy uzyskiwać raporty na temat tego, że w jakiejś części infrastruktury są niezastosowane zmiany. I inżynier, już pod nadzorem, uruchamia zadania, aby je zastosować, albo robi to ze swojej konsoli.

W Amazonie istnieje coś takiego jak Terminate protection. I może ona chronić w niektórych przypadkach przed niepożądanymi zmianami. To znaczy, że Terraform poszedł na Amazona i mówi: „Muszę zabić ten instance, aby stworzyć inny.” A Amazon mówi: „Przykro mi, nie dzisiaj. Mamy włączoną ochronę przed usunięciem.”

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

A wisienką na torcie jest optymalizacja kodu. Kiedy pracujemy z kodem Terraform, musimy przekazać do modułu bardzo dużą liczbę parametrów. To te parametry, które są niezbędne do stworzenia jakiegoś zasobu. A kod zamienia się w dużą listę parametrów, które trzeba przekazać z modułu do modułu, z modułu do modułu, zwłaszcza gdy moduły są zagnieżdżone.

I to jest bardzo trudne do przeczytania. Trudno to poddać przeglądowi. I bardzo często zdarza się, że niektóre parametry przechodzą przegląd, a nie są do końca tymi, które są potrzebne. A to kosztuje czas i pieniądze, aby później to poprawić.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Dlatego proponuję używać czegoś takiego jak złożony parametr, który zawiera pewne drzewo wartości. To znaczy, że potrzebna jest jakaś folder, w którym wskazane są wszystkie wartości, które chciałbyś mieć w jakimś środowisku.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Wywołując ten moduł, można uzyskać drzewo, które jest generowane w jednym wspólnym module, tzn. w wspólnym module, który działa identycznie dla całej infrastruktury.

W tym module można wykonać pewne obliczenia, korzystając z nowej funkcji w Terraform, jaką są locals. A następnie jednym output’em można zwrócić skomplikowany parametr, który może zawierać hashe, tablice itp.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Na tym kończą się wszystkie najlepsze znaleziska, które mam. Chciałbym opowiedzieć anegdotę o Kolumbie. Kiedy szukał pieniędzy na swoją ekspedycję, by odkryć Indie (jak wtedy myślał), nikt mu nie wierzył i sądzono, że to niemożliwe. Wtedy powiedział: „Zróbcie tak, aby jajko nie upadło”. Wszyscy bankierzy, bardzo bogaci i prawdopodobnie mądrzy ludzie, starali się w jakiś sposób postawić jajko, a ono ciągle upadało. Wtedy Kolumb wziął jajko, lekko na nie nacisnął. Skorupka się zgnieściła, a jajko pozostało nieruchome. Powiedzieli: „O, to zbyt proste!”. A Kolumb odpowiedział: „Tak, to zbyt proste. I kiedy odkryję Indie, wszyscy będą korzystać z tej trasy handlowej.”

To, co wam teraz opowiedziałem, to prawdopodobnie dość proste i trywialne rzeczy. I gdy o nich się dowiesz i zaczynasz je używać, to jest w porządku. Więc korzystajcie. A jeśli są to dla was normalne rzeczy, to przynajmniej wiecie, jak postawić jajko, aby nie upadło.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Podsumujmy:

  • Staraj się unikać śnieżynek. Im mniej śnieżynek, tym mniej zasobów potrzebujesz, aby wprowadzać zmiany w całej swojej dużej infrastrukturze.
  • Ciągłe zmiany. Tzn. gdy w kodzie zaszły jakieś zmiany, należy jak najszybciej dostosować swoją infrastrukturę do tych zmian. Nie może być sytuacji, aby ktoś po dwóch-trzech miesiącach przyszedł, by sprawdzić Elasticsearch, zrobił Terraform plan, a tam była masa zmian, których się nie spodziewał. I poświęca się bardzo dużo czasu, aby przywrócić wszystko do porządku.
  • Testy i automatyzacja. Im więcej twojego kodu jest objętego testami i funkcjami, tym większa pewność, że wszystko robisz poprawnie. A automatyczna dostawa wielokrotnie zwiększy twoją pewność.
  • Kod dla środowiska testowego i produkcyjnego powinien być praktycznie identyczny. Praktycznie, ponieważ jednak produkcja jest trochę inna i zawsze będą jakieś niuanse, które wykraczają poza środowisko testowe. Niemniej jednak, można to zapewnić z pewnym marginesem.
  • Jeśli macie dużo kodu Terraform, a utrzymanie go w aktualnym stanie zajmuje dużo czasu, nigdy nie jest za późno na refaktoryzację i doprowadzenie go do dobrej formy.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

  • Niezmienna infrastruktura. Dostarczanie AMI według harmonogramu.
  • Struktura dla route53, gdy macie wiele rekordów i chcecie, aby były uporządkowane w sposób spójny.
  • Walcząc z ograniczeniami API rate limits. To wtedy Amazon mówi: „Dość, nie mogę już przyjmować więcej zapytań, proszę poczekać”. I połowa firmy czeka, aż będzie mogła uruchomić swoją infrastrukturę.
  • Instancje ratunkowe. Amazon to nie jest tania zabawa, a spoty pozwalają zaoszczędzić sporą sumę. Można o tym mówić przez cały wykład.
  • Bezpieczeństwo i role IAM.
  • Wyszukiwanie zagubionych zasobów, gdy macie w Amazone instancje o nieznanym pochodzeniu, które konsumują pieniądze. Nawet jeśli instancja kosztuje 100-150 dolarów miesięcznie – w skali roku to ponad 1 000. Wyszukiwanie takich zasobów to korzystna sprawa.
  • I zarezerwowane instancje.

Wzorce w Terraform do walki z chaosem i ręczną rutyną. Maksym Kostrikin (Ixtens)

Na tym kończę. Terraform to naprawdę świetna rzecz, korzystajcie. Dziękuję!

Pytania

Dziękuję za prezentację! Macie plik stanu w S3, a jak rozwiązujecie problem, że kilka osób może wziąć ten plik stanu i próbować się rozwinąć?

Po pierwsze, nie spieszymy się. Po drugie, istnieją flagi, w których informujemy, że pracujemy nad jakimś fragmentem kodu. To znaczy, że mimo iż infrastruktura jest bardzo duża, nie oznacza to, że stale ktoś coś wdraża. Kiedy była aktywna faza – to był problem, mieliśmy pliki stanu w Gicie. To było ważne, inaczej ktoś obsłużyłby plik stanu, i musieliśmy ręcznie je zbierać w jednym miejscu, aby wszystko mogło dalej trwać. Teraz takiego problemu nie ma. W ogóle, Terraform rozwiązał ten problem. A jeśli coś się stale zmienia, można używać blokad, które zapobiegają tym problemom.

Używacie wersji otwartej czy enterprise?

Żadnego enterprise, to znaczy wszystko, co można pobrać za darmo.

Nazywam się Stanisław. Chciałem dodać małe uzupełnienie. Mówiłeś o funkcji Amazon, która pozwala na stworzenie niezniszczalnego instance. To jest również dostępne w samym Terraformie; w bloku Life Second można zdefiniować zakaz zmian lub zakaz usunięcia.

Czas był ograniczony. Dobre spostrzeżenie.

Chciałem zapytać o dwie rzeczy. Po pierwsze, mówiłeś o testowaniu. Czy korzystałeś z jakichś narzędzi do testowania? Słyszałem o wtyczce Test Kitchen. Może jest coś jeszcze. I chciałbym jeszcze zapytać o Local Values. Czym one się w zasadzie różnią od Input Variables? I dlaczego nie mogę parametryzować czegoś tylko przez Local Values? Próbowałem zrozumieć ten temat, ale jakoś mi to nie wyszło.

Możemy porozmawiać o tym bardziej szczegółowo poza tą salą. Narzędzia do testowania mamy na własną rękę. Nie ma tam nic, co moglibyśmy przetestować. W ogóle są opcje, kiedy automatyczne testy uruchamiają infrastrukturę, sprawdzają, czy wszystko jest w porządku, a potem wszystko niszczą z raportem, że twoja infrastruktura wciąż jest w dobrej kondycji. U nas tego nie ma, ponieważ testowe stosy uruchamiają się codziennie. I to wystarcza. A jeśli coś zaczyna się psuć, to zacznie się psuć niezależnie od tego, czy to jeszcze gdzieś sprawdzimy.

Odnośnie Local Values, kontynuujmy rozmowę poza salą.

Cześć! Dziękuję za prezentację! Bardzo pouczające. Mówiłeś, że macie bardzo dużo jednorodnego kodu do opisu infrastruktury. Czy nie rozważaliście możliwości generowania tego kodu?

Świetne pytanie, dziękuję! Chodzi o to, że gdy używamy infrastruktury jako kodu, zakładamy, że patrzymy na kod i rozumiemy, jaka infrastruktura za tym kodem stoi. Jeśli kod jest generowany, musimy wyobrazić sobie, jaki kod zostanie wygenerowany, aby zrozumieć, jaka infrastruktura się tam znajduje. Albo generujemy kod, commitujemy go i właściwie wychodzi to samo. Dlatego poszliśmy tym krokiem, jak to napisaliśmy, to otrzymaliśmy. Poza tym generatory pojawiły się nieco później, gdy zaczęliśmy działać. Już było za późno na zmiany.

Słyszałeś coś o jsonnet?

Nie.

Zobacz, to naprawdę świetna rzecz. Widzę konkretny przypadek, w którym można to zastosować i generować strukturę danych.

Generatory są dobre, kiedy masz sytuację jak w dowcipie o maszynie do golenia. To znaczy, za pierwszym razem twarz jest różna, ale potem wszyscy mają tę samą twarz. Generatory bardzo dobrze się sprzedają. Ale niestety, mamy trochę różne twarze. To jest problem.

Po prostu spójrz. Dziękuję!

Mam na imię Maksym, jestem z Sberbanku. Trochę opowiedziałeś, że próbowałeś dostosować Terraform do analogii języka programowania. Nie prościej korzystać z Ansible?

To bardzo różne rzeczy. Można i w Ansible tworzyć zasoby, i Puppet może tworzyć zasoby w Amazonie. Ale Terraform jest do tego doskonale przystosowany.

Macie tylko Amazon?

Chodzi nie o to, że mamy tylko Amazon. Mamy prawie tylko Amazon. Ale kluczową cechą jest to, że Terraform pamięta. W Ansible, jeśli powiesz: „Utwórz mi 5 instancji”, to utworzy, a potem mówisz: „A teraz potrzebuję 3”. I Terraform powie: „Ok, 2 usunę”, a Ansible powie: „Ok, oto 3”. W sumie 8.

Cześć! Dziękuję za twoje wystąpienie! Bardzo interesująco było posłuchać o Terraformie. Od razu chciałbym dodać mały komentarz na temat tego, że Terraform wciąż nie ma stabilnej wersji, dlatego z dużą ostrożnością podchodźcie do Terraformu.

Dobrze mieć łyżkę do obiadu. To znaczy, jeśli potrzebujesz rozwiązania, to czasami odkładasz to, co jest niestabilne itd., ale działa i nam pomogło.

Pytanie takie. Używacie Remote backend, używacie S3. Dlaczego nie używacie oficjalnego backendu?

Oficjalnego?

Terraform Cloud.

Kiedy się pojawił?

4 miesiące temu.

Gdyby pojawił się 4 lata temu, to pewnie odpowiedziałbym na twoje pytanie.

Tam jest już wbudowana funkcja i blokady, i można przechowywać plik stanie. Spróbuj. Ale też tego nie testowałem.

Podróżujemy dużym pociągiem, który jedzie z dużą prędkością. I nie można po prostu wziąć i wyrzucić kilku wagonów.

Mówiłeś o śnieżynkach, a dlaczego nie użyliście branży? Dlaczego nie udało się tak zrobić?

Mamy takie podejście, że cała infrastruktura jest w jednym repozytorium. Terraform, Puppet, wszystkie skrypty, które jakoś się do tego odnoszą, są w jednym repozytorium. W ten sposób możemy zapewnić, że zmiany inkrementalne są testowane jedna po drugiej. Gdyby było wiele gałęzi, taki projekt byłby praktycznie niemożliwy do utrzymania. Mijają pół roku, a one מאוד się rozchodzą, że to po prostu jakieś ukaranie. To jest to, od czego chcieliśmy uciekać przed refaktoryzacją.

To znaczy, to nie działa?

To w ogóle nie działa.

W branchu usunąłem slajd folderu. Tzn. jeśli zrobimy dla każdego testowego stosu, na przykład, zespół A – ma swój folder, zespół B ma swój folder, to również nie działa. Stworzyliśmy zunifikowany kod środowiska testowego, który był wystarczająco elastyczny, aby pasować do wszystkich. Tzn. obsługiwaliśmy jeden kod.

Cześć! Nazywam się Jura! Dziękuję za prezentację! Pytanie dotyczące modułów. Mówicie, że używacie modułów. Jak rozwiązujecie problem, jeśli w jednym module wprowadzone są zmiany, które nie są zgodne z zamianami innej osoby? W jakiś sposób wersjonujecie moduły, czy próbujecie dostosować wun­derwa­flę, aby spełnić dwa wymagania?

To problem dużej kuli śnieżnej. To, czego doświadczamy, gdy jakieś niegroźne zmiany mogą złamać część infrastruktury. I to będzie zauważalne dopiero po dłuższym czasie.

Tzn. na razie nic się nie rozwiązuje?

Robicie uniwersalne moduły. Unikajcie płatków śniegu. I wszystko będzie w porządku. Druga połowa prezentacji jest o tym, jak to uniknąć.

Dzień dobry! Dziękuję za prezentację! Chciałbym dopytać. Za kulisami została duża kupa, dla której przyszedłem. W jaki sposób zintegrowane są Puppet i przydzielanie ról?

User-data.

Tzn. po prostu wyrzucacie plik i jakoś go wykonujecie?

User-data – to notatka, tzn. kiedy robimy klon obrazu, to uruchamia się Daemon i próbując zrozumieć, kim jest, czyta notatkę, że jest load balancerem.

Tzn. to jakiś oddzielny proces, który jest przekazywany?

Nie my go wynaleźliśmy. Korzystamy z niego.

Dzień dobry! Mam pytanie dotyczące User-data. Powiedzieliście, że są problemy, że ktoś może coś nie tam przekazać. Czy jest jakiś sposób przechowywania user-data w tym samym Gicie, aby zawsze było jasne, do czego odnosi się User-data?

Generujemy User-data z template. To znaczy, że pojawia się tam pewna liczba zmiennych. A Terraform generuje ostateczny wynik. Dlatego nie można po prostu spojrzeć na template i powiedzieć, co wyjdzie, ponieważ wszystkie problemy są związane z tym, że deweloper myśli, że przekazuje tam ciąg, a tam przychodzi tablica. I ma – bum i ja – ten, ten, następny ciąg, i wszystko się rozpadło. Jeśli to jest nowy zasób i osoba go uruchamia, widzi, że coś nie działa, to szybko można to rozwiązać. A jeśli zaktualizowała się grupa autoscale, to w pewnym momencie instancje w grupie autoscale zaczynają się zamieniać. I hop, coś nie działa. To jest frustrujące.

Czyli jedynym rozwiązaniem jest testowanie?

Tak, widzisz problem, dodajesz tam kroki testowe. To znaczy, że również output można testować. Może nie jest to tak wygodne, ale można też postawić jakieś znaczniki – sprawdzaj, czy User-data jest tu przybita gwoździami.

Mam na imię Timur. Bardzo fajnie, że są prezentacje o tym, jak poprawnie organizować Terraform.

Nawet jeszcze nie zacząłem.

Myślę, że na następnej konferencji, może być. Mam proste pytanie. Dlaczego hardcodujesz wartość w oddzielnym module, zamiast używać tfvars, to znaczy, czym lepszy moduł z wartościami, niż tfvars?

To znaczy, że muszę tutaj (slajd: Production/environment/settings.tf) napisać: domain = zmienna, domain vpcnetwork, zmienna vpcnetwork i stvars – wyciągnąć to samo?

Robimy to dokładnie tak samo. Odwołujemy się do modułu setting source, na przykład.

W istocie to taki tfvars. Tfvars jest bardzo wygodny w środowisku testowym. Mam tfvars dla dużych instancji, dla małych. I wrzuciłem jeden plik do folderu. I otrzymałem to, co chciałem. Kiedy budujemy infrastrukturę, chcemy, żeby można było spojrzeć i od razu wszystko zrozumieć. A tak to wychodzi, że trzeba spojrzeć tutaj, potem spojrzeć w tfvars.

Czyli, żeby wszystko było w jednym miejscu?

Tak, tfvars – to wtedy, gdy masz jeden kod. I jest on używany w kilku różnych miejscach z różnymi niuansami. Wtedy wrzuciłbyś tfvars i uzyskał swoje niuanse. A my – to infrastruktura jako kod w czystej postaci. Spojrzałeś i zrozumiałeś.

Cześć! Czy zdarzały się Wam sytuacje, w których dostawca chmury ingerował w to, co zrobiliście za pomocą Terraform? Załóżmy, że edytujemy metadane. Są tam klucze ssh. A Google ciągle wrzuca tam swoje metadane, swoje klucze. I Terraform zawsze informuje, że ma zmiany. Po każdym uruchomieniu, nawet jeśli nic się nie zmienia, zawsze mówi, że zaktualizuje to pole.

Z kluczami, ale – tak, część infrastruktury jest dotknięta tym problemem, to znaczy, że Terraform nic nie może zmienić. My sami też nic nie możemy zmienić. Na razie żyjemy z tym.

To znaczy, że mieliście z tym do czynienia, ale nic nie wymyśliliście, on po prostu robi to sam?

Niestety, tak.

Cześć! Nazywam się Stanisław Starkow. Mail. ru Group. Jak rozwiązujecie problem z generowaniem tagu na …, jak go przesyłacie? Rozumiem, że przez User—data, aby wskazać nazwę hosta, wskazać Puppet? A druga część pytania. Jak rozwiązujecie ten problem w SG, tzn. kiedy generujecie SG, setki jednorodnych instancji, jak je właściwie nazwać?

Te instancje, które są dla nas bardzo ważne, nazywamy ładnie. Te, które nie są potrzebne, mają dopisek, że to grupa autoskalowania. I teoretycznie można je usunąć, aby uzyskać nową.

Jeśli chodzi o problem z tagiem, to nie chodzi o problem, a o zadanie. Tagi są u nas bardzo, bardzo intensywnie używane, ponieważ infrastruktura jest duża i kosztowna. Musimy monitorować, na co wydawane są pieniądze, dlatego tagi umożliwiają rozdzielenie, co i gdzie poszło. I w konsekwencji wyszukiwanie, gdzie wydawane są duże kwoty.

O co jeszcze był pytanie?

Kiedy SG tworzy setki instancji, trzeba je jakoś odróżniać?

Nie, nie trzeba. Na każdej instancji jest agent, który informuje, że mam problem. Jeśli agent zgłasza, to on o nim wie i, przynajmniej, jego adres IP istnieje. Już można działać. Po drugie, używamy Consul do odkrywania, tam, gdzie nie ma Kubernetes. I Consul także pokazuje adres IP instancji.

To znaczy, że opieracie się na IP, a nie na nazwie hosta?

Nie można opierać się na nazwie hosta, to znaczy, że jest ich bardzo wiele. Są identyfikatory instancji – AE itd. Można je gdzieś znaleźć, można je wrzucić do wyszukiwarki.

Cześć! Zrozumiałem, że Terraform to świetna rzecz, dostosowana do chmur.

Nie tylko.

To mnie właśnie interesuje. Co jeśli zdecydujecie się na masowe przejście na Bare Metal ze wszystkimi swoimi instancjami? Czy nie będzie żadnych problemów? A może jednak będziecie musieli użyć innych produktów, jak wspomniany tu Ansible?

Ansible dotyczące czegoś innego. To znaczy, Ansible działa, gdy instancja jest uruchomiona. Terraform działa przed uruchomieniem instancji. Przejście na Bare Metal - nie.

Teraz nie, ale przyjdzie biznes i powie: „Dajmy spokój”.

Przejście do innej chmury - tak, ale tu trzeba to zrealizować w inny sposób. Trzeba napisać kod Terraform tak, aby z mniejszym trudem można było przejść do innej chmury.

Początkowo postawiono sobie cel, aby nasza cała infrastruktura była agnostyczna, czyli każda chmura powinna pasować, ale pewnego dnia biznes się poddał i powiedział: „Ok, przez najbliższe N lat nigdzie nie odejdziemy, można korzystać z usług Amazonu”.

Terraform pozwala tworzyć w Front-End zadania, konfigurować PagerDuty, dokumenty danych itd. Ma naprawdę wiele możliwości. Może praktycznie kontrolować cały świat.

Dziękuję za prezentację! Ja również od 4 lat pracuję z Terraform. Na etapie płynnego przejścia do Terraform, do infrastruktury, do deklaratywnego opisu, napotykaliśmy sytuacje, gdy ktoś coś robił ręcznie, a Ty próbowałeś zrobić plan. I otrzymywałeś tam jakiś błąd. Jak rozwiązujecie takie problemy? Jak znajdziecie zagubione zasoby, które były wskazane?

Głównie ręcznie i wzrokowo, jeśli widzimy w raporcie coś dziwnego, analizujemy, co tam się dzieje, albo po prostu usuwamy. A tak w ogóle, pull requesty to standard.

Jeśli wystąpi błąd, czy robicie rollback? Próbowaliście coś takiego robić?

Nie, to decyzja człowieka w danej chwili, gdy widzi problem.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster