Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Źródło: https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/small-terraform
Ten przykład zawiera kod dla strukturyzacji konfiguracji Terraform dla małego rozmiaru infrastruktury, w której nie są używane zależności zewnętrzne.
Idealny na początek i gdy refaktoryzacja na bieżąco jest możliwa
Idealny do modułów z małymi zasobami
Dobry dla małych i liniowych modułów infrastruktury (np. terraform-aws-atlantis)
Dobry dla małej liczby zasobów (mniej niż 20-30)
Plik jednego stanu dla wszystkich zasobów może spowolnić proces pracy z Terraform. Jeśli liczba zasobów rośnie, rozważ użycie argumentu -target
, aby je ograniczyć.
Pytania dotyczące struktury kodu są zdecydowanie najczęściej zadawanymi w społeczności Terraform. W pewnym momencie każdy zaczyna się zastanawiać co dla projektu będzie najlepsze.
To jedno z pytań, na które jest wiele odpowiedzi, lecz bardzo trudno jest udzielić uniwersalnych porad, więc postarajmy się zacząć od zrozumienia z czym mamy do czynienia.
Jaka jest złożoność Twojego projektu?
Liczba powiązanych zasobów
Liczba użytych dostawców Terraform (uwaga — patrz poniżej na temat „dostawców logicznych” (logical providers))
Jak często zmienia się Twoja infrastruktura?
Zaczynając od raz w miesiącu/tygodniu/codziennie
Skończywszy na ciągłym (za każdym razem, gdy pojawia się nowa zmiana (commit))
Kto lub co zmienia kod? Czy pozwalasz serwerowi CI aktualizować repozytorium po zbudowaniu nowego artefaktu?
Tylko programiści mogą wysyłać kod do repozytorium infrastruktury
Każdy może proponować zmiany, otwierając pull-requesty (w tym automatyczne zadania uruchomione na serwerze CI)
Z jakiej platformy lub usługi wdrożeniowej korzystasz?
AWS CodeDeploy, Kubernetes czy OpenShift wymagają nieco innych podejść
Jak grupowane są środowiska?
Według środowiska, regionu, projektu
Umieszczenie całego kodu w pliku main.tf
jest dobrym pomysłem, jeśli dopiero zaczynasz swoją przygodę z Terraform lub piszesz testowy kod, aby coś zweryfikować. We wszystkich innych przypadkach lepiej będzie mieć kilka plików podzielonych logicznie w następujący sposób:
main.tf
— wywoływanie modułów, zmienny lokalnych i źródeł danych w celu utworzenia wszystkich zasobów
variables.tf
— zawiera deklaracje zmiennych używanych w main.tf
outputs.tf
— zawiera dane wyjściowe z zasobów utworzonych w main.tf
versions.tf
— zawiera wymagania dotyczące wersji dla Terraform i dostawców
Plik terraform.tfvars
nie powinien być używany poza kompozycją.
Upewnij się, że rozumiesz kluczowe pojęcia — moduł zasobu, moduł infrastruktury i kompozycja, gdyż są one używane w poniższych przykładach.
Łatwiej i szybciej pracuje się z mniejszą liczbą zasobów
komendy terraform plan
i terraform apply
wykonują wywołania API, aby zweryfikować status zasobów
Jeśli masz całą infrastrukturę w jednej kompozycji, może to zająć trochę czasu
Promień rażenia jest mniejszy przy mniejszej ilości zasobów
Odizolowanie od siebie niepowiązanych zasobów poprzez umieszczenie ich w oddzielnych kompozycjach zmniejsza ryzyko, jeśli coś pójdzie nie tak
Rozpocznij swój projekt od użycia stanu zdalnego (remote state), ponieważ:
Twój laptop nie jest odpowiednim miejscem na źródło prawdy (source of truth) o Twojej infrastrukturze
Zarządzanie plikiem tfstate
w repozytorium git to koszmar
Później, gdy warstwy infrastruktury zaczną rosnąć w wielu kierunkach (liczba zależności lub zasobów) łatwiej będzie mieć wszystko pod kontrolą
Ćwicz pisanie spójnej struktury i praktykuj zachowywanie konwencji nazewnictwa:
Podobnie jak przy kodzie proceduralnym, kod Terraform powinien być napisany tak, aby w pierwszej kolejności mogli go przeczytać ludzie. Zachowanie porządku pomoże, kiedy trzeba będzie wrócić do zmian sprzed pół roku.
Przenoszenie zasobów w pliku stanu Terraform jest możliwe, ale może to być trudniejsze, jeśli masz niespójną strukturę i nazewnictwo
Zachowaj moduły zasobów tak proste, jak to możliwe
Nie "hardkoduj" wartości, które mogą być przekazywane jako zmienne lub uzyskane przy użyciu źródeł danych
Użyj źródeł danych i terraform_remote_state
jako łącznika między modułami infrastruktury w kompozycji
W tej książce przykładowe projekty są pogrupowane według złożoności — od małych do bardzo dużych infrastruktur. Ten podział nie jest ścisły, więc sprawdź, jak robią to inni.
Posiadanie małej infrastruktury oznacza, że istnieje niewielka liczba zależności i niewiele zasobów. Wraz z rozwojem projektu pojawia się potrzeba łączenia wykonywania konfiguracji Terraform. Łączenia różnych modułów infrastruktury i przekazywanie wartości w ramach kompozycji staje się oczywistym następstwem.
Istnieje co najmniej 5 odrębnych grup rozwiązań do orkiestracji, z których korzystają programiści_stki:
Czysty Terraform. Bardzo proste rozwiązanie. Programiści_stki muszą znać tylko Terraform, aby wykonać zadanie.
Terragrunt. Narzędzie, którego można użyć do orkiestracji całej infrastruktury, a także obsługi zależności. Terragrunt działa natywnie z modułami infrastruktury i kompozycjami, dzięki czemu ogranicza powielanie kodu.
Skrypty wewnętrzne. Często używane jako punkt startowy do używania orkiestracji oraz przed odkryciem Terragrunt.
Ansible lub inne narzędzie ogólnego przeznaczenia do automatyzacji. Zwykle wybierane rozwiązanie, gdy Terraform jest używany po implementacji Ansible lub gdy aktywnie używany jest interfejs użytkownika Ansible.
Crossplane i inne rozwiązania inspirowane Kubernetes. Czasami sensowne jest wykorzystanie ekosystemu Kubernetes i zastosowanie pętli uzgadniania (reconciliation loop), aby osiągnąć pożądany stan konfiguracji Terraform. Obejrzyj film Crossplane vs Terraform, aby uzyskać więcej informacji.
Mając to wszystko na uwadze — ta książka zawiera przegląd pierwszych dwóch z struktur projektowych — tylko Terraform i Terragrunt.
Zobacz przykłady struktur kodu dla Terraform lub Terragrunt w następnym rozdziale.
Nie ma powodu, aby nie przestrzegać przynajmniej poniższych zasad :)
Pamiętaj, że rzeczywiste zasoby często mają ograniczenia w dopuszczalnym nazewnictwie. Niektóre zasoby, na przykład nie mogą zawierać myślników. Inne zaś muszą być napisane z wykorzystaniem camelCase. Konwencje zawarte w tej książce odnoszą się tylko do samych nazw Terraform.
Wszędzie używaj _
(podkreślenia) zamiast -
(myślnika) (nazwy zasobów, nazwy źródeł danych, nazwy zmiennych, dane wyjściowe itp.).
Staraj się używać małych liter i cyfr (nawet jeśli obsługiwany jest kod UTF-8).
Nie powtarzaj typu zasobu w nazwie zasobu (ani częściowo, ani całkowicie):
resource "aws_route_table" "public" {}
resource "aws_route_table" "public_route_table" {}
resource "aws_route_table" "public_aws_route_table" {}
Nazwa zasobu powinna nazywać się this
, jeśli nie ma bardziej opisowej i ogólnej nazwy, lub jeśli moduł zasobów tworzy pojedynczy zasób tego typu (np. w module AWS VPC jest pojedynczy zasób typu aws_nat_gateway
i wiele zasobów typu aws_route_table
, więc aws_nat_gateway
powinien nazywać się this
, a aws_route_table
powinny być nazwane opisowe - jak private
, public
, database
.
Nazwy zawsze powinny być rzeczownikami w liczbie pojedynczej.
Używaj -
wewnątrz wartości argumentów oraz w miejscach, w których wartość będą odczytywane przez człowiekowa (np. wewnątrz nazwy DNS instancji RDS).
Argumenty count
lub for_each
umieszczaj wewnątrz bloku zasobu lub źródła danych jako pierwszy argument u góry i oddzielaj go znakiem nowej linii.
Argument tags
, jeśli jest obsługiwany przez zasób, umieszczaj jako ostatni , po którym następuje depend_on
i lifecycle
, jeśli to konieczne. Wszystkie te elementy powinny być oddzielone pojedynczym pustym wierszem.
Używając warunków logicznych przy argumencie count
lub for_each
stosuj wartości logiczne zamiast porównywania długości ciągu czy innych wyrażeń.
resource
)count
/ for_each