TL;DR — Kurzzusammenfassung
Terraform Remote State Backends auf S3, Azure Blob und GCS konfigurieren. State Locking, Migration, Workspaces, Sicherheit und projektübergreifende Referenzen.
Terraform pflegt eine State-Datei — ein JSON-Protokoll jeder verwalteten Ressource — um Ihre HCL-Konfiguration auf echte Infrastruktur abzubilden. Bei Einzelpersonenarbeit reicht eine lokale State-Datei aus. Sobald ein zweiter Ingenieur oder eine CI-Pipeline terraform apply auf dieselbe Infrastruktur ausführt, wird lokaler State zu einem geteilten Risiko ohne Locking, ohne Versionierung und ohne Zugriffssteuerung. Dieser Leitfaden behandelt alle Aspekte der Terraform Remote State Backends: die Wahl des richtigen Anbieters, State-Locking-Konfiguration, Migration vom lokalen State, Manipulation des States mit CLI-Befehlen, Absicherung sensibler Daten und Einrichtung projektübergreifender Referenzen.
Voraussetzungen
- Terraform CLI v1.6 oder neuer lokal installiert
- Ein AWS-Konto mit Berechtigungen zum Erstellen von S3-Buckets und DynamoDB-Tabellen (für AWS-Beispiele)
- Azure CLI authentifiziert gegen ein Abonnement (für Azure-Blob-Beispiele)
- Grundlegende Kenntnisse der Terraform-Ressourcenblöcke und des
terraform apply-Workflows - Git zur Versionsverwaltung Ihrer Terraform-Konfigurationen (niemals
terraform.tfstatecommitten)
Warum Lokaler State für Teams Gefährlich Ist
Das lokale Terraform-Backend schreibt terraform.tfstate in das aktuelle Verzeichnis. Dies erzeugt drei kritische Probleme, sobald mehr als eine Person oder ein Prozess dieselbe Infrastruktur berührt:
Kein Locking. Zwei Ingenieure führen terraform apply gleichzeitig aus. Der zweite Apply liest veralteten State, berechnet einen Plan auf Basis veralteter Daten und überschreibt dann den State des ersten Apply. Vom ersten Apply erstellte Ressourcen werden zu Waisen — sie existieren in der Cloud, sind aber für Terraform unsichtbar.
Kein Teilen. Jeder Ingenieur hat seine eigene State-Kopie auf seinem Laptop. Änderungen einer Person sind für andere unsichtbar, bis State-Dateien manuell ausgetauscht werden.
Versehentliches Löschen. Ein rm -rf im falschen Verzeichnis, ein Festplattenausfall oder ein verlorener Laptop löscht die State-Datei vollständig. Ohne sie weiß Terraform nicht, was es verwaltet, und versucht alle Ressourcen neu zu erstellen.
S3 Backend konfigurieren (AWS)
Das S3-Backend ist die häufigste Wahl für AWS-Teams. Es kombiniert einen S3-Bucket (für dauerhaften Speicher und Versionierung) mit einer DynamoDB-Tabelle (für verteiltes Locking).
Backend-Infrastruktur erstellen
# S3-Bucket für State-Speicherung
aws s3api create-bucket \
--bucket acme-terraform-state \
--region us-east-1
# Versionierung aktivieren für State-Wiederherstellung
aws s3api put-bucket-versioning \
--bucket acme-terraform-state \
--versioning-configuration Status=Enabled
# Öffentlichen Zugriff blockieren
aws s3api put-public-access-block \
--bucket acme-terraform-state \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,\
BlockPublicPolicy=true,RestrictPublicBuckets=true
# DynamoDB-Tabelle für State-Locking
aws dynamodb create-table \
--table-name terraform-state-locks \
--attribute-definitions AttributeName=LockID,AttributeType=S \
--key-schema AttributeName=LockID,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
Backend-Block konfigurieren
terraform {
backend "s3" {
bucket = "acme-terraform-state"
key = "networking/prod/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-state-locks"
encrypt = true
}
}
Der key ist der S3-Objektpfad. Verwenden Sie eine konsistente Namenskonvention — <Projekt>/<Umgebung>/terraform.tfstate — damit alle Teams die State-Dateien der anderen finden können.
Azure Blob Storage Backend konfigurieren
Für Azure-zentrierte Teams verwenden Sie ein Azure Storage Account. Azure Blob Storage bietet natives Locking über Blob-Leases — keine separate Locking-Ressource ist erforderlich.
az group create --name rg-terraform-state --location eastus
az storage account create \
--name acmetfstate2026 \
--resource-group rg-terraform-state \
--sku Standard_LRS \
--encryption-services blob \
--min-tls-version TLS1_2
az storage container create \
--name tfstate \
--account-name acmetfstate2026
terraform {
backend "azurerm" {
resource_group_name = "rg-terraform-state"
storage_account_name = "acmetfstate2026"
container_name = "tfstate"
key = "networking/prod/terraform.tfstate"
}
}
State Locking und Konsistenz
Wenn Terraform einen state-modifizierenden Vorgang startet (plan, apply, destroy), versucht es eine Sperre zu erwerben. Mit dem S3-Backend stellt DynamoDB die Sperre bereit. Jeder gleichzeitige Prozess, der dieselbe Sperre zu erwerben versucht, erhält eine Fehlermeldung mit Informationen darüber, wer sie hält.
So geben Sie eine durch einen abgestürzten Prozess hinterlassene Sperre frei:
terraform force-unlock a3f2b1
Verwenden Sie force-unlock niemals, während eine andere Operation aktiv ist. Nutzen Sie diesen Befehl nur, wenn Sie sicher sind, dass der haltende Prozess beendet ist.
Migration von Lokalem zu Remotem State
Erstmigration
Nachdem Sie einen Backend-Block erstmals zu Ihrer Konfiguration hinzugefügt haben, führen Sie aus:
terraform init -migrate-state
Terraform erkennt das neue Backend, fragt Sie, ob Sie den vorhandenen lokalen State kopieren möchten, und schreibt ihn an den Remote-Speicherort. Ein Backup wird als terraform.tfstate.backup gespeichert.
Wechsel zwischen Remote-Backends
So verschieben Sie State von einem Remote-Backend zu einem anderen (z.B. von S3 zu Terraform Cloud):
- Aktualisieren Sie den Backend-Block auf das neue Ziel
- Führen Sie
terraform init -migrate-stateaus - Bestätigen Sie die Migrationsaufforderung
Terraform State-Befehle
# Alle im State getrackten Ressourcen auflisten
terraform state list
# Vollständige Attribute einer bestimmten Ressource anzeigen
terraform state show aws_instance.web
# Ressource umbenennen (nach HCL-Refaktorierung)
terraform state mv aws_instance.old_name aws_instance.new_name
# Ressource in eine andere State-Datei verschieben
terraform state mv \
-state-out=../other-project/terraform.tfstate \
aws_vpc.main aws_vpc.main
# Ressource aus dem State entfernen ohne sie in der Cloud zu löschen
terraform state rm aws_instance.legacy_server
# State als JSON herunterladen
terraform state pull > current-state.json
# State durch eine modifizierte Datei ersetzen (gefährlich)
terraform state push modified-state.json
State-Datei-Sicherheit
Terraform-State-Dateien enthalten jeden Attributwert jeder Ressource — einschließlich Datenbankpasswörter, private TLS-Schlüssel und API-Tokens. Auch wenn Sie eine Variable oder ein Output als sensitive = true markieren, erscheint der Wert weiterhin im Klartext im State-JSON.
Verschlüsselung im Ruhezustand. Aktivieren Sie Verschlüsselung im Speicher-Backend:
# S3: SSE-KMS mit kundenverwalteter Schlüssel durchsetzen
aws s3api put-bucket-encryption \
--bucket acme-terraform-state \
--server-side-encryption-configuration '{
"Rules": [{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789:key/abc-123"
}
}]
}'
IAM mit minimalem Privileg. Gewähren Sie CI-Pipelines nur die benötigten Berechtigungen für den S3-Bucket und die DynamoDB-Tabelle.
Workspaces zur Umgebungstrennung
Terraform-Workspaces erstellen isolierte State-Dateien innerhalb derselben Backend-Konfiguration:
terraform workspace new dev
terraform workspace new staging
terraform workspace new production
terraform workspace list
terraform workspace select production
terraform apply
Referenzieren Sie den aktuellen Workspace in der Konfiguration, um Ressourcengrößen oder -anzahlen je Umgebung zu variieren:
locals {
env_config = {
dev = { instance_type = "t3.micro", min_size = 1 }
staging = { instance_type = "t3.small", min_size = 2 }
production = { instance_type = "t3.medium", min_size = 3 }
}
}
resource "aws_instance" "web" {
instance_type = local.env_config[terraform.workspace].instance_type
}
Projektübergreifende Referenzen mit terraform_remote_state
Die terraform_remote_state-Datenquelle ermöglicht einem Terraform-Projekt, Outputs aus der State-Datei eines anderen Projekts zu lesen, ohne Ressourcendeklarationen zu duplizieren:
# Das Networking-Projekt exponiert seine VPC-ID
output "vpc_id" {
value = aws_vpc.main.id
}
# Das Anwendungsprojekt liest die VPC-ID aus dem Networking-State
data "terraform_remote_state" "networking" {
backend = "s3"
config = {
bucket = "acme-terraform-state"
key = "networking/prod/terraform.tfstate"
region = "us-east-1"
}
}
resource "aws_instance" "app" {
subnet_id = data.terraform_remote_state.networking.outputs.vpc_id
}
Partielle Backend-Konfiguration für CI/CD
Backend-Blöcke können keine Variablen-Interpolation verwenden. Nutzen Sie partielle Konfiguration mit -backend-config-Flags:
# main.tf — keine Werte angegeben
terraform {
backend "s3" {}
}
# CI-Pipeline übergibt Werte zum init-Zeitpunkt
terraform init \
-backend-config="bucket=acme-terraform-state" \
-backend-config="key=networking/prod/terraform.tfstate" \
-backend-config="region=us-east-1" \
-backend-config="dynamodb_table=terraform-state-locks"
Backend-Vergleich
| Funktion | S3 + DynamoDB | Azure Blob | GCS | Terraform Cloud | Consul |
|---|---|---|---|---|---|
| State Locking | DynamoDB-Tabelle | Nativer Blob-Lease | Nativer Objekt-Lock | Eingebaut | Nativer KV |
| Verschlüsselung | SSE-S3 / SSE-KMS | Azure-verwaltete Schlüssel | Google-verwaltete Schlüssel | AES-256 eingebaut | Manuelles TLS |
| Versionierung | S3-Objektversionierung | Blob-Versionierung | Objektversionierung | Eingebauter Verlauf | Manuelle Snapshots |
| Kosten (geringe Nutzung) | ~1 $/Monat | ~1 $/Monat | ~1 $/Monat | Kostenlos (500 Ressourcen) | Self-hosted-Betrieb |
| Zugriffskontrolle | IAM-Richtlinien | Azure RBAC | GCP IAM | Teams + SSO | ACL-Tokens |
| Einrichtungskomplexität | Mittel (2 Ressourcen) | Mittel (3 Ressourcen) | Niedrig (1 Bucket) | Niedrig (SaaS) | Hoch (Cluster) |
| Am besten für | AWS-native Teams | Azure-native Teams | GCP-native Teams | Multi-Cloud + Richtlinien | On-premises |
Reales Multi-Umgebungs-Szenario
Ihr Team verwaltet 300+ AWS-Ressourcen in Dev, Staging und Produktion. Ingenieure haben terraform.tfstate in Git committet. An einem Mittwochmorgen wenden zwei Ingenieure gleichzeitig Änderungen am Produktions-VPC an — einer fügt ein privates Subnetz hinzu, der andere modifiziert eine Sicherheitsgruppe. Der zweite Apply liest den früheren State, berechnet einen Plan, der das neue Subnetz ignoriert, und überschreibt den State. Das Subnetz existiert in AWS, ist aber für Terraform unsichtbar: eine Geister-Ressource, die bei jedem zukünftigen Plan verwirrende Diffs erzeugt.
Die Zielarchitektur verwendet ein S3-Backend mit DynamoDB-Locking und getrennten Schlüsseln pro Umgebung:
# Initialisierung pro Umgebung mit partieller Konfiguration
terraform init \
-backend-config="bucket=acme-terraform-state" \
-backend-config="key=acme/production/terraform.tfstate" \
-backend-config="region=us-east-1" \
-backend-config="dynamodb_table=terraform-state-locks"
Jede Umgebung hat ihre eigene State-Datei unter einem eigenen Schlüssel. DynamoDB-Locking verhindert gleichzeitige Applies. S3-Versionierung ermöglicht das Zurücksetzen eines korrumpierten States.
Fallstricke und Randfälle
Sensible Daten im State sind immer im Klartext. Auch mit sensitive = true auf Outputs erscheinen Werte im State-JSON. Behandeln Sie die State-Datei wie einen Secrets-Speicher und schränken Sie den Zugriff entsprechend ein.
Backend-Blöcke können keine Variablen oder Locals verwenden. Nur Literalwerte und -backend-config-Flags werden unterstützt. Der Versuch, var.region in einem Backend-Block zu referenzieren, schlägt zur Parse-Zeit fehl.
Workspace-Schlüsselkollisionen. Wenn der Backend-Schlüssel den Workspace-Namen nicht enthält, teilen sich alle Workspaces eine State-Datei.
State-Drift durch externe Änderungen. Ressourcen, die über die AWS-Konsole oder das Azure-Portal geändert wurden, werden im State nicht reflektiert, bis Sie terraform refresh ausführen.
Partielle Apply-Fehler. Schlägt ein Apply auf halbem Weg fehl, spiegelt der State wider, was erfolgreich erstellt wurde. Löschen Sie den State nicht — führen Sie einfach terraform apply erneut aus.
Fehlerbehebung
Sperrerwerb-Fehler
Error: Error acquiring the state lock
Ursache: Ein anderer Prozess hält die Sperre oder ein früherer Prozess ist abgestürzt ohne sie freizugeben.
Lösung: Stellen Sie sicher, dass kein anderer Apply oder Plan aktiv ist. Falls die Sperre veraltet ist, führen Sie terraform force-unlock <LOCK_ID> aus.
Zugriff verweigert bei State-Operationen
Error: Failed to load state: AccessDenied: Access Denied
Ursache: Die ausführende IAM-Identität fehlen s3:GetObject, s3:PutObject oder dynamodb:PutItem.
Lösung: Überprüfen Sie die IAM-Richtlinie der CI-Rolle und fügen Sie die fehlenden Berechtigungen hinzu.
State-Datei-Korruption
Symptome: terraform plan zeigt alle Ressourcen zur Neuerstellung, obwohl sie in der Cloud existieren.
Lösung: Stellen Sie eine frühere State-Version aus der S3-Versionierung wieder her und verwenden Sie terraform state push, um sie anzuwenden.
Zusammenfassung
- Lokaler State ist für Teams unsicher: kein Locking, kein Teilen, und eine Löschung vernichtet das Infrastruktur-Wissen
- S3 + DynamoDB, Azure Blob, GCS und Terraform Cloud bieten dauerhafte, sperrfähige Remote-Backends
- State Locking verhindert gleichzeitige Änderungen und Korruption
- Migration von lokalem zu Remote-State mit
terraform init -migrate-state - Verwenden Sie
terraform state list,show,mvundrm, um State zu inspizieren und zu refaktorieren ohne Applies auszuführen - Behandeln Sie State-Dateien wie Geheimnisse — aktivieren Sie Verschlüsselung im Ruhezustand und schränken Sie IAM-Zugriff ein
- Verwenden Sie Workspaces oder separate Root-Module mit unabhängigen Backends zur Umgebungsisolierung
terraform_remote_stateermöglicht projektübergreifenden Datenaustausch; entkoppeln Sie mit SSM oder Vault für losere Kopplung- Partielle Backend-Konfiguration mit
-backend-confighält Geheimnisse aus der Versionsverwaltung heraus