Best Practices bei der Verwendung von Terraform [geschlossen]

111

Ich bin dabei, unsere Infrastruktur in Terraform umzuwandeln. Was ist die beste Vorgehensweise zum tatsächlichen Verwalten der Terraform-Dateien und des Status? Mir ist klar, dass es sich um eine Infrastruktur als Code handelt, und ich werde meine .tf-Dateien in git festschreiben, aber lege ich auch tfstate fest? Sollte das irgendwo wie S3 liegen? Ich möchte, dass CI all dies irgendwann verwaltet, aber das ist weitreichend und erfordert, dass ich die beweglichen Teile für die Dateien herausfinde.

Ich möchte wirklich nur sehen, wie die Leute da draußen diese Art von Sachen tatsächlich in der Produktion verwenden

Marc Young
quelle

Antworten:

85

Ich bin auch in der Lage, die vorhandene AWS-Infrastruktur auf Terraform zu migrieren. Daher werde ich versuchen, die Antwort während meiner Entwicklung zu aktualisieren.

Ich habe mich stark auf die offiziellen Terraform- Beispiele und das mehrfache Ausprobieren verlassen, um Bereiche zu konkretisieren, in denen ich unsicher war.

.tfstate Dateien

Die Terraform-Konfiguration kann verwendet werden, um viele Boxen in unterschiedlichen Infrastrukturen bereitzustellen, von denen jede einen anderen Status haben kann. Da dieser Status auch von mehreren Personen ausgeführt werden kann, sollte er sich an einem zentralen Ort (wie S3) befinden, jedoch nicht an Git.

Dies kann anhand der Terraform bestätigt werden .gitignore.

Entwicklersteuerung

Unser Ziel ist es, Entwicklern eine bessere Kontrolle über die Infrastruktur zu bieten und gleichzeitig ein vollständiges Audit (Git-Protokoll) und die Möglichkeit zur Überprüfung von Änderungen (Pull-Anforderungen) aufrechtzuerhalten. Vor diesem Hintergrund strebe ich einen neuen Infrastruktur-Workflow an:

  1. Basisgrundlage für gängige AMIs, die wiederverwendbare Module enthalten, z. B. Marionetten.
  2. Von DevOps mithilfe von Terraform bereitgestellte Kerninfrastruktur.
  3. Entwickler ändern die Terraform-Konfiguration in Git nach Bedarf (Anzahl der Instanzen; neue VPC; Hinzufügen einer Region / Verfügbarkeitszone usw.).
  4. Die Git-Konfiguration wurde gepusht und eine Pull-Anfrage wurde von einem Mitglied des DevOps-Teams auf ihre Richtigkeit überprüft.
  5. Wenn dies genehmigt wird, ruft Webhook zum Erstellen und Bereitstellen von CI auf (unsicher, wie mehrere Umgebungen zu diesem Zeitpunkt partitioniert werden sollen).

Bearbeiten 1 - Aktueller Status aktualisieren

Seit ich mit dieser Antwort angefangen habe, habe ich viel TF-Code geschrieben und fühle mich in unserem Zustand wohler. Wir haben auf dem Weg Fehler und Einschränkungen festgestellt, aber ich akzeptiere, dass dies ein Merkmal der Verwendung neuer, sich schnell ändernder Software ist.

Layout

Wir haben eine komplizierte AWS-Infrastruktur mit mehreren VPCs mit jeweils mehreren Subnetzen. Der Schlüssel zur einfachen Verwaltung bestand darin, eine flexible Taxonomie zu definieren, die Region, Umgebung, Service und Eigentümer umfasst und mit der wir unseren Infrastrukturcode (sowohl Terraform als auch Marionette) organisieren können.

Module

Der nächste Schritt bestand darin, ein einzelnes Git-Repository zum Speichern unserer Terraform-Module zu erstellen. Unsere oberste Verzeichnisstruktur für die Module sieht folgendermaßen aus:

tree -L 1 .

Ergebnis:

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

Jeder legt einige vernünftige Standardeinstellungen fest, macht sie jedoch als Variablen verfügbar, die von unserem "Kleber" überschrieben werden können.

Kleben

Wir haben ein zweites Repository mit unserem glue, das die oben genannten Module verwendet. Es ist in Übereinstimmung mit unserem Taxonomiedokument angelegt:

.
├── 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

Innerhalb der Client-Ebene verfügen wir über AWS-kontospezifische .tfDateien, die globale Ressourcen bereitstellen (z. B. IAM-Rollen). Als nächstes folgt die Regionsebene mit öffentlichen EC2-SSH-Schlüsseln. Schließlich in unserer Umgebung ( dev, stg, produsw.) sind unsere VPC - Setups, zB Erstellung und Peering - Verbindungen usw. gespeichert sind.

Randnotiz: Wie Sie sehen können, widerspreche ich meinem eigenen Rat, wenn ich mich terraform.tfstatean Git halte. Dies ist eine vorübergehende Maßnahme, bis ich zu S3 wechsle, passt aber zu mir, da ich derzeit der einzige Entwickler bin.

Nächste Schritte

Dies ist immer noch ein manueller Prozess und noch nicht in Jenkins, aber wir portieren eine ziemlich große, komplizierte Infrastruktur und bisher so gut. Wie gesagt, ein paar Bugs, aber es läuft gut!

Bearbeiten 2 - Änderungen

Es ist fast ein Jahr her, seit ich diese erste Antwort geschrieben habe, und der Zustand von Terraform und mir hat sich erheblich verändert. Ich bin jetzt an einer neuen Position und verwende Terraform zum Verwalten eines Azure-Clusters. Terraform ist jetzt v0.10.7.

Zustand

Die Leute haben mir wiederholt gesagt, dass der Staat nicht in Git gehen soll - und sie sind korrekt. Wir haben dies als Zwischenmaßnahme für ein Zwei-Personen-Team verwendet, das sich auf die Kommunikation und Disziplin der Entwickler stützte. Mit einem größeren, verteilten Team nutzen wir jetzt den Remote-Status in S3 vollständig mit Sperren, die von DynamoDB bereitgestellt werden. Im Idealfall wird dies auf Consul migriert, jetzt ist es Version 1.0, um Cloud-übergreifende Anbieter zu kürzen.

Module

Zuvor haben wir interne Module erstellt und verwendet. Dies ist immer noch der Fall, aber mit dem Aufkommen und Wachstum der Terraform-Registrierung versuchen wir, diese zumindest als Basis zu verwenden.

Dateistruktur

Die neue Position hat eine viel einfachere Taxonomie mit nur zwei Infx-Umgebungen - devund prod. Jedes hat seine eigenen Variablen und Ausgänge, wobei unsere oben erstellten Module wiederverwendet werden. Der remote_stateAnbieter hilft auch beim Teilen von Ausgaben erstellter Ressourcen zwischen Umgebungen. In unserem Szenario handelt es sich um Subdomänen in verschiedenen Azure-Ressourcengruppen zu einer global verwalteten TLD.

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

Planung

Mit den zusätzlichen Herausforderungen eines verteilten Teams speichern wir jetzt immer unsere Ausgabe des terraform planBefehls. Wir können überprüfen und wissen, was ausgeführt wird, ohne dass das Risiko von Änderungen zwischen der planund der applyBühne besteht (obwohl das Sperren dabei hilft). Denken Sie daran, diese Plandatei zu löschen, da sie möglicherweise "geheime" Variablen im Klartext enthalten kann.

Insgesamt sind wir sehr zufrieden mit Terraform und lernen und verbessern uns weiter mit den neuen Funktionen.

Ewan
quelle
Haben Sie seit dieser Antwort Glück / Probleme gehabt? Ihre scheint sehr ähnlich zu sein, was ich vorhabe, aber Sie könnten weiter als ich sein.
Marc Young
3
Ich bin gespannt, warum tfstate-Dateien Ihrer Meinung nach nicht in git gespeichert werden sollten. Liegt es einfach daran, dass der alte Staat es nicht wert ist, gerettet zu werden, oder gibt es andere Probleme?
Agbodike
3
@agbodike - Wenn Sie als einzelner Entwickler oder Teil eines sehr kleinen Teams arbeiten, kann tfstate in git gehalten werden, solange es regelmäßig verpflichtet und gepusht wird, um Konflikte zu vermeiden. Mein nächster Schritt besteht darin, dies gemäß den Remote- Statusdokumenten in S3 einzurichten (die auch besagen: "Die Arbeit mit Terraform in einem Team wird dadurch kompliziert, da es häufig zu Zusammenführungskonflikten kommt. Der Remote-Status hilft, diese Probleme zu beheben.") . Wie bei den meisten Dingen kann eine gute Teamkommunikation helfen, die meisten Probleme zu lindern, unabhängig von der Taktik, den Status zu halten :-)
Ewan
1
@ the0ther - Ich fürchte, mein Haupt-Repository ist proprietär, aber ich arbeite derzeit an einem persönlichen Repository, das ich in naher Zukunft öffentlich zugänglich machen werde.
Ewan
2
Hast du Glück bei einem Git Repo @Ewan? Ich würde gerne sehen, was du tust.
David
85

Wir verwenden Terraform häufig und empfehlen folgende Einstellungen:

Dateilayout

Wir empfehlen dringend, den Terraform-Code für jede Ihrer Umgebungen (z. B. Stage, Prod, QA) in separaten Vorlagensätzen (und daher in separaten .tfstateDateien) zu speichern. Dies ist wichtig, damit Ihre separaten Umgebungen beim Vornehmen von Änderungen tatsächlich voneinander isoliert sind. Andernfalls ist es zu einfach, etwas in Prod in die Luft zu jagen, während Sie beim Staging mit Code herumspielen. Unter Terraform, VPC und warum Sie eine tfstate-Datei pro env benötigen, finden Sie eine farbenfrohe Diskussion darüber, warum.

Daher sieht unser typisches Dateilayout folgendermaßen aus:

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

Der gesamte Terraform-Code für die Stage-VPC wird in den stageOrdner verschoben , der gesamte Code für die Produkt-VPC wird in den prodOrdner verschoben , und der gesamte Code, der außerhalb einer VPC gespeichert ist (z. B. IAM-Benutzer, SNS-Themen, S3-Buckets), wird in den globalOrdner verschoben .

Beachten Sie, dass wir unseren Terraform-Code normalerweise in drei Dateien aufteilen:

  • vars.tf: Eingangsvariablen.
  • outputs.tf: Ausgabevariablen.
  • main.tf: Die tatsächlichen Ressourcen.

Module

Normalerweise definieren wir unsere Infrastruktur in zwei Ordnern:

  1. infrastructure-modules: Dieser Ordner enthält kleine, wiederverwendbare, versionierte Module. Stellen Sie sich jedes Modul als Blaupause für die Erstellung einer einzelnen Infrastruktur vor, z. B. einer VPC oder einer Datenbank.
  2. infrastructure-live: Dieser Ordner enthält die aktuelle Live-Infrastruktur, die durch Kombinieren der Module erstellt wird infrastructure-modules. Stellen Sie sich den Code in diesem Ordner als die tatsächlichen Häuser vor, die Sie aus Ihren Bauplänen gebaut haben.

Ein Terraform-Modul ist nur ein beliebiger Satz von Terraform-Vorlagen in einem Ordner. Zum Beispiel könnten wir einen Ordner mit dem Namen haben vpcin infrastructure-modulesdem definiert , all Routing - Tabellen, Subnetzen, Gateways, ACLs, etc. für einen einzelnen VPC:

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

Wir können dieses Modul dann in infrastructure-live/stageund verwenden infrastructure-live/prod, um die Stage- und Prod-VPCs zu erstellen. So infrastructure-live/stage/main.tfkönnte beispielsweise aussehen:

module "stage_vpc" {
  source = "git::[email protected]: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"
}

Um ein Modul zu verwenden, verwenden Sie die moduleRessource und verweisen ihr sourceFeld entweder auf einen lokalen Pfad auf Ihrer Festplatte (z. B. source = "../infrastructure-modules/vpc") oder, wie im obigen Beispiel, auf eine Git-URL (siehe Modulquellen ). Der Vorteil der Git-URL ist, dass wir ein bestimmtes git sha1 oder tag ( ref=v0.0.4) angeben können . Jetzt definieren wir unsere Infrastruktur nicht nur als eine Reihe kleiner Module, sondern können diese Module auch versionieren und bei Bedarf sorgfältig aktualisieren oder zurücksetzen.

Wir haben eine Reihe wiederverwendbarer, getesteter und dokumentierter Infrastrukturpakete zum Erstellen von VPCs, Docker-Clustern, Datenbanken usw. erstellt. Unter der Haube sind die meisten nur versionierte Terraform-Module.

Zustand

Wenn Sie Terraform zum Erstellen von Ressourcen verwenden (z. B. EC2-Instanzen, Datenbanken, VPCs), werden Informationen darüber aufgezeichnet, was in einer .tfstateDatei erstellt wurde. Um Änderungen an diesen Ressourcen vorzunehmen, muss jeder in Ihrem Team auf dieselbe .tfstateDatei zugreifen. Sie sollten sie jedoch NICHT in Git einchecken ( eine Erklärung finden Sie hier ).

Stattdessen empfehlen wir, .tfstateDateien in S3 zu speichern , indem Sie Terraform Remote State aktivieren , das bei jedem Ausführen von Terraform automatisch die neuesten Dateien pusht / zieht. Stellen Sie sicher, dass die Versionierung in Ihrem S3-Bucket aktiviert ist, damit Sie auf ältere .tfstateDateien zurückgreifen können, falls Sie die neueste Version irgendwie beschädigen. Ein wichtiger Hinweis: Terraform bietet keine Verriegelung . Wenn also zwei Teammitglieder terraform applygleichzeitig in derselben .tfstateDatei ausgeführt werden, überschreiben sie möglicherweise die Änderungen des jeweils anderen.

Um dieses Problem zu lösen, haben wir ein Open-Source-Tool namens Terragrunt erstellt , ein Thin Wrapper für Terraform, der Amazon DynamoDB verwendet, um Sperren bereitzustellen (was für die meisten Teams völlig kostenlos sein sollte). Weitere Informationen finden Sie unter Hinzufügen einer automatischen Remote-Status-Sperre und -Konfiguration zu Terraform mit Terragrunt .

Weiterführende Literatur

Wir haben gerade eine Reihe von Blog-Posts mit dem Titel " Ein umfassender Leitfaden für Terraform" gestartet , in denen alle Best Practices, die wir für die Verwendung von Terraform in der realen Welt gelernt haben, ausführlich beschrieben werden.

Update: Der umfassende Leitfaden zu Terraform-Blogpostserien wurde so populär, dass wir ihn zu einem Buch namens Terraform: Up & Running !

Jewgenij Brikman
quelle
Ich denke das ist die richtige Antwort. Verwenden Sie Module, versionieren Sie sie und halten Sie Umgebungen getrennt.
Wrangler
Muss der Remote-Konfigurationsschritt jedes Mal neu ausgeführt werden, wenn Sie an einer anderen Terraform-Komponente / Umgebung / Modul / was auch immer arbeiten möchten, wenn Sie nicht Terragrunt oder einen anderen Wrapper verwenden?
Jmreicha
@jmreicha: Sie müssen ausgeführt werden, remote configwenn Sie gerade Ihre Terraform-Konfigurationen ausgecheckt haben oder wenn Sie eine vorherige Remote-Konfiguration ändern möchten. Terraform 0.9 wird das Konzept von einführen backends, das vieles davon vereinfacht. Weitere Informationen finden Sie in dieser PR .
Jewgenij Brikman
Nur damit ich verstehe - ich arbeite an einer Umweltbühne, beginne dann aber mit der Arbeit an einem Produkt. Ich muss den remote configBefehl erneut ausführen , um auf den Prod-Status zu zeigen. Unter der Annahme eines unterschiedlichen Zustands pro Umgebung. Ist das richtig? Ich freue mich auf v0.9.
Jmreicha
Wenn Sie genau denselben .tfDateisatz in zwei verschiedenen Umgebungen bereitstellen möchten, müssen Sie ihn bei remote configjedem Wechsel ausführen . Dies ist offensichtlich sehr fehleranfällig, daher empfehle ich nicht, diese Technik tatsächlich zu verwenden. Lesen Sie stattdessen das empfohlene Terraform-Dateilayout in diesem Blog-Beitrag sowie die Verwendung von Terraform-Modulen in diesem Blog-Beitrag .
Jewgenij Brikman
9

Früher remote configerlaubt, jetzt aber durch " Backends " ersetzt, so dass Terraform Remote nicht mehr verfügbar ist.

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

Einzelheiten finden Sie in den Dokumenten .

Shantanu
quelle
Muss die Remote-Quelle jedes Mal neu konfiguriert werden, wenn Sie an einer anderen Terraform-Komponente / Umgebung / Modul / was auch immer arbeiten möchten?
jmreicha
6

Ausführlicher von @Yevgeny Brikman behandelt, aber speziell auf die Fragen des OP geantwortet:

Was ist die beste Vorgehensweise zum tatsächlichen Verwalten der Terraform-Dateien und des Status?

Verwenden Sie git für TF-Dateien. Aber checken Sie keine Statusdateien ein (dh tfstate). Verwenden Sie stattdessen Terragruntzum Synchronisieren / Sperren von Statusdateien mit S3.

aber verpflichte ich mich auch tfstate?

Nein.

Sollte das irgendwo wie S3 liegen?

Ja

Snowcrash
quelle
2

Ich weiß, dass es hier viele Antworten gibt, aber mein Ansatz ist ganz anders.

   Modules
   Environment management 
   Separation of duties

Module

  1. Erstellen Sie Module für logische Ressourcensammlungen. Beispiel: Wenn Sie eine API bereitstellen möchten, für die eine Datenbank, HA-VMs, automatische Skalierung, DNS, PubSub und Objektspeicher erforderlich sind, sollten alle diese Ressourcen in einem einzigen Modul zusammengefasst werden.
  2. Vermeiden Sie das Erstellen von Modulen, die eine einzelne Ressource verwenden. Dies kann und wurde getan, und viele Module in der Registrierung tun dies, aber es ist eine Vorgehensweise, die eher beim Zugriff auf Ressourcen als bei der Orchestrierung der Infrastruktur hilft. Beispiel: Ein Modul für AWS EC2 erleichtert dem Benutzer den Zugriff auf EC2, indem es das Aufrufen komplexer Konfigurationen vereinfacht. Ein Modul wie das Beispiel in 1. unterstützt den Benutzer jedoch bei der Orchestrierung der anwendungs-, komponenten- oder dienstgesteuerten Infrastruktur.
    1. Vermeiden Sie Ressourcendeklarationen in Ihrem Arbeitsbereich. Hier geht es mehr darum, Ihren Code aufgeräumt und organisiert zu halten. Da Module einfach versioniert werden können, haben Sie mehr Kontrolle über Ihre Releases.

Umweltmanagement

IaC hat den SDLC-Prozess für das Infrastrukturmanagement relevant gemacht, und es ist nicht normal, dass sowohl Entwicklungsinfrastruktur als auch Entwicklungsanwendungsumgebungen vorhanden sind.

  1. Verwenden Sie keine Ordner zum Verwalten Ihrer IaC-Umgebungen. Dies führt zu Abweichungen, da es keine gemeinsame Vorlage für Ihre Infrastruktur gibt.
  2. Verwenden Sie einen einzelnen Arbeitsbereich und Variablen, um die Umgebungsspezifikationen zu steuern. Beispiel: Schreiben Sie Ihre Module so, dass sich der Plan beim Ändern der Umgebungsvariablen (var.stage ist beliebt) an Ihre Anforderungen anpasst. Typischerweise sollten die Umgebungen so wenig wie möglich variieren, wobei Menge, Exposition und Kapazität normalerweise die variablen Konfigurationen sind. Dev stellt möglicherweise 1 VM mit 1 Kern und 1 GB RAM in privater Topologie bereit, aber die Produktion kann 3 VMs mit 2 Kernen und 4 GB RAM mit zusätzlicher öffentlicher Topologie umfassen. Sie können natürlich mehr Variationen haben: dev kann den Datenbankprozess auf demselben Server wie die Anwendung ausführen, um Kosten zu sparen, aber die Produktion verfügt möglicherweise über eine dedizierte DB-Instanz. All dies kann durch Ändern einer einzelnen Variablen, ternäre Anweisungen und Interpolation verwaltet werden.

Aufgabentrennung

Wenn Sie sich in einer kleinen Organisation befinden oder eine persönliche Infrastruktur betreiben, trifft dies nicht wirklich zu, hilft Ihnen jedoch bei der Verwaltung Ihrer Vorgänge.

  1. Teilen Sie Ihre Infrastruktur nach Aufgaben, Verantwortlichkeiten oder Teams auf. Beispiel: Zentrale IT-Steuerung, die gemeinsam genutzten Diensten zugrunde liegt (virtuelle Netzwerke, Subnetze, öffentliche IP-Adressen, Protokollgruppen, Governance-Ressourcen, DBs mit mehreren Mandanten, gemeinsam genutzte Schlüssel usw.), während das API-Team nur die für ihren Dienst erforderlichen Ressourcen (VMs, LBs) steuert , PubSub usw.) und nutzen zentrale IT-Dienste über Datenquellen- und Remote-Status-Lookups.
    1. Teamzugriff regeln. Beispiel: Die zentrale IT verfügt möglicherweise über Administratorrechte, das API-Team hat jedoch nur Zugriff auf einen eingeschränkten Satz öffentlicher Cloud-APIs.

Dies hilft auch bei Release-Problemen, da sich einige Ressourcen selten ändern, während sich andere ständig ändern. Durch die Trennung werden Risiken und Komplexität beseitigt.

Diese Strategie weist Parallelen zur Multi-Account-Strategie von AWS auf. Lesen Sie für weitere Informationen.

CI / CD

Dies ist ein eigenes Thema, aber Terraform funktioniert sehr gut in einer guten Pipeline. Der häufigste Fehler besteht darin, CI als Silberkugel zu behandeln. Technisch gesehen sollte Terraform die Infrastruktur nur in Phasen einer Montagepipeline bereitstellen. Dies würde sich von dem unterscheiden, was in CI-Phasen geschieht, in denen die Vorlagen normalerweise validiert und getestet werden.

NB Geschrieben auf dem Handy, entschuldigen Sie bitte alle Fehler.

Henry Dobson
quelle
0

Bevor die Antworten sehr solide und informativ waren, werde ich versuchen, meine 2 Cent hier hinzuzufügen

Allgemeine Empfehlungen zur Strukturierung von Code

  1. Es ist einfacher und schneller, mit einer geringeren Anzahl von Ressourcen zu arbeiten:

    • Cmds terraform planund terraformapply führen beide Cloud-API-Aufrufe durch, um den Status der Ressourcen zu überprüfen.
    • Wenn Sie Ihre gesamte Infrastruktur in einer einzigen Komposition haben, kann dies viele Minuten dauern (selbst wenn Sie mehrere Dateien im selben Ordner haben).
  2. Der Explosionsradius ist mit weniger Ressourcen kleiner:

    • Das Isolieren nicht verwandter Ressourcen voneinander, indem sie in separaten Kompositionen (Ordnern) abgelegt werden, verringert das Risiko, wenn etwas schief geht.
  3. Starten Sie Ihr Projekt mit dem Remote-Status:

  4. Versuchen Sie, eine konsistente Struktur- und Namenskonvention zu üben:

    • Wie bei prozeduralem Code sollte Terraform- Code so geschrieben werden, dass die Benutzer ihn zuerst lesen können. Konsistenz hilft, wenn in sechs Monaten Änderungen vorgenommen werden.
    • Es ist möglich, Ressourcen in der Terraform-Statusdatei zu verschieben , dies ist jedoch möglicherweise schwieriger, wenn Sie eine inkonsistente Struktur und Benennung haben.
  5. Halten Sie Ressourcenmodule so einfach wie möglich.

  6. Nicht schwer Code Werte , die als Variablen übergeben werden können oder entdeckt Datenquellen.

  7. Verwenden Sie dataQuellen und terraform_remote_stateinsbesondere als Klebstoff zwischen Infrastrukturmodulen innerhalb der Komposition.

( siehe Artikel: https://www.terraform-best-practices.com/code-structure )


Beispiel:

Es ist einfacher und schneller, mit einer geringeren Anzahl von Ressourcen zu arbeiten. Im Folgenden wird ein empfohlenes Codelayout vorgestellt.

HINWEIS: Nur als Referenz, die nicht unbedingt befolgt werden muss, da jedes Projekt seine eigenen spezifischen Merkmale aufweist

.
├── 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
Exequiel Barrirero
quelle
0

Ich glaube, es gibt nur wenige Best Practices, die bei der Verwendung von Terraform für die Orchestrierung der Infrastruktur befolgt werden müssen

  1. Schreiben Sie nicht denselben Code erneut (Wiederverwendbarkeit)
  2. Halten Sie die Umgebungskonfiguration getrennt, um sie einfach zu warten.
  3. Verwenden Sie das Remote-Backend s3 (verschlüsselt) und die Dynamo-Datenbank, um die Parallelitätssperre zu handhaben
  4. Erstellen Sie ein Modul und verwenden Sie dieses Modul mehrmals in der Hauptinfrastruktur. Dies ähnelt einer wiederverwendbaren Funktion, die durch Übergabe verschiedener Parameter mehrmals aufgerufen werden kann.

Behandeln Sie mehrere Umgebungen

In den meisten Fällen wird empfohlen, den Terraform-Arbeitsbereich für die verschiedenen Umgebungen zu verwenden. Ich glaube jedoch, dass die Verwendung des Arbeitsbereichs je nach Arbeitsweise in einer Organisation variieren kann. Andere speichern den Terraform-Code für jede Ihrer Umgebungen (z. B. Stufe, Produkt, Qualitätssicherung), um die Umgebungszustände zu trennen. In diesem Fall kopieren wir jedoch nur an vielen Stellen denselben Code.

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

Ich verfolgte einen anderen Ansatz, um das Duplizieren desselben Terraform-Codes zu handhaben und zu vermeiden, indem ich in jedem Umgebungsordner behielt, da ich glaube, dass die gesamte Umgebung zu 90% gleich ist.

├── 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

Konfiguration in Bezug auf Umgebungen

Halten Sie die umgebungsbezogene Konfiguration und Parameter in einer variablen Datei getrennt und übergeben Sie diesen Wert, um die Infrastruktur zu konfigurieren. zB wie unten

  • 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"

Bedingtes Überspringen des Infrastrukturteils

Erstellen Sie eine Konfiguration in einer env-spezifischen Variablendatei und entscheiden Sie sich basierend auf dieser Variablen, diesen Teil zu erstellen oder zu überspringen. Auf diese Weise kann je nach Bedarf der spezifische Teil der Infrastruktur übersprungen werden.

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"
}

Der folgende Befehl ist erforderlich, um die Infra-Änderungen für jede Umgebung zu initialisieren und auszuführen. CD in den erforderlichen Umgebungsordner.

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

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

Als Referenz: https://github.com/mattyait/devops_terraform

Mahattam
quelle
0

Ich mag die Idee von Unterordnern nicht, da dies zu unterschiedlichen Quellen pro Umgebung führt und dazu neigt, zu driften.

Der bessere Ansatz besteht darin, einen einzigen Stapel für alle Umgebungen zu haben (sagen wir dev, preprod und prod). Verwenden Sie zum Arbeiten in einer einzelnen Umgebung terraform workspace.

terraform workspace new dev

Dadurch wird ein neuer Arbeitsbereich erstellt. Dies umfasst eine dedizierte Statusdatei und die Variable, die terraform.workspaceSie in Ihrem Code verwenden können.

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

Auf diese Weise erhalten Sie Eimer aufgerufen

  • my-tf-test-Bucket-Dev
  • my-tf-test-Bucket-Preprod
  • my-tf-test-Bucket-Prod

nach dem Anwenden auf die oben genannten Arbeitsbereiche ( terraform workspace select <WORKSPACE>zum Ändern von Umgebungen verwenden). Um den Code noch mehrregionssicher zu machen, gehen Sie folgendermaßen vor:

data "aws_region" "current" {}

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

zu bekommen (für uns-Ost-1 Region)

  • my-tf-test-buckel-us-east-1-dev
  • my-tf-test-buckel-us-east-1-preprod
  • my-tf-test-buckel-us-east-1-prod
Magister Halderian
quelle
0

Einige bewährte Methoden für Terraform:

  1. Vermeiden Sie harte Codierung: Manchmal haben Entwickler Ressourcen direkt manuell erstellt. Sie müssen diese Ressource markieren und den Terraform-Import verwenden, um sie in Codes aufzunehmen. Eine Probe:

    account_number = "123456789012" account_alias = "mycompany"

  2. Ausführen von Terraform aus einem Docker-Container: Terraform gibt einen offiziellen Docker-Container frei, mit dem Sie einfach steuern können, welche Version Sie ausführen können.

Es wird empfohlen, den Terraform Docker-Container auszuführen, wenn Sie Ihren Build-Job in der CI / CD-Pipeline festlegen.

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"

Weitere Informationen finden Sie in meinem Blog: https://medium.com/tech-darwinbox/how-darwinbox-manages-infrastructure-at-scale-with-terraform-371e2c5f04d3

ND1772
quelle
0

Ich möchte zu diesem Thread beitragen.

  • Dies ist höchstwahrscheinlich AWS S3 + DynamoDB, sofern Sie nicht Terraform Cloud verwenden.
  • Separate Infrastruktur (Netzwerk + RBAC) für Produktions- und Nicht-Produkt-Backends.
  • Planen Sie, den Zugriff auf Statusdateien (Netzwerkzugriff und RBAC) von außerhalb eines bestimmten Netzwerks (z. B. Deployment Agent Pool) zu deaktivieren.
  • Behalten Sie die Terraform-Backend-Infrastruktur nicht in der Laufzeitumgebung bei. Verwenden Sie ein separates Konto.
  • Aktivieren Sie die Objektversionierung in Ihren Terraform-Backends, um den Verlust von Änderungen und Statusdateien zu vermeiden und den Terraform-Statusverlauf beizubehalten.

In einigen besonderen Fällen ist ein manueller Zugriff auf Terraform-Statusdateien erforderlich. Dinge wie Refactoring, Änderungen oder das Beheben von Fehlern erfordern die Ausführung von Terraform-Statusoperationen durch das Betriebspersonal. Planen Sie für solche Gelegenheiten einen außergewöhnlich kontrollierten Zugriff auf den Terraform-Status mithilfe von Bastion Host, VPN usw.

Überprüfen Sie ein längeres Best Practices-Blog , das dies ausführlich behandelt, einschließlich Richtlinien für CI / CD-Pipelines.

Piotr Gwiazda
quelle
-1

Wenn Sie immer noch nach der besseren Lösung suchen, werfen Sie einen Blick auf Arbeitsbereiche, die die Verwaltung unterschiedlicher Umgebungsordnerstrukturen ersetzen können und arbeitsbereichsspezifische Variablen enthalten können.

Wie Jewgenij Brikman erwähnte, ist es besser, eine Modulstruktur zu haben.

Rajendra
quelle
-1

Verwenden Sie die Terraform Cloud zum Verwalten und Speichern von Status zusammen mit den oben genannten Hinweisen.

Den Zalman
quelle