Best Practices
Production-ready Terraform Projekte.
Lernziele
Nach dieser Lektion kennst du die Muster production-ready Terraform-Projekte: Repository-Struktur, Secret-Handling, Versionierung, Blast-Radius-Kontrolle und operativer Betrieb. Du kannst ein Projekt anhand einer Checkliste bewerten und typische Anti-Patterns in bestehenden Codebases erkennen.
Das Problem: Tutorial-Terraform in Produktion
Viele Teams starten mit einem main.tf in einem Repo — und wachsen nie darüber hinaus. Drei Jahre später: 2.000 Zeilen in einer Datei, Secrets in tfvars auf Laptops, ein State für alles, kein Linting, Provider unpinned, und niemand traut sich an terraform apply in Prod.
Best Practices sind keine pedantischen Regeln — sie sind die Antwort auf Incidents, die andere Teams schon hatten. Du musst sie nicht alle am ersten Tag umsetzen, aber du musst sie benennen können — im Interview und im Architektur-Review.
Repository-Struktur: lesbar und reviewbar
Ein bewährtes Layout:
platform-infra/
├── modules/ # wiederverwendbare Bausteine
│ ├── vpc/
│ └── eks/
├── env/
│ ├── dev/
│ ├── staging/
│ └── prod/
│ ├── main.tf
│ ├── backend.tf
│ ├── variables.tf
│ └── terraform.tfvars # nicht für Secrets!
├── .terraform.lock.hcl
├── .gitignore # *.tfstate, .terraform/
└── .github/workflows/
Prinzipien:
- Ein State pro Umgebung/Stack — nicht ein Monolith
- Module für Wiederverwendung, dünne Root-Module pro Env
- Keine Secrets in Git — weder in
.tfnoch in.tfvars - Lock-Datei committen — reproduzierbare Provider
Dateinamen sind Konvention, nicht Gesetz — aber main.tf + variables.tf + outputs.tf pro Modul hilft Reviewern.
Secrets: sensitive ist kein Vault
variable "db_password" {
type = string
sensitive = true
}
sensitive = true versteckt den Wert in der CLI-Ausgabe — nicht im State. Der State liegt unverschlüsselt lesbar in S3, wenn du encrypt = false setzt.
Production-Patterns:
- Secrets aus Vault, AWS Secrets Manager oder SSM Parameter Store via Data Source zur Laufzeit
- CI injects Secrets als
TF_VAR_*— nie in Repo - State-Bucket: SSE-KMS, Zugriff nur für Pipeline-Rolle
- Keine Passwörter in
terraform.tfvars—.gitignorereicht nicht, wenn es schon committed war
Blast Radius: kleine States, klare Grenzen
Je größer der State, desto länger Plan/Apply, desto höher das Risiko eines fehlgeschlagenen Applies mitten in 200 Ressourcen.
Stack-Schnitt typischerweise entlang von:
- Lifecycle: Netzwerk (selten) vs. Apps (häufig)
- Team-Ownership: Platform-Team vs. Produktteam
- Blast Radius: Datenbank-Stack getrennt von Compute
terraform apply sollte in unter wenigen Minuten durchlaufen — wenn nicht, ist der Stack zu groß.
Versionierung und Upgrade-Disziplin
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
- Terraform CLI und Provider separat pinnen
- Upgrades in Staging zuerst; Changelog lesen
moved-Blöcke statt manuellemstate mvbei Resource-Renames (ab TF 1.1)- Dependabot/Renovate für Provider-Updates mit CI-Plan als Gate
Operativer Betrieb: mehr als Apply
| Praxis | Zweck |
|---|---|
| Drift-Detection (scheduled plan) | ClickOps finden |
| State-Backup (S3-Versionierung) | Recovery bei Korruption |
prevent_destroy auf kritische Resources | Schutz vor terraform destroy |
| Runbooks für State Lock, Import, Recovery | On-Call-tauglich |
CODEOWNERS auf /env/prod/ | Pflicht-Review für Prod |
Tagging-Standard: Jede Resource bekommt Environment, ManagedBy = terraform, Team — über default_tags am Provider oder ein Label-Modul. Ohne Tags ist Cost Allocation und Incident-Scoping unmöglich.
Anti-Patterns — explizit benennen
terraform applylokal auf Prod — CI-only für Prod-targetals Workflow — technische Schuld- Monolith-State — alles in einem Apply
- Copy-Paste statt Module — Drift garantiert
- Kein Plan-Review — Blind Apply
- Provider unpinned — Breaking Changes über Nacht
- State in Git — Security-Incident waiting to happen
- count/for_each mit hartem Index —
[0]bricht bei Reorder
Praxis: Projekt-Checkliste durchgehen
Nimm ein bestehendes Lab oder Repo und prüfe:
# Struktur
ls -la env/ modules/ 2>/dev/null || echo "Keine env/modules-Trennung"
# Secrets in Git?
git log -p -- '*.tfvars' | head -20
# State lokal?
test -f terraform.tfstate && echo "WARN: lokaler State" || echo "OK"
# Lockfile?
test -f .terraform.lock.hcl && echo "OK: Lockfile" || echo "WARN: kein Lock"
# fmt
terraform fmt -check -recursive && echo "OK: fmt" || echo "FIX: fmt"
Dokumentiere Findings — das ist ein realistisches Platform-Engineering-Audit.
Typische Stolperfallen
Best Practices als Big-Bang: Alles auf einmal refactoren blockiert Features. Inkrementell: erst Remote State, dann Module, dann CI — eine Sache pro Sprint.
Golden Path ohne Escape Hatch: Teams umgehen Terraform, wenn der offizielle Weg zu langsam ist. Dokumentierter Escape mit Zeitlimit schlägt verstecktes ClickOps.
Dokumentation in Confluence, Code in Git: Runbooks veralten. README im Repo mit Backend-Setup, Apply-Prozess und Notfall-Kontakten.
prevent_destroy überall: Schützt zwar, blockiert aber legitime Replacements. Nur auf wirklich kritische Stateful Resources.
Interview-Vorbereitung
„Wie sieht production-ready Terraform aus?” — Struktur (Module, env-Stacks), Remote State + Lock, Secrets external, CI Plan/Apply, Version Pinning, Drift-Detection, Tagging, kleine Blast Radius.
Follow-ups:
- „Wo liegen Secrets?” — Vault/SSM/Secrets Manager; nie im State unverschlüsselt blind vertrauen.
- „Wie groß soll ein State sein?” — Klein genug für schnellen Plan; getrennt nach Lifecycle und Ownership.
- „Größtes Anti-Pattern?” — Local apply auf Prod, Monolith-State, State in Git — eines konkret ausarbeiten.
- „Wie upgradest du Provider?” — Changelog, Staging, plan, Lockfile update.
Zusammenfassung
Production-ready Terraform bedeutet: klare Repo-Struktur mit Modulen und getrennten Env-Stacks, Remote State mit Verschlüsselung, Secrets außerhalb von Git, gepinnte Versionen, CI-gated Plan/Apply, Drift-Detection und kleine Blast Radii. Anti-Patterns wie Monolith-State, lokaler Prod-Apply und unpinned Provider sind bewusst zu vermeiden — nicht aus Pedanterie, sondern weil die Alternativen teuer sind.
In der abschließenden Lektion bündeln wir alles für die Interview-Vorbereitung — typische Fragen, Antwortstrukturen und Troubleshooting-Szenarien aus dem gesamten Lernpfad.