🏗️ Terraform Lektion 5/15 ~7 Min. Fortgeschritten

State Management Grundlagen

terraform.tfstate — warum und wie.

📝 Meine Notizen

Lernziele

Nach dieser Lektion kannst du erklären, warum Terraform State existiert und was darin steht. Du kennst die Befehle state list, show, mv und rm, verstehst State Locking und weißt, warum terraform.tfstate niemals ins Git gehört. Außerdem kannst du den Unterschied zwischen Config-Drift und State-Drift benennen.

Das Problem: Terraform kennt die Cloud nicht von selbst

Stell dir vor, du hast gestern per Terraform einen S3-Bucket angelegt. Heute führst du terraform plan aus — wie soll Terraform wissen, dass aws_s3_bucket.artifacts dieser eine Bucket in deinem AWS-Account ist und nicht ein neuer, den es gerne anlegen würde?

Die Cloud-API kennt keine Terraform-Namen. Sie kennt nur ARNs, IDs und Tags. State ist die Brücke: eine JSON-Datei (standardmäßig terraform.tfstate), die jeden Resource-Block in deinem Code mit der realen ID in der Cloud verknüpft — plus gespeicherte Attribute, Abhängigkeiten und Metadaten.

Ohne State müsste Terraform bei jedem Lauf alle Ressourcen in der Cloud durchsuchen und raten, was wozu gehört. Das wäre langsam, fehleranfällig und bei gleichnamigen Ressourcen unmöglich.

Was im State steht — und was nicht

Der State enthält pro Resource:

  • Typ und Name im Code (aws_s3_bucket.artifacts)
  • ID in der Cloud (arn:aws:s3:::platprep-artifacts)
  • Attribute — auch solche, die du nicht explizit gesetzt hast (computed values)
  • Abhängigkeiten (dependencies-Array)
  • Metadata — z. B. serial, lineage für Konsistenzprüfungen

Was der State nicht ersetzt: Er ist kein Backup deiner Infrastruktur. Löschst du den State und die Ressourcen existieren noch, weiß Terraform nichts mehr von ihnen — du musst importieren (Lektion 13). Löschst du den State und führst terraform destroy aus, passiert nichts, weil Terraform nicht weiß, was es zerstören soll.

Secrets im State: Auch mit sensitive = true in Variables landen Werte im State im Klartext. Deshalb gehört terraform.tfstate nicht ins Git und muss at rest verschlüsselt werden (Lektion 6).

State-Befehle: chirurgische Eingriffe

Manchmal musst du den State manuell anpassen — nicht die Cloud, sondern nur die Zuordnung:

# Was verwaltet Terraform?
terraform state list

# Details einer Resource
terraform state show aws_s3_bucket.artifacts

# Resource im Code umbenennen, ohne Cloud-Objekt neu anzulegen
terraform state mv aws_s3_bucket.old_name aws_s3_bucket.new_name

# Resource aus State entfernen (Cloud-Objekt bleibt!)
terraform state rm aws_s3_bucket.artifacts

state mv ist der saubere Weg bei Refactorings: Du änderst den lokalen Namen im HCL und verschiebst den State-Eintrag — kein Destroy/Create in der Cloud. state rm entfernt die Verwaltung: Terraform „vergisst” die Resource. Nützlich, wenn du eine Resource an ein anderes Modul übergeben willst, ohne sie physisch zu löschen.

Vorsicht: State-Manipulation ohne Backup ist riskant. Vor jedem mv oder rm: State-Backup ziehen (terraform state pull > backup.json).

State Locking: kein paralleler Apply

Zwei Entwickler, die gleichzeitig terraform apply ausführen, können den State gegenseitig überschreiben — mit korruptem State und halb angewendeten Änderungen als Ergebnis. State Locking verhindert das: Bevor Apply oder State-Schreiboperationen starten, setzt Terraform ein Lock.

Lokal (Default-Backend) gibt es kein echtes Locking — nur ein Warnhinweis. Deshalb ist lokaler State für Teams ungeeignet. Remote Backends (S3 + DynamoDB, Terraform Cloud, GCS) implementieren echtes Locking (Lektion 6).

Symptom eines hängenden Locks: Error acquiring the state lock. Ursache oft: abgebrochener Apply, der das Lock nicht freigegeben hat. Lösung: terraform force-unlock <LOCK_ID> — nur wenn du sicher bist, dass kein anderer Apply läuft.

Drift: wenn Realität und Code auseinanderlaufen

Config-Drift: Jemand ändert in der AWS-Console ein Tag oder öffnet einen Port — der Code bleibt gleich. Beim nächsten plan zeigt Terraform die Abweichung und will zurück zum Code-Zustand.

State-Drift: Der State stimmt nicht mehr mit der Realität überein — z. B. nach manuellem Löschen einer Resource in der Console. Terraform denkt, sie existiert noch; apply schlägt fehl.

Gegenmaßnahmen: Kein ClickOps in Terraform-verwalteter Infra, regelmäßiger plan in CI (Drift-Detection), und bei Bedarf terraform refresh bzw. -refresh-only planen.

Praxis: State mit dem local-Provider erkunden

mkdir state-lab && cd state-lab
cat > main.tf <<'EOF'
resource "random_pet" "server" {
  length = 2
}

output "pet_name" {
  value = random_pet.server.id
}
EOF

terraform init && terraform apply -auto-approve
terraform state list
terraform state show random_pet.server
cat terraform.tfstate | jq '.resources[0].instances[0].attributes.id'

# Umbenennen im Code + State mv
# (random_pet.server → random_pet.app in main.tf ändern)
terraform state mv random_pet.server random_pet.app
terraform plan   # sollte "No changes" zeigen
terraform destroy

Schau dir terraform.tfstate einmal im Editor an — aber committe sie nie. Du siehst die exakte JSON-Struktur, die Terraform intern nutzt.

Typische Stolperfallen

State ins Git committen: Enthält IDs, manchmal Secrets, und ist die Single Source of Truth für deine Infra-Zuordnung. .gitignore mit *.tfstate und *.tfstate.backup ist Pflicht.

Lokalen State im Team teilen: Per Slack oder USB-Stick — garantiert Korruption. Ab zwei Personen: Remote Backend.

state rm statt destroy missverstehen: rm löscht nichts in der Cloud. Die Resource wird zur „Waisen”-Ressource — weiterhin in AWS, aber nicht mehr von Terraform verwaltet.

Lock ignorieren und force-unlock reflexartig nutzen: Erst prüfen, ob wirklich kein Apply läuft. Ein Unlock während eines laufenden Apply kann den State beschädigen.

Interview-Vorbereitung

„Warum braucht Terraform State?” — Um Code-Blöcke mit realen Cloud-IDs zu verknüpfen, Diffs zu berechnen und Abhängigkeiten zu tracken. Deklarativ heißt nicht „stateless”.

Follow-ups:

  • „Was passiert, wenn du den State verlierst?” — Terraform kennt die Ressourcen nicht mehr; Import oder manuelles Rekonstruieren nötig; Cloud-Ressourcen laufen weiter.
  • „Unterschied state mv vs. Resource im Code löschen und neu anlegen?” — mv behält die Cloud-Ressource; Löschen + Neuanlegen würde destroy/create triggern.
  • „Was ist State Locking?” — Mechanismus gegen parallele Writes; Remote Backends setzen ein Lock vor Apply.
  • „Enthält der State Secrets?” — Ja, im Klartext; deshalb Verschlüsselung und kein Git.

Zusammenfassung

State mappt deine HCL-Ressourcen auf echte Cloud-IDs und ist Voraussetzung für jeden Plan. Du manipulierst ihn chirurgisch mit state list/show/mv/rm, schützt ihn vor parallelen Writes durch Locking und lässt ihn nie ins Git. Config-Drift erkennst du per plan; State-Drift vermeidest du durch disziplinierten Betrieb ohne ClickOps.

In der nächsten Lektion verlagern wir den State ins Remote Backend — damit Teams sicher zusammenarbeiten können.