Terraformer — infrastruktura do kodowania

Terraformer — infrastruktura do kodowania
Chciałbym opowiedzieć o nowym narzędziu CLI, które napisałem, aby rozwiązać stary problem.

problem

Terraform od dawna jest standardem w społeczności Devops/Cloud/IT. Jest to bardzo wygodne i przydatne do radzenia sobie z infrastrukturą jako kodem. W Terraformie jest wiele przysmaków, a także wiele widelców, ostrych noży i grabi.
Dzięki Terraform bardzo wygodnie jest tworzyć nowe rzeczy, a następnie zarządzać nimi, zmieniać je lub usuwać. Co powinni zrobić ci, którzy posiadają ogromną infrastrukturę w chmurze, a nie stworzoną poprzez Terraform? Przepisanie i ponowne utworzenie całej chmury jest w jakiś sposób kosztowne i niebezpieczne.
Napotkałem ten problem przy 2 zadaniach, najprostszym przykładem jest sytuacja, gdy chcesz, aby wszystko było w Git w postaci plików terraform, ale masz ponad 250 segmentów i ręczne zapisywanie ich w terraformie to dużo.
Jest problem od 2014 roku w terrafomie, który został zamknięty w 2016 roku z nadzieją, że będzie import.

Ogólnie wszystko jest jak na zdjęciu tylko od prawej do lewej

Ostrzeżenia: Autor przez połowę swojego życia nie mieszka w Rosji i niewiele pisze po rosyjsku. Uważaj na błędy ortograficzne.

Solutions

1. Istnieje gotowe i stare rozwiązanie dla AWS terraformowanie. Kiedy próbowałem przepuścić przez to ponad 250 wiader, zdałem sobie sprawę, że wszystko jest tam złe. AWS od dawna wprowadza mnóstwo nowych opcji, ale terraforming o nich nie wie i w ogóle jest rubinowo szablon wygląda na rzadki. Po 2 w nocy wysłałem Prośba o pociągnięcie dodać tam więcej funkcji i zdałem sobie sprawę, że takie rozwiązanie w ogóle nie jest odpowiednie.
Jak działa terraforming: pobiera dane z AWS SDK i generuje tf i tfstate za pomocą szablonu.
Są tu 3 problemy:
1. Zawsze będą występować opóźnienia w aktualizacjach
2. Pliki tf czasami wychodzą uszkodzone
3. stan tf jest zbierany oddzielnie od stanu tf i nie zawsze jest zbieżny
Ogólnie rzecz biorąc, trudno uzyskać wynik, w którym „plan terraformowy” mówi, że nie ma żadnych zmian

2. `terraform import` to polecenie wbudowane w terraform. Jak to działa?
Piszesz pusty plik TF z nazwą i typem zasobu, następnie uruchamiasz `terraform import` i przekazujesz identyfikator zasobu. terraform kontaktuje się z dostawcą, odbiera dane i tworzy plik tfstate.
Są tu 3 problemy:
1. Dostajemy tylko plik tfstate, a tf jest pusty, trzeba go napisać ręcznie lub przekonwertować z tfstate
2. Może pracować tylko z jednym zasobem na raz i nie obsługuje wszystkich zasobów. I co mam znowu zrobić z ponad 250 wiadrami?
3. Musisz znać ID zasobów - czyli opakować je w kod pobierający listę zasobów
Ogólnie rzecz biorąc, wynik jest częściowy i nie jest dobrze skalowany

Moja decyzja

wymagania:
1. Możliwość tworzenia plików tf i tfstate dla zasobów. Na przykład pobierz wszystkie zasobniki/grupę zabezpieczeń/system równoważenia obciążenia, a „plan terraform” zwrócił informację, że nie ma żadnych zmian
2. Potrzebujesz 2 chmur GCP + AWS
3. Globalne rozwiązanie, które można łatwo zaktualizować za każdym razem i nie marnować czasu na każdy zasób przez 3 dni pracy
4. Zrób to jako Open Source – wszyscy mają ten sam problem

Język Go jest tym, za co go uwielbiam i ma bibliotekę do tworzenia plików HCL używanych w terraformie + dużo kodu w terraformie, który może być przydatny

Ścieżka

Pierwsza próba
Zacząłem od prostej wersji. Kontaktowanie się z chmurą za pośrednictwem SDK w celu uzyskania wymaganego zasobu i przekształcenie go w pola dla terraformu. Próba zakończyła się natychmiastowym niepowodzeniem w grupie bezpieczeństwa, ponieważ nie podobało mi się 1.5 dnia na konwersję tylko grupy bezpieczeństwa (a jest dużo zasobów). Przez dłuższy czas pola można zmieniać/dodawać

Drugie podejście
Na podstawie opisanego pomysłu tutaj. Po prostu weź i przekonwertuj tfstate na tf. Znajdują się tam wszystkie dane, a pola są takie same. Jak uzyskać pełny stan tf dla wielu zasobów? Tutaj z pomocą przyszła komenda `terraform Refresh`. terraform pobiera wszystkie zasoby w tfstate i według identyfikatora pobiera z nich dane i zapisuje wszystko w tfstate. Oznacza to, że utwórz pusty stan tf zawierający tylko nazwy i identyfikatory, uruchom `terraform Refresh` i wtedy otrzymamy pełne stany tf. Brawo!
Teraz zróbmy rekursywną pornografię polegającą na pisaniu konwertera tfstate na tf. Dla tych, którzy nigdy nie czytali tfstate, jest to JSON, ale wyjątkowy.
Oto jego ważna część atrybutów

 "attributes": {
                            "id": "default/backend-logging-load-deployment",
                            "metadata.#": "1",
                            "metadata.0.annotations.%": "0",
                            "metadata.0.generate_name": "",
                            "metadata.0.generation": "24",
                            "metadata.0.labels.%": "1",
                            "metadata.0.labels.app": "backend-logging",
                            "metadata.0.name": "backend-logging-load-deployment",
                            "metadata.0.namespace": "default",
                            "metadata.0.resource_version": "109317427",
                            "metadata.0.self_link": "/apis/apps/v1/namespaces/default/deployments/backend-logging-load-deployment",
                            "metadata.0.uid": "300ecda1-4138-11e9-9d5d-42010a8400b5",
                            "spec.#": "1",
                            "spec.0.min_ready_seconds": "0",
                            "spec.0.paused": "false",
                            "spec.0.progress_deadline_seconds": "600",
                            "spec.0.replicas": "1",
                            "spec.0.revision_history_limit": "10",
                            "spec.0.selector.#": "1",

Jest:
1. identyfikator - ciąg znaków
2. metadane - tablica o rozmiarze 1, a w niej obiekt z polami, co opisano poniżej
3. spec - skrót o rozmiarze 1 i klucz, w którym znajduje się wartość
Krótko mówiąc, zabawny format, wszystko może mieć kilka poziomów głębokości

                   "spec.#": "1",
                            "spec.0.min_ready_seconds": "0",
                            "spec.0.paused": "false",
                            "spec.0.progress_deadline_seconds": "600",
                            "spec.0.replicas": "1",
                            "spec.0.revision_history_limit": "10",
                            "spec.0.selector.#": "1",
                            "spec.0.selector.0.match_expressions.#": "0",
                            "spec.0.selector.0.match_labels.%": "1",
                            "spec.0.selector.0.match_labels.app": "backend-logging-load",
                            "spec.0.strategy.#": "0",
                            "spec.0.template.#": "1",
                            "spec.0.template.0.metadata.#": "1",
                            "spec.0.template.0.metadata.0.annotations.%": "0",
                            "spec.0.template.0.metadata.0.generate_name": "",
                            "spec.0.template.0.metadata.0.generation": "0",
                            "spec.0.template.0.metadata.0.labels.%": "1",
                            "spec.0.template.0.metadata.0.labels.app": "backend-logging-load",
                            "spec.0.template.0.metadata.0.name": "",
                            "spec.0.template.0.metadata.0.namespace": "",
                            "spec.0.template.0.metadata.0.resource_version": "",
                            "spec.0.template.0.metadata.0.self_link": "",
                            "spec.0.template.0.metadata.0.uid": "",
                            "spec.0.template.0.spec.#": "1",
                            "spec.0.template.0.spec.0.active_deadline_seconds": "0",
                            "spec.0.template.0.spec.0.container.#": "1",
                            "spec.0.template.0.spec.0.container.0.args.#": "3",

Generalnie jeśli ktoś chce mieć problem programistyczny na rozmowę kwalifikacyjną to niech po prostu poprosi o napisanie parsera do tego zadania :)
Po wielu próbach napisania parsera bez błędów, znalazłem jego część w kodzie terraforma i to najważniejszą. I wszystko wydawało się działać dobrze

Próba trzecia
dostawcy terraform to pliki binarne zawierające kod ze wszystkimi zasobami i logiką do pracy z interfejsem API chmury. Każda chmura ma własnego dostawcę, a sam terraform wywołuje je tylko poprzez swój protokół RPC między dwoma procesami.
Teraz zdecydowałem się skontaktować z dostawcami terraform bezpośrednio za pośrednictwem wywołań RPC. Wyszło pięknie i umożliwiło zmianę dostawców terraform na nowszych i uzyskanie nowych funkcji bez zmiany kodu. Okazuje się również, że nie wszystkie pola w tfstate powinny znajdować się w tf, ale jak możesz się tego dowiedzieć? Po prostu zapytaj o to swojego dostawcę. Potem rozpoczęła się kolejna rekursywna pornografia polegająca na składaniu wyrażeń regularnych, poszukująca pól wewnątrz stanu tfstate na wszystkich poziomach głębokości.

Ostatecznie otrzymaliśmy przydatne narzędzie CLI, które ma wspólną infrastrukturę dla wszystkich dostawców terraform i można łatwo dodać nowe. Ponadto dodawanie zasobów zajmuje niewiele kodu. Plus wszelkiego rodzaju gadżety, takie jak połączenia między zasobami. Oczywiście problemów było wiele i nie da się ich wszystkich opisać.
Nazwałem zwierzę Terrafomer.

Finał

Używając Terrafomeru, wygenerowaliśmy 500-700 tysięcy linii kodu tf+tfstate z dwóch chmur. Mogliśmy wziąć starsze rzeczy i zacząć je dotykać tylko poprzez terraformę, tak jak w najlepszej infrastrukturze, jako pomysły na kod. To po prostu magia, gdy bierzesz ogromną chmurę i otrzymujesz ją od zespołu w postaci plików pracowników terraform. A potem grep/replace/git i tak dalej.

Przeczesałem to i uporządkowałem, dostałem pozwolenie. Wydano go na GitHub dla wszystkich w czwartek (02.05.19). github.com/GoogleCloudPlatform/terraformer
Otrzymałem już 600 gwiazdek, 2 prośby o ściągnięcie za dodanie obsługi openstack i kubernetes. Dobra opinia. Ogólnie rzecz biorąc, projekt jest przydatny dla ludzi
Radzę każdemu, kto chce rozpocząć pracę z Terraformem i nie przepisywać wszystkiego od nowa.
Chętnie wyciągnę prośby, problemy, gwiazdki.

Демо
Terraformer — infrastruktura do kodowania

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

Dodaj komentarz