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.tfstate committen)

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):

  1. Aktualisieren Sie den Backend-Block auf das neue Ziel
  2. Führen Sie terraform init -migrate-state aus
  3. 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

FunktionS3 + DynamoDBAzure BlobGCSTerraform CloudConsul
State LockingDynamoDB-TabelleNativer Blob-LeaseNativer Objekt-LockEingebautNativer KV
VerschlüsselungSSE-S3 / SSE-KMSAzure-verwaltete SchlüsselGoogle-verwaltete SchlüsselAES-256 eingebautManuelles TLS
VersionierungS3-ObjektversionierungBlob-VersionierungObjektversionierungEingebauter VerlaufManuelle Snapshots
Kosten (geringe Nutzung)~1 $/Monat~1 $/Monat~1 $/MonatKostenlos (500 Ressourcen)Self-hosted-Betrieb
ZugriffskontrolleIAM-RichtlinienAzure RBACGCP IAMTeams + SSOACL-Tokens
EinrichtungskomplexitätMittel (2 Ressourcen)Mittel (3 Ressourcen)Niedrig (1 Bucket)Niedrig (SaaS)Hoch (Cluster)
Am besten fürAWS-native TeamsAzure-native TeamsGCP-native TeamsMulti-Cloud + RichtlinienOn-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, mv und rm, 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_state ermöglicht projektübergreifenden Datenaustausch; entkoppeln Sie mit SSM oder Vault für losere Kopplung
  • Partielle Backend-Konfiguration mit -backend-config hält Geheimnisse aus der Versionsverwaltung heraus

Verwandte Artikel