Terraform erfasst jede Ressource, die es verwaltet, in einer State-Datei — einem JSON-Dokument, das Ihre Konfiguration auf die tatsächliche Infrastruktur abbildet. Wenn Sie allein mit einer lokalen State-Datei arbeiten, ist alles einfach. Aber sobald ein zweiter Ingenieur die gleiche Infrastruktur berührt oder eine CI-Pipeline parallel läuft, wird der lokale State zum Problem. Dieser Leitfaden behandelt, wie der Terraform State intern funktioniert, wie Sie Remote-Backends für die Teamzusammenarbeit konfigurieren und wie Sie die operativen Herausforderungen des State-Managements im großen Maßstab bewältigen.

Voraussetzungen

  • Terraform CLI v1.6 oder höher installiert
  • Ein AWS-Konto mit Berechtigungen zum Erstellen von S3-Buckets und DynamoDB-Tabellen (für S3-Backend-Beispiele)
  • Azure CLI mit einem authentifizierten Abonnement (für Azure Storage-Backend-Beispiele)
  • Grundverständnis von Terraform-Ressourcenblöcken und dem terraform apply-Workflow
  • Ein Versionskontrollsystem (Git) zum Speichern Ihrer Terraform-Konfigurationen

Den Terraform State verstehen

Jedes Mal, wenn Sie terraform apply ausführen, schreibt Terraform eine terraform.tfstate-Datei, die die Zuordnung zwischen Ihrer HCL-Konfiguration und den tatsächlichen Infrastrukturressourcen aufzeichnet. Diese Datei enthält:

  • Ressourcen-IDs — die eindeutige Kennung, die jeder Cloud-Anbieter einer Ressource zuweist (z.B. i-0abc123def456, eine Azure-Ressourcen-ID)
  • Attributwerte — jedes berechnete Attribut wie IP-Adressen, ARNs, generierte Passwörter
  • Abhängigkeitsgraph-Metadaten — die Reihenfolge, in der Ressourcen erstellt oder zerstört werden müssen
  • Provider-Konfiguration — welche Provider-Version und Konfiguration verwendet wurde

Hier ist ein vereinfachter Ausschnitt einer State-Datei:

{
  "version": 4,
  "terraform_version": "1.6.0",
  "resources": [
    {
      "mode": "managed",
      "type": "aws_instance",
      "name": "web",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "attributes": {
            "id": "i-0abc123def456789",
            "ami": "ami-0c55b159cbfafe1f0",
            "instance_type": "t3.micro",
            "public_ip": "54.210.167.99"
          }
        }
      ]
    }
  ]
}

Die State-Datei ist die einzige Quelle der Wahrheit für Terraform. Ohne sie kann Terraform nicht feststellen, was in Ihrer Infrastruktur existiert, und würde versuchen, alles von Grund auf neu zu erstellen. Der Verlust oder die Beschädigung der State-Datei ist einer der gefährlichsten operativen Ausfälle in einem Terraform-Workflow.

Remote-Backends konfigurieren

Ein Remote-Backend speichert die State-Datei an einem gemeinsamen, dauerhaften Ort statt im lokalen Dateisystem. Jede Backend-Option hat unterschiedliche Kompromisse hinsichtlich Kosten, Komplexität und Funktionsumfang.

S3-Backend (AWS)

Das häufigste Backend für AWS-zentrierte Teams. Erstellen Sie zunächst die unterstützende Infrastruktur:

# S3-Bucket für State-Speicherung erstellen
aws s3api create-bucket \
  --bucket my-terraform-state-prod \
  --region us-east-1

# Versionierung für State-Wiederherstellung aktivieren
aws s3api put-bucket-versioning \
  --bucket my-terraform-state-prod \
  --versioning-configuration Status=Enabled

# DynamoDB-Tabelle für State-Sperrung erstellen
aws dynamodb create-table \
  --table-name terraform-locks \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST

Konfigurieren Sie dann das Backend in Ihrem Terraform-Code:

terraform {
  backend "s3" {
    bucket         = "my-terraform-state-prod"
    key            = "infrastructure/prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

Azure Storage-Backend

Für Azure-Teams verwenden Sie ein Speicherkonto mit einem Blob-Container:

# Ressourcengruppe erstellen
az group create --name rg-terraform-state --location eastus

# Speicherkonto erstellen
az storage account create \
  --name tfstateaccount2026 \
  --resource-group rg-terraform-state \
  --sku Standard_LRS \
  --encryption-services blob

# Blob-Container erstellen
az storage container create \
  --name tfstate \
  --account-name tfstateaccount2026
terraform {
  backend "azurerm" {
    resource_group_name  = "rg-terraform-state"
    storage_account_name = "tfstateaccount2026"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
  }
}

Google Cloud Storage-Backend

terraform {
  backend "gcs" {
    bucket = "my-terraform-state-bucket"
    prefix = "terraform/state"
  }
}

Terraform Cloud-Backend

HCP Terraform (ehemals Terraform Cloud) bietet ein verwaltetes Backend mit integrierter Benutzeroberfläche, Kostenabschätzung und Richtliniendurchsetzung:

terraform {
  cloud {
    organization = "my-org"
    workspaces {
      name = "production-infra"
    }
  }
}

State-Sperrung

Wenn zwei Ingenieure oder CI-Jobs gleichzeitig terraform apply gegen denselben State ausführen, überschreibt einer die Änderungen des anderen, was zu State-Korruption und verwaisten Ressourcen führt. State-Sperrung verhindert dies, indem vor jeder state-ändernden Operation eine exklusive Sperre erworben wird.

Mit dem S3-Backend stellt DynamoDB die Sperre bereit. Wenn Terraform einen Plan oder Apply startet, schreibt es einen Sperreintrag:

{
  "LockID": "my-terraform-state-prod/infrastructure/prod/terraform.tfstate",
  "Info": "{\"ID\":\"abc-123\",\"Operation\":\"OperationTypeApply\",\"Who\":\"jcarlos@workstation\"}"
}

Wenn ein anderer Prozess versucht, die Sperre zu erwerben, blockiert Terraform mit:

Error: Error acquiring the state lock
Lock Info:
  ID:        abc-123
  Path:      infrastructure/prod/terraform.tfstate
  Operation: OperationTypeApply
  Who:       jcarlos@workstation
  Created:   2026-02-21 10:15:00.000000 UTC

Um eine hängende Sperre manuell freizugeben (mit äußerster Vorsicht verwenden):

terraform force-unlock abc-123

Geben Sie die Sperre nur manuell frei, wenn Sie sicher sind, dass keine andere Operation läuft. Eine Sperre, die nach einem abgestürzten Prozess hängt, ist sicher freizugeben; eine Sperre, die von einem aktiven Apply gehalten wird, nicht.

State-Migration

Von Lokal zu Remote

Nachdem Sie einen backend-Block zu Ihrer Konfiguration hinzugefügt haben, führen Sie aus:

terraform init

# Terraform erkennt die Backend-Änderung:
# Initializing the backend...
# Do you want to copy existing state to the new backend?
# Enter a value: yes

Terraform kopiert Ihre lokale terraform.tfstate zum Remote-Backend und erstellt ein lokales Backup unter terraform.tfstate.backup.

Zwischen Remote-Backends

Um den State von einem Remote-Backend zu einem anderen zu verschieben:

  1. Aktualisieren Sie die Backend-Konfiguration auf das neue Ziel
  2. Führen Sie terraform init -migrate-state aus
  3. Bestätigen Sie die Migration
terraform init -migrate-state

Einzelne Ressourcen verschieben

Verwenden Sie terraform state mv, um Ressourcen zwischen State-Dateien zu refaktorieren oder umzubenennen:

# Eine Ressource innerhalb desselben States umbenennen
terraform state mv aws_instance.old_name aws_instance.new_name

# Eine Ressource in eine andere State-Datei verschieben
terraform state mv -state-out=other.tfstate aws_instance.web aws_instance.web

Um eine Ressource aus dem State zu entfernen, ohne sie zu zerstören (nützlich beim Import in ein anderes Modul):

terraform state rm aws_instance.legacy_server

Backend-Vergleich

FunktionS3 + DynamoDBAzure StorageGCSTerraform CloudConsul
State-SperrungDynamoDB-TabelleNativer Blob-LeaseNativIntegriertNativ
Verschlüsselung im RuhezustandSSE-S3 / SSE-KMSAzure-verwaltete SchlüsselGoogle-verwaltete SchlüsselIntegriertes AES-256Manuelle TLS-Konfiguration
VersionierungS3-VersionierungBlob-VersionierungObjektversionierungIntegriertManuell
Kosten~1 $/Monat (geringe Nutzung)~1 $/Monat~1 $/MonatKostenloser Tarif (500 Ressourcen)Selbst gehostet
ZugriffskontrolleIAM-RichtlinienAzure RBACIAM-RichtlinienTeams + SSOACL-Tokens
KonfigurationskomplexitätMittel (2 Ressourcen)Mittel (3 Ressourcen)Niedrig (1 Bucket)Niedrig (SaaS)Hoch (Cluster)
Am besten fürAWS-TeamsAzure-TeamsGCP-TeamsMulti-Cloud, RichtlinienOn-Premises

Praxisszenario

Ihr Team von fünf Ingenieuren verwaltet über 200 AWS-Ressourcen in drei Umgebungen — Dev, Staging und Produktion. Alle haben Terraform lokal ausgeführt und State-Dateien in Git committet. An einem Montagmorgen wenden zwei Ingenieure gleichzeitig Änderungen am Produktions-VPC an: einer fügt ein Subnet hinzu, der andere ändert eine Security Group. Das zweite Apply überschreibt den State des ersten Ingenieurs, und Terraform weiß nichts mehr vom neuen Subnet. Das Subnet existiert in AWS, ist aber für Terraform unsichtbar — eine „Phantomressource”, die bei jedem zukünftigen Plan Konflikte verursachen wird.

Die Lösung: Konfigurieren Sie ein S3-Backend mit DynamoDB-Sperrung und organisieren Sie den State nach Umgebung:

terraform {
  backend "s3" {
    bucket         = "acme-terraform-state"
    key            = "env/${terraform.workspace}/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
# Isolierte Workspaces erstellen
terraform workspace new dev
terraform workspace new staging
terraform workspace new production

# Umgebung wechseln
terraform workspace select production
terraform apply

Jetzt hat jede Umgebung ihre eigene State-Datei unter einem separaten Schlüsselpräfix, die Sperrung verhindert gleichzeitige Änderungen, und die Versionierung ermöglicht ein Rollback, wenn etwas schiefgeht.

Fallstricke und Sonderfälle

Sensible Daten im State — Terraform speichert Ressourcenattribute im Klartext, einschließlich Datenbankpasswörter, API-Schlüssel und TLS-Zertifikate. Selbst mit Verschlüsselung im Ruhezustand kann jeder mit Lesezugriff auf die State-Datei Geheimnisse einsehen. Verwenden Sie sensitive = true bei Outputs und Variablen, um deren Anzeige in der CLI-Ausgabe zu verhindern, aber wissen Sie, dass sie weiterhin in der State-Datei existieren. Beschränken Sie den State-Zugriff auf die minimale Anzahl von Personen und Pipelines.

State-Drift — Wenn jemand die Infrastruktur außerhalb von Terraform ändert (z.B. über die AWS-Konsole), wird die State-Datei veraltet. Führen Sie regelmäßig terraform plan aus, um Drift zu erkennen. Verwenden Sie terraform refresh (oder den integrierten Refresh während des Plans), um den State ohne Änderungsanwendung zu aktualisieren.

Partielle Anwendungen — Wenn terraform apply mittendrin fehlschlägt, werden einige Ressourcen erstellt und andere nicht. Die State-Datei spiegelt genau wider, was erstellt wurde. Löschen Sie nicht die State-Datei. Führen Sie terraform apply erneut aus, um die verbleibenden Ressourcen zu vervollständigen.

Backend-Konfiguration unterstützt keine Variablen — Der backend-Block unterstützt keine Variableninterpolation. Verwenden Sie -backend-config-Flags oder .tfbackend-Dateien für dynamische Werte:

terraform init -backend-config="bucket=my-state-bucket" \
               -backend-config="key=project/terraform.tfstate"

Workspace-Schlüsselkonflikte — Stellen Sie bei der Verwendung von Workspaces sicher, dass der key-Pfad in Ihrer Backend-Konfiguration workspace-aware ist. Andernfalls teilen (und überschreiben) alle Workspaces dieselbe State-Datei.

Fehlerbehebung

Sperr-Erwerbsfehler

Error: Error acquiring the state lock

Ursache: Ein anderer Prozess hält die Sperre, oder ein vorheriger Prozess ist abgestürzt, ohne sie freizugeben. Lösung: Stellen Sie sicher, dass kein anderes terraform apply oder plan läuft. Wenn die Sperre veraltet ist, verwenden Sie terraform force-unlock <LOCK_ID>.

Zugriff verweigert bei State-Operationen

Error: Failed to load state: AccessDenied: Access Denied

Ursache: Die IAM-Richtlinie gewährt nicht s3:GetObject, s3:PutObject oder dynamodb:PutItem. Lösung: Stellen Sie sicher, dass die ausführende Identität die erforderlichen Berechtigungen sowohl für den S3-Bucket als auch die DynamoDB-Tabelle hat.

State-Datei-Korruption

Symptome: terraform plan zeigt Ressourcen, die neu erstellt werden sollen, obwohl sie bereits existieren, oder Fehler über unbekannte Ressourcentypen. Lösung: Stellen Sie eine frühere State-Version aus der S3-Versionierung wieder her:

# State-Dateiversionen auflisten
aws s3api list-object-versions \
  --bucket my-terraform-state-prod \
  --prefix infrastructure/prod/terraform.tfstate

# Eine bestimmte Version herunterladen
aws s3api get-object \
  --bucket my-terraform-state-prod \
  --key infrastructure/prod/terraform.tfstate \
  --version-id "abc123" \
  restored.tfstate

# Wiederhergestellten State hochladen
terraform state push restored.tfstate

Backend-Initialisierungsschleifen

Error: Backend initialization required, please run "terraform init"

Ursache: Das .terraform-Verzeichnis fehlt oder die Backend-Konfiguration hat sich geändert. Lösung: Führen Sie terraform init aus. Bei einem Backend-Wechsel verwenden Sie terraform init -migrate-state oder terraform init -reconfigure (letzteres verwirft den bestehenden State, nur für Neuanfänge verwenden).

Zusammenfassung

  • Der Terraform State ist die kritische Zuordnung zwischen Ihrem HCL-Code und der realen Infrastruktur — löschen Sie ihn nie, bearbeiten Sie ihn nicht manuell und committen Sie ihn nicht in Git
  • Remote-Backends (S3, Azure Storage, GCS, Terraform Cloud) ermöglichen Teamzusammenarbeit mit gemeinsamer, dauerhafter State-Speicherung
  • State-Sperrung über DynamoDB, Blob-Leases oder integrierte Mechanismen verhindert gleichzeitige Änderungen und Korruption
  • Migrieren Sie den State mit terraform init -migrate-state und manipulieren Sie einzelne Ressourcen mit terraform state mv und terraform state rm
  • Aktivieren Sie die Versionierung auf Ihrem Speicher-Backend, um sich von versehentlicher State-Korruption oder fehlerhaften Applies zu erholen
  • Halten Sie den Zugriff auf sensible Daten streng kontrolliert, da der Terraform State Geheimnisse im Klartext speichert
  • Verwenden Sie Workspaces oder separate Root-Module, um Umgebungen zu isolieren und den Wirkungsradius zu reduzieren

Verwandte Artikel