Najlepsze praktyki podczas korzystania z Terraform [zamknięte]


111

Jestem w trakcie zamiany naszej infrastruktury na terraform. Jaka jest najlepsza praktyka rzeczywistego zarządzania plikami terraform i stanem? Zdaję sobie sprawę, że jest to infrastruktura jako kod i zatwierdzę moje pliki .tf do gita, ale czy zatwierdzę również tfstate? Czy powinno to znajdować się gdzieś jak S3? Chciałbym, żeby ostatecznie CI poradził sobie z tym wszystkim, ale to jest bardzo rozciągnięte i wymaga ode mnie wymyślenia ruchomych elementów dla plików.

Naprawdę chcę tylko zobaczyć, jak ludzie faktycznie wykorzystują tego typu rzeczy w produkcji

Odpowiedzi:


85

Jestem również w stanie migracji istniejącej infrastruktury AWS do Terraform, więc będę starał się aktualizować odpowiedź w miarę rozwoju.

W dużej mierze polegałem na oficjalnych przykładach Terraform i wielu próbach i błędach, aby opracować obszary, w których nie byłem pewien.

.tfstate pliki

Konfiguracja Terraform może służyć do obsługi wielu skrzynek w innej infrastrukturze, z których każda może mieć inny stan. Ponieważ może być również uruchamiany przez wiele osób, stan ten powinien znajdować się w scentralizowanej lokalizacji (takiej jak S3), ale nie w git.

Można to potwierdzić patrząc na Terraform .gitignore.

Kontrola dewelopera

Naszym celem jest zapewnienie deweloperom większej kontroli nad infrastrukturą przy jednoczesnym zachowaniu pełnego audytu (dziennik git) oraz możliwości sprawdzania poprawności zmian (pull requesty). Mając to na uwadze, nowy przepływ pracy dotyczący infrastruktury, do którego dążę, to:

  1. Podstawowy fundament powszechnych AMI, które obejmują moduły wielokrotnego użytku, np. Marionetka.
  2. Infrastruktura podstawowa udostępniana przez DevOps przy użyciu Terraform.
  3. Deweloperzy w razie potrzeby zmieniają konfigurację Terraform w Git (liczba wystąpień, nowy VPC, dodanie regionu / strefy dostępności itp.).
  4. Konfiguracja Git została wypchnięta, a żądanie ściągnięcia zostało przesłane do sprawdzenia przez członka zespołu DevOps.
  5. Po zatwierdzeniu wywołuje element webhook do CI w celu kompilacji i wdrożenia (nie jest w tej chwili pewna, jak podzielić wiele środowisk na partycje)

Edycja 1 - aktualizacja aktualnego stanu

Odkąd zacząłem tę odpowiedź, napisałem dużo kodu TF i czuję się bardziej komfortowo w naszym stanie rzeczy. Po drodze napotkaliśmy błędy i ograniczenia, ale zgadzam się, że jest to cecha charakterystyczna używania nowego, szybko zmieniającego się oprogramowania.

Układ

Mamy skomplikowaną infrastrukturę AWS z wieloma VPC z wieloma podsieciami. Kluczem do łatwego zarządzania tym było zdefiniowanie elastycznej taksonomii obejmującej region, środowisko, usługę i właściciela, której możemy użyć do uporządkowania kodu naszej infrastruktury (zarówno terraform, jak i marionetki).

Moduły

Następnym krokiem było utworzenie jednego repozytorium git do przechowywania naszych modułów terraform. Nasza struktura katalogów najwyższego poziomu dla modułów wygląda następująco:

tree -L 1 .

Wynik:

├── README.md
├── aws-asg
├── aws-ec2
├── aws-elb
├── aws-rds
├── aws-sg
├── aws-vpc
└── templates

Każdy z nich ustawia rozsądne wartości domyślne, ale ujawnia je jako zmienne, które mogą zostać nadpisane przez nasz „klej”.

Klej

Posiadamy drugie repozytorium z naszym, gluektóre korzysta z modułów wymienionych powyżej. Jest ułożony zgodnie z naszym dokumentem taksonomicznym:

.
├── README.md
├── clientA
   ├── eu-west-1
      └── dev
   └── us-east-1
       └── dev
├── clientB
   ├── eu-west-1
      ├── dev
      ├── ec2-keys.tf
      ├── prod
      └── terraform.tfstate
   ├── iam.tf
   ├── terraform.tfstate
   └── terraform.tfstate.backup
└── clientC
    ├── eu-west-1
       ├── aws.tf
       ├── dev
       ├── iam-roles.tf
       ├── ec2-keys.tf
       ├── prod
       ├── stg
       └── terraform.tfstate
    └── iam.tf

Na poziomie klienta mamy .tfpliki specyficzne dla konta AWS , które udostępniają globalne zasoby (takie jak role IAM); następny to poziom regionu z kluczami publicznymi EC2 SSH; W końcu w naszym środowisku ( dev, stg, prodetc) są naszą konfiguracje VPC, tworzenie instancji i zaglądanie połączeń itd są przechowywane.

Uwaga boczna: Jak widać, sprzeciwiam się mojej własnej radzie powyżej, trzymając się terraform.tfstategit. Jest to środek tymczasowy, dopóki nie przejdę na S3, ale mi odpowiada, ponieważ obecnie jestem jedynym programistą.

Następne kroki

Jest to nadal proces ręczny i jeszcze nie w Jenkinsie, ale przenosimy dość dużą, skomplikowaną infrastrukturę i jak dotąd jest to dobre. Jak powiedziałem, kilka błędów, ale wszystko idzie dobrze!

Edycja 2 - zmiany

Minął prawie rok, odkąd napisałem tę wstępną odpowiedź, a stan Terraform i mnie znacznie się zmienił. Jestem teraz na nowej pozycji przy użyciu Terraform do zarządzania klastrem Azure, a Terraform jest teraz v0.10.7.

Stan

Ludzie wielokrotnie powtarzali mi, że stan nie powinien wchodzić w Git - i mają rację. Wykorzystaliśmy to jako środek tymczasowy z dwuosobowym zespołem, który polegał na komunikacji i dyscyplinie programistów. W większym, rozproszonym zespole w pełni wykorzystujemy stan zdalny w S3 z blokadą zapewnianą przez DynamoDB. Najlepiej byłoby, gdyby zostało to przeniesione do Consul, teraz jest to wersja 1.0, aby zmniejszyć liczbę dostawców usług w chmurze.

Moduły

Wcześniej tworzyliśmy i używaliśmy modułów wewnętrznych. Nadal tak jest, ale wraz z pojawieniem się i rozwojem rejestru Terraform staramy się wykorzystać je przynajmniej jako podstawę.

Struktura plików

Nowa pozycja ma znacznie prostszą taksonomię z tylko dwoma środowiskami infx - devi prod. Każdy ma własne zmienne i dane wyjściowe, wykorzystując ponownie nasze moduły utworzone powyżej. remote_stateDostawca pomaga w dzieleniu się wyjść tworzonych zasobów pomiędzy środowiskami. Nasz scenariusz obejmuje subdomeny w różnych grupach zasobów platformy Azure do globalnie zarządzanej domeny TLD.

├── main.tf
├── dev
   ├── main.tf
   ├── output.tf
   └── variables.tf
└── prod
    ├── main.tf
    ├── output.tf
    └── variables.tf

Planowanie

Ponownie z dodatkowymi wyzwaniami rozproszonego zespołu, teraz zawsze zapisujemy nasze wyniki terraform planpolecenia. Możemy sprawdzić i wiedzieć, co zostanie uruchomione bez ryzyka pewnych zmian między sceną plana apply(chociaż pomaga w tym blokowanie). Pamiętaj, aby usunąć ten plik planu, ponieważ może on potencjalnie zawierać „tajne” zmienne tekstowe.

Ogólnie jesteśmy bardzo zadowoleni z Terraform i nadal się uczymy i ulepszamy dzięki dodanym nowym funkcjom.


Czy masz szczęście / problemy od czasu tej odpowiedzi? Twoje wydaje się bardzo podobne do tego, do czego zmierzam, ale możesz być dalej ode mnie.
Marc Young

3
Jestem ciekaw, dlaczego uważasz, że pliki tfstate nie powinny być przechowywane w git? Czy to po prostu dlatego, że starego państwa nie warto ratować, czy też są inne problemy?
agbodike

3
@agbodike - Podczas pracy jako pojedynczy programista lub część bardzo małego zespołu, tfstate może pozostać w git, o ile jest regularnie zaangażowany i popychany w celu uniknięcia konfliktów. Moim następnym krokiem jest skonfigurowanie tego zgodnie z dokumentacją stanu zdalnego w S3 (która również mówi: „To sprawia, że ​​praca z Terraform w zespole jest skomplikowana, ponieważ jest to częste źródło konfliktów scalania. Stan zdalny pomaga złagodzić te problemy”). . Jak w większości rzeczy, chociaż dobra komunikacja w zespole może pomóc złagodzić większość / wszystkie problemy, niezależnie od taktyki utrzymania stanu :-)
Ewan

1
@ the0ther - Obawiam się, że moje główne repozytorium jest zastrzeżone, jednak obecnie pracuję nad prywatnym, które udostępnię publicznie w najbliższej przyszłości.
Ewan

2
Jakieś szczęście w repozytorium Git @Ewan? Chciałbym zobaczyć, co robisz.
David

85

Intensywnie używamy Terraform, a nasza zalecana konfiguracja jest następująca:

Układ plików

Zdecydowanie zalecamy przechowywanie kodu Terraform dla każdego środowiska (np. Stage, prod, qa) w osobnych zestawach szablonów (a zatem w osobnych .tfstateplikach). Jest to ważne, aby Twoje oddzielne środowiska były faktycznie odizolowane od siebie podczas wprowadzania zmian. W przeciwnym razie, podczas majstrowania przy jakimś kodzie podczas inscenizacji, zbyt łatwo jest wysadzić coś w prod. Zobacz Terraform, VPC i dlaczego potrzebujesz pliku tfstate na env, aby zapoznać się z kolorową dyskusją o tym, dlaczego.

Dlatego nasz typowy układ plików wygląda następująco:

stage
   main.tf
   vars.tf
   outputs.tf
prod
   main.tf
   vars.tf
   outputs.tf
global
   main.tf
   vars.tf
   outputs.tf

Cały kod Terraform dla etapu VPC trafia do stagefolderu, cały kod dla produktu VPC trafia do prodfolderu, a cały kod, który znajduje się poza VPC (np. Użytkownicy IAM, tematy SNS, zasobniki S3) trafia do globalfolderu .

Zwróć uwagę, że zgodnie z konwencją zazwyczaj dzielimy nasz kod Terraform na 3 pliki:

  • vars.tf: Zmienne wejściowe.
  • outputs.tf: Zmienne wyjściowe.
  • main.tf: Rzeczywiste zasoby.

Moduły

Zazwyczaj naszą infrastrukturę definiujemy w dwóch folderach:

  1. infrastructure-modules: Ten folder zawiera małe, wielokrotnego użytku, wersjonowane moduły. Potraktuj każdy moduł jako plan tworzenia pojedynczego elementu infrastruktury, takiego jak VPC lub baza danych.
  2. infrastructure-live: Ten folder zawiera rzeczywistą działającą infrastrukturę, którą tworzy poprzez połączenie modułów w infrastructure-modules. Pomyśl o kodzie w tym folderze jak o rzeczywistych domach, które zbudowałeś ze swoich planów.

Moduł Terraform jest byle zestaw szablonów Terraform w folderze. Na przykład możemy mieć folder o nazwie vpcin, infrastructure-modulesktóry definiuje wszystkie tabele tras, podsieci, bramy, listy ACL itp. Dla jednej sieci VPC:

infrastructure-modules
   vpc
     main.tf
     vars.tf
     outputs.tf

Możemy wtedy użyć tego modułu w infrastructure-live/stagei infrastructure-live/proddo tworzenia VPCs scenie i prod. Na przykład tak infrastructure-live/stage/main.tfmoże wyglądać:

module "stage_vpc" {
  source = "git::git@github.com:gruntwork-io/module-vpc.git//modules/vpc-app?ref=v0.0.4"

  vpc_name         = "stage"
  aws_region       = "us-east-1"
  num_nat_gateways = 3
  cidr_block       = "10.2.0.0/18"
}

Aby użyć modułu, użyj rozszerzenia module zasobu i wskazać jego sourcepole na ścieżkę lokalną na dysku twardym (np. source = "../infrastructure-modules/vpc") Lub, jak w powyższym przykładzie, adres URL Git (patrz źródła modułów ). Zaletą adresu URL Git jest to, że możemy określić konkretny git sha1 lub tag ( ref=v0.0.4). Teraz nie tylko definiujemy naszą infrastrukturę jako zbiór małych modułów, ale możemy wersjonować te moduły i starannie aktualizować lub wycofywać w razie potrzeby.

Stworzyliśmy wiele wielokrotnego użytku, przetestowanych i udokumentowanych pakietów infrastruktury do tworzenia VPC, klastrów Docker, baz danych i tak dalej, a większość z nich to po prostu wersjonowane moduły Terraform.

Stan

Gdy używasz Terraform do tworzenia zasobów (np. Instancji EC2, baz danych, VPC), zapisuje on informacje o tym, co utworzył w .tfstatepliku. Aby wprowadzić zmiany w tych zasobach, wszyscy w Twoim zespole muszą mieć do nich dostęp.tfstate pliku, ale NIE powinieneś sprawdzać go w Git (zobacz tutaj, aby uzyskać wyjaśnienie, dlaczego ).

Zamiast tego zalecamy przechowywanie .tfstateplików w S3, włączając Terraform Remote State , który automatycznie wypycha / pobiera najnowsze pliki przy każdym uruchomieniu Terraform. Upewnij się, że włączyłeś.tfstate przechowywanie wersji w swoim zasobniku S3, aby móc przywrócić starsze pliki, jeśli w jakiś sposób uszkodzisz najnowszą wersję. Jednak ważna uwaga: Terraform nie zapewnia blokowania . Więc jeśli dwóch członków zespołu pracuje terraform applyw tym samym czasie na tym samym .tfstatepliku, mogą skończyć się wzajemnym nadpisywaniem zmian.

Aby rozwiązać ten problem, stworzyliśmy narzędzie open source o nazwie Terragrunt , które jest cienkim opakowaniem dla Terraform, które wykorzystuje Amazon DynamoDB do zapewniania blokowania (które powinno być całkowicie bezpłatne dla większości zespołów). Aby uzyskać więcej informacji, zobacz Dodawanie automatycznego blokowania i konfiguracji stanu zdalnego do Terraform z Terragrunt .

Dalsza lektura

Właśnie rozpoczęliśmy serię postów na blogu zatytułowanej Kompleksowy przewodnik po Terraform , w którym szczegółowo opisano wszystkie najlepsze praktyki, jakich nauczyliśmy się przy używaniu Terraform w prawdziwym świecie.

Aktualizacja: seria wpisów na blogu Wszechstronny przewodnik po Terraform stała się tak popularna, że ​​rozszerzyliśmy ją do książki pod tytułem Terraform: Up & Running !


Myślę, że to jest poprawna odpowiedź. Używaj modułów, edytuj je i oddzielaj środowiska.
wrangler

Czy krok zdalnej konfiguracji musi być uruchamiany ponownie za każdym razem, gdy chcesz pracować na innym komponencie terraform / środowisku / module / czymkolwiek, jeśli nie używasz terragrunt lub innego opakowania?
jmreicha

@jmreicha: Musisz uruchomić, remote configjeśli właśnie sprawdziłeś konfiguracje Terraform lub jeśli chcesz zmienić poprzednią konfigurację zdalną. Terraform 0.9 wprowadzi koncepcję backends, która bardzo to uprości. Zobacz ten PR, aby uzyskać więcej informacji.
Yevgeniy Brikman

Żeby zrozumieć - pracuję na „scenie” środowiska, ale potem zaczynam pracę nad „produkcją”. Będę musiał ponownie uruchomić remote configpolecenie, aby wskazać stan produktu. Zakładając inny stan na środowisko. Czy to prawda? Nie mogę się doczekać wersji 0.9.
jmreicha

Jeśli zamierzasz wdrożyć dokładnie ten sam zestaw .tfplików w dwóch różnych środowiskach, tak, musisz uruchamiać za remote configkażdym razem, gdy się przełączasz. Jest to oczywiście bardzo podatne na błędy, więc nie polecam korzystania z tej techniki. Zamiast tego zapoznaj się z zalecanym układem pliku Terraform w tym poście na blogu oraz sposobem korzystania z modułów Terraform w tym poście .
Yevgeniy Brikman

9

Wcześniej remote configpozwalano na to, ale teraz zostało zastąpione przez „ backendy ”, więc zdalne sterowanie terraform nie jest już dostępne.

terraform remote config -backend-config="bucket=<s3_bucket_to_store_tfstate>" -backend-config="key=terraform.tfstate" -backend=s3
terraform remote pull
terraform apply
terraform remote push

Szczegółowe informacje można znaleźć w dokumentacji .


Czy zdalne źródło wymaga rekonfiguracji za każdym razem, gdy chcesz pracować na innym komponencie terraform / środowisku / module / czymkolwiek?
jmreicha

6

Bardziej szczegółowo omówione przez @Yevgeny Brikman, ale w szczególności odpowiadając na pytania OP:

Jaka jest najlepsza praktyka rzeczywistego zarządzania plikami terraform i stanem?

Użyj git dla plików TF. Ale nie sprawdzaj plików stanu w (np. Tfstate). Zamiast tego użyj Terragruntdo synchronizacji / blokowania plików stanu do S3.

ale czy ja również zatwierdzam tfstate?

Nie.

Czy powinno to znajdować się gdzieś jak S3?

tak


2

Wiem, że jest tu wiele odpowiedzi, ale moje podejście jest zupełnie inne.

   Modules
   Environment management 
   Separation of duties

Moduły

  1. Twórz moduły dla logicznych kolekcji zasobów. Przykład: jeśli Twoim celem jest wdrożenie interfejsu API, który wymaga bazy danych, maszyn wirtualnych wysokiej dostępności, autoskalowania, DNS, PubSub i magazynu obiektów, wówczas wszystkie te zasoby powinny być oparte na szablonie w jednym module.
  2. Unikaj tworzenia modułów wykorzystujących jeden zasób. Można to zrobić i zostało zrobione, a wiele modułów w rejestrze to robi, ale jest to praktyka, która pomaga w dostępie do zasobów, a nie w orkiestracji infrastruktury. Przykład: Moduł dla AWS EC2 pomaga użytkownikowi uzyskać dostęp do EC2, czyniąc złożone konfiguracje łatwiejszymi do wywołania, ale moduł taki jak w przykładzie w 1. pomaga użytkownikowi podczas aranżacji aplikacji, komponentów lub infrastruktury opartej na usługach.
    1. Unikaj deklaracji zasobów w obszarze roboczym. Chodzi bardziej o utrzymanie porządku i organizacji kodu. Ponieważ moduły są łatwo wersjonowane, masz większą kontrolę nad swoimi wydaniami.

Zarządzanie środowiskiem

IaC sprawiło, że proces SDLC jest istotny dla zarządzania infrastrukturą i nie jest normalne oczekiwanie posiadania infrastruktury programistycznej, jak również środowisk programistycznych.

  1. Nie używaj folderów do zarządzania środowiskami IaC. Prowadzi to do dryfu, ponieważ nie ma wspólnego szablonu dla Twojej infrastruktury.
  2. Używaj jednego obszaru roboczego i zmiennych do kontrolowania specyfikacji środowiska. Przykład: Napisz swoje moduły tak, aby po zmianie zmiennej środowiskowej (popularna jest var.stage) plan dostosowuje się do twoich wymagań. Zazwyczaj środowiska powinny różnić się tak mało, jak to możliwe, przy czym ilość, ekspozycja i pojemność są zwykle zmiennymi konfiguracjami. Deweloper może wdrożyć 1 maszynę wirtualną z 1 rdzeniem i 1 GB pamięci RAM w topologii prywatnej, ale produkcja może obejmować 3 maszyny wirtualne z 2 rdzeniami i 4 GB pamięci RAM z dodatkową topologią publiczną. Możesz oczywiście mieć więcej wariantów: programista może uruchamiać proces bazy danych na tym samym serwerze co aplikacja, aby obniżyć koszty, ale produkcja może mieć dedykowaną instancję bazy danych. Wszystkim tym można zarządzać, zmieniając pojedynczą zmienną, potrójne instrukcje i interpolację.

Rozdzielenie obowiązków

Jeśli jesteś w małej organizacji lub posiadasz infrastrukturę osobistą, to tak naprawdę nie ma zastosowania, ale pomoże ci zarządzać twoimi operacjami.

  1. Podziel swoją infrastrukturę według obowiązków, odpowiedzialności lub zespołów. Przykład: centralna kontrola IT leżąca u podstaw usług współdzielonych (sieci wirtualne, podsieci, publiczne adresy IP, grupy dzienników, zasoby ładu, bazy danych z wieloma dzierżawcami, klucze współdzielone itp.), Podczas gdy zespół API kontroluje tylko zasoby potrzebne do ich usługi (maszyny wirtualne, LB , PubSub itp.) I korzystaj z usług centralnego IT za pośrednictwem źródeł danych i zdalnego wyszukiwania stanu.
    1. Zarządzaj dostępem do zespołu. Przykład: Centralny dział IT może mieć uprawnienia administratora, ale zespół API ma dostęp tylko do ograniczonego zestawu API chmury publicznej.

Pomaga to również w przypadku problemów z wydaniem, ponieważ niektóre zasoby rzadko się zmieniają, podczas gdy inne zmieniają się cały czas. Separacja eliminuje ryzyko i złożoność.

Ta strategia przypomina strategię wielu kont AWS. Przeczytaj, aby uzyskać więcej informacji.

CI / CD

To temat sam w sobie, ale Terraform działa bardzo dobrze w ramach dobrego potoku. Najczęstszym błędem jest tutaj traktowanie CI jako srebrnej kuli. Z technicznego punktu widzenia Terraform powinien dostarczać infrastrukturę tylko na etapach rurociągu montażowego. Byłoby to niezależne od tego, co dzieje się na etapach CI, gdzie zazwyczaj sprawdza się i testuje szablony.

Uwaga: Napisane na telefon komórkowy, więc przepraszamy za wszelkie błędy.


0

Zanim odpowiedzi będą bardzo solidne i pouczające, spróbuję dodać tutaj moje 2 centy

Typowe zalecenia dotyczące strukturyzacji kodu

  1. Praca z mniejszą liczbą zasobów jest łatwiejsza i szybsza:

    • Cmds terraform plani terraformzastosuj oba wywołania interfejsu API chmury w celu zweryfikowania stanu zasobów.
    • Jeśli masz całą infrastrukturę w jednej kompozycji, może to zająć wiele minut (nawet jeśli masz kilka plików w tym samym folderze).
  2. Promień rażenia jest mniejszy i mniej zasobów:

    • Izolowanie niepowiązanych zasobów od siebie poprzez umieszczenie ich w oddzielnych kompozycjach (folderach) zmniejsza ryzyko, jeśli coś pójdzie nie tak.
  3. Rozpocznij projekt przy użyciu stanu zdalnego:

  4. Spróbuj przećwiczyć spójną strukturę i konwencję nazewnictwa:

    • Podobnie jak kod proceduralny, kod Terraform powinien być napisany tak, aby ludzie mogli go najpierw przeczytać, a spójność pomoże, gdy zmiany nastąpią za sześć miesięcy.
    • Możliwe jest przenoszenie zasobów w pliku stanu Terraform, ale może to być trudniejsze, jeśli masz niespójną strukturę i nazewnictwo.
  5. Utrzymuj moduły zasobów w jak najbardziej przejrzystej formie.

  6. Nie twórz na stałe wartości, które można przekazać jako zmienne lub wykryć za pomocą źródeł danych.

  7. Używaj dataźródeł, a terraform_remote_statezwłaszcza jako kleju między modułami infrastruktury w kompozycji.

( patrz artykuł: https://www.terraform-best-practices.com/code-structure )


Przykład:

Praca z mniejszą liczbą zasobów jest łatwiejsza i szybsza, dlatego poniżej przedstawiamy zalecany układ kodu.

UWAGA: jako odniesienie, którego nie należy ściśle przestrzegać, ponieważ każdy projekt ma swoje specyficzne cechy

.
├── 1_tf-backend #remote AWS S3 + Dynamo Lock tfstate 
   ├── main.tf
   ├── ...
├── 2_secrets
   ├── main.tf
   ├── ...
├── 3_identities
   ├── account.tf
   ├── roles.tf
   ├── group.tf
   ├── users.tf
   ├── ...
├── 4_security
   ├── awscloudtrail.tf
   ├── awsconfig.tf
   ├── awsinspector.tf
   ├── awsguarduty.tf
   ├── awswaf.tf
   └── ...
├── 5_network
   ├── account.tf
   ├── dns_remote_zone_auth.tf
   ├── dns.tf
   ├── network.tf
   ├── network_vpc_peering_dev.tf
   ├── ...
├── 6_notifications
   ├── ...
├── 7_containers
   ├── account.tf
   ├── container_registry.tf
   ├── ...
├── config
   ├── backend.config
   └── main.config
└── readme.md

0

Uważam, że podczas korzystania z narzędzia Terraform do orkiestracji infrastruktury należy przestrzegać kilku najlepszych praktyk

  1. Nie pisz ponownie tego samego kodu (możliwość ponownego wykorzystania)
  2. Zachowaj oddzielną konfigurację środowiska, aby łatwo ją utrzymać.
  3. Użyj zdalnego zaplecza s3 (zaszyfrowanego) i dynamo DB do obsługi blokowania współbieżności
  4. Utwórz moduł i używaj go wielokrotnie w głównej infrastrukturze, podobnie jak funkcja wielokrotnego użytku, którą można wywołać wielokrotnie, przekazując inny parametr.

Obsługuj wiele środowisk

Najczęściej zalecanym sposobem jest użycie terraform „przestrzeni roboczej” do obsługi wielu środowisk, ale uważam, że wykorzystanie przestrzeni roboczej może się różnić w zależności od sposobu pracy w organizacji. Innym jest przechowywanie kodu Terraform dla każdego środowiska (np. Stage, prod, QA) w celu oddzielenia stanów środowiska. Jednak w tym przypadku po prostu kopiujemy ten sam kod w wielu miejscach.

├── main.tf
├── dev
   ├── main.tf
   ├── output.tf
   └── variables.tf
└── prod
├── main.tf
├── output.tf
└── variables.tf

Zastosowałem inne podejście do obsługi i unikania powielania tego samego kodu terraform, przechowując w każdym folderze środowiska, ponieważ uważam, że przez większość czasu całe środowisko będzie w 90% takie samo.

├── deployment
 ├── 01-network.tf
 ├── 02-ecs_cluster.tf
 ├── 03-ecs_service.tf
 ├── 04-eks_infra.tf
 ├── 05-db_infra.tf
 ├── 06-codebuild-k8s.tf
 ├── 07-aws-secret.tf
 ├── backend.tf
 ├── provider.tf
 └── variables.tf
├── env
 ├── dev
  ├── dev.backend.tfvar
  └── dev.variables.tfvar
 └── prod
 ├── prod.backend.tfvar
 └── prod.variables.tfvar
├── modules
 └── aws
 ├── compute
  ├── alb_loadbalancer
  ├── alb_target_grp
  ├── ecs_cluster
  ├── ecs_service
  └── launch_configuration
 ├── database
  ├── db_main
  ├── db_option_group
  ├── db_parameter_group
  └── db_subnet_group
 ├── developertools
 ├── network
  ├── internet_gateway
  ├── nat_gateway
  ├── route_table
  ├── security_group
  ├── subnet
  ├── vpc
 └── security
 ├── iam_role
 └── secret-manager
└── templates

Konfiguracja związana ze środowiskami

Zachowaj konfigurację i parametry związane ze środowiskiem oddzielnie w pliku zmiennych i przekaż tę wartość, aby skonfigurować infrastrukturę. np. jak poniżej

  • dev.backend.tfvar

      region = "ap-southeast-2"
      bucket = "dev-samplebackendterraform"
      key = "dev/state.tfstate"
      dynamo_db_lock = "dev-terraform-state-lock"
  • dev.variable.tfvar

    environment                     =   "dev"
    vpc_name                        =   "demo"
    vpc_cidr_block                  =   "10.20.0.0/19"
    private_subnet_1a_cidr_block    =   "10.20.0.0/21"
    private_subnet_1b_cidr_block    =   "10.20.8.0/21"
    public_subnet_1a_cidr_block     =   "10.20.16.0/21"
    public_subnet_1b_cidr_block     =   "10.20.24.0/21"

Warunkowe pomijanie części infrastruktury

Utwórz konfigurację w pliku zmiennej specyficznej dla środowiska env i na podstawie tej zmiennej zdecyduj o utworzeniu lub pominięciu tej części. W ten sposób w zależności od potrzeb można pominąć określoną część infrastruktury.

variable vpc_create {
   default = "true"
}

module "vpc" {
  source = "../modules/aws/network/vpc"
  enable = "${var.vpc_create}"
  vpc_cidr_block = "${var.vpc_cidr_block}"
  name = "${var.vpc_name}"
 }

 resource "aws_vpc" "vpc" {
    count                = "${var.enable == "true" ? 1 : 0}"
    cidr_block           = "${var.vpc_cidr_block}"
    enable_dns_support   = "true"
   enable_dns_hostnames = "true"
}

poniższe polecenie jest wymagane do zainicjowania i wykonania zmian infra dla każdego środowiska, cd do wymaganego folderu środowiska.

  terraform init -var-file=dev.variables.tfvar -backend-config=dev.backend.tfvar ../../deployment/

  terraform apply -var-file=dev.variables.tfvar ../../deployment

Dla odniesienia: https://github.com/mattyait/devops_terraform


0

Nie podoba mi się pomysł z podfolderami, ponieważ spowoduje to różne źródła dla każdego środowiska i ma tendencję do dryfowania.

Lepszym podejściem jest posiadanie jednego stosu dla wszystkich środowisk (powiedzmy dla programistów, preprod i prod). Aby pracować w jednym środowisku, użyj terraform workspace.

terraform workspace new dev

Tworzy to nowy obszar roboczy. Obejmuje to dedykowany plik stanu i zmienną, terraform.workspacektórej możesz użyć w swoim kodzie.

resource "aws_s3_bucket" "bucket" {
  bucket = "my-tf-test-bucket-${terraform.workspace}"
}

W ten sposób otrzymasz tzw. Wiadra

  • my-tf-test-bucket-dev
  • my-tf-test-bucket-preprod
  • my-tf-test-bucket-prod

po zastosowaniu do powyższych obszarów roboczych (użyj terraform workspace select <WORKSPACE>do zmiany środowisk). Aby kod był odporny na wiele regionów, zrób to w następujący sposób:

data "aws_region" "current" {}

resource "aws_s3_bucket" "bucket" {
  bucket = "my-tf-test-bucket-${data.aws_region.current.name}-${terraform.workspace}"
}

dostać (dla regionu us-east-1)

  • my-tf-test-bucket-us-east-1-dev
  • my-tf-test-bucket-us-east-1-preprod
  • my-tf-test-bucket-us-east-1-prod

0

Niektóre sprawdzone metody Terraform do przestrzegania:

  1. Unikaj twardego kodowania: czasami programiści ręcznie tworzyli zasoby bezpośrednio. Musisz oznaczyć te zasoby i użyć importu terraform, aby uwzględnić je w kodach. Próbka:

    account_number = „123456789012” account_alias = „mojafirma”

  2. Uruchom Terraform z kontenera Dockera: Terraform udostępnia oficjalny kontener Docker, który umożliwia łatwe kontrolowanie, którą wersję można uruchomić.

Zaleca się uruchomienie kontenera Terraform Docker podczas ustawiania zadania kompilacji w potoku ciągłej integracji / ciągłej integracji.

TERRAFORM_IMAGE=hashicorp/terraform:0.11.7
TERRAFORM_CMD="docker run -ti --rm -w /app -v ${HOME}/.aws:/root/.aws -v ${HOME}/.ssh:/root/.ssh -v `pwd`:/app $TERRAFORM_IMAGE"

Więcej informacji można znaleźć na moim blogu: https://medium.com/tech-darwinbox/how-darwinbox-manages-infrastructure-at-scale-with-terraform-371e2c5f04d3


0

Chciałbym wnieść swój wkład w ten wątek.

  • Najprawdopodobniej będzie to AWS S3 + DynamoDB, chyba że używasz Terraform Cloud.
  • Oddzielna infrastruktura (sieć + RBAC) backendów produkcyjnych i nieprodowych.
  • Zaplanuj wyłączenie dostępu do plików stanu (dostęp do sieci i RBAC) spoza wyznaczonej sieci (np. Puli agentów wdrożeniowych).
  • Nie przechowuj infrastruktury zaplecza Terraform w środowisku wykonawczym. Użyj osobnego konta.
  • Włącz przechowywanie wersji obiektów w zapleczu Terraform, aby uniknąć utraty zmian i plików stanu oraz w celu zachowania historii stanu Terraform.

W niektórych szczególnych przypadkach wymagany będzie ręczny dostęp do plików stanu Terraform. Rzeczy takie jak refaktoryzacja, wprowadzanie zmian lub naprawianie defektów będą wymagały uruchomienia operacji Terraform stanu przez personel operacyjny. W takich przypadkach zaplanuj wyjątkowo kontrolowany dostęp do stanu Terraform za pomocą hosta bastionu, VPN itp.

Zapoznaj się z dłuższym blogiem z najlepszymi praktykami, który szczegółowo omawia tę kwestię, w tym wskazówki dotyczące potoków ciągłej integracji / ciągłej integracji.


-1

Jeśli nadal szukasz lepszego rozwiązania, spójrz na obszary robocze, które mogą zastąpić utrzymywanie innej struktury folderów środowiska, które mogą mieć zmienne specyficzne dla obszaru roboczego.

Jak wspomniał Yevgeniy Brikman , lepiej mieć strukturę modułową .


-1

Użyj chmury terraform do zarządzania stanami i zapisywania ich wraz z powyższymi wskazówkami.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.