Jede Cloud-Ressource, die Sie je durch Klicken in einer Web-Konsole erzeugt haben (eine VM, ein Load Balancer, ein DNS-Eintrag), lÀsst sich auch in einer Textdatei beschreiben und mit einem einzigen Befehl erstellen. Die Datei liegt in git, durchlÀuft eine Pull Request und reproduziert dasselbe Setup auf einem zweiten Account, ohne dass sich jemand merken muss, welche neun Einstellungen er von Hand geÀndert hat. Genau das macht Terraform.

Was Terraform tatsÀchlich tut

Terraform ist ein Open-Source-Tool von HashiCorp, das Infrastruktur als Konfigurationsdateien in HCL (HashiCorp Configuration Language) beschreibt und diese dann gegen die API eines Cloud-Providers anwendet. Sie schreiben einen resource-Block, der den S3-Bucket, die EC2-Instanz oder den Cloudflare-DNS-Eintrag beschreibt, den Sie wollen, fĂŒhren terraform apply aus, und Terraform ermittelt die nötigen API-Aufrufe, damit diese Ressource existiert — und verfolgt sie danach weiter, sodass ein zweites apply nur Ă€ndert, was sich tatsĂ€chlich geĂ€ndert hat.

Das Modell ist deklarativ, nicht prozedural: Sie beschreiben den Endzustand, nicht die Schritte dorthin. Sie schreiben nicht “erstelle einen Bucket, setze dann seine Policy, aktiviere dann Versioning”. Sie schreiben, wie der Bucket aussehen soll, und Terraform ermittelt die Reihenfolge der Operationen, einschließlich dessen, was zuerst existieren muss, wenn eine Ressource von einer anderen abhĂ€ngt.

Terraform selbst weiß nichts ĂŒber AWS, Azure oder Cloudflare. Dieses Wissen steckt in Providern: Plugins, die HCL-Resource-Blöcke in Aufrufe gegen eine bestimmte API ĂŒbersetzen. Die Terraform Registry listet Tausende davon, offizielle und von der Community gepflegte, die alles abdecken, von den drei großen Clouds bis zu GitHub-Repository-Einstellungen und Datadog-Monitoren. Derselbe Mechanismus erstellt einen verwalteten Kubernetes-Cluster (google_container_cluster, aws_eks_cluster) oder einen einzelnen DNS-Eintrag vor einem CDN. Hat ein Dienst eine API, hat mit ziemlicher Sicherheit schon jemand einen Provider dafĂŒr geschrieben.

Wie terraform plan und apply funktionieren

Ein minimales Arbeitsverzeichnis hat mindestens zwei Dateien.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# terraform.tf — welche Provider diese Konfiguration braucht
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  required_version = ">= 1.5"
}

provider "aws" {
  region = "eu-west-1"
}
1
2
3
4
5
6
7
8
9
# main.tf — die eigentliche Ressource
resource "aws_s3_bucket" "reports" {
  bucket = "acme-monthly-reports"

  tags = {
    Environment = "production"
    ManagedBy   = "terraform"
  }
}

Vier Befehle decken den tÀglichen Workflow ab:

1
2
3
4
terraform init     # lÀdt das aws-Provider-Plugin, richtet das Backend ein
terraform plan     # zeigt, was sich Ă€ndern wĂŒrde, ohne etwas anzufassen
terraform apply    # fragt nach BestÀtigung, macht dann die API-Aufrufe
terraform destroy  # entfernt alles, was diese Konfiguration verwaltet

terraform init liest required_providers und lĂ€dt die passenden Plugin-Binaries nach .terraform/. Sie fĂŒhren es einmal pro Verzeichnis aus, und erneut jedes Mal, wenn Sie einen Provider oder ein Modul hinzufĂŒgen.

terraform plan ist der Befehl, den Sie tatsĂ€chlich am hĂ€ufigsten ausfĂŒhren werden. Er vergleicht Ihre .tf-Dateien, den gespeicherten State und die reale Infrastruktur, wie sie die API des Providers meldet, und gibt dann einen Diff aus: zu erstellende (+), zu Ă€ndernde (~) oder zu löschende (-) Ressourcen. Es passiert noch nichts. Genau das macht es sicher, Terraform auf Produktion zu richten — Sie lesen den Plan, bevor irgendetwas angefasst wird.

terraform apply fĂŒhrt den Plan erneut aus, zeigt ihn wieder an und wartet, bis Sie yes eingeben, bevor die Provider-APIs in der richtigen AbhĂ€ngigkeitsreihenfolge aufgerufen werden. In CI ĂŒbergeben Sie -auto-approve oder, besser, wenden eine bereits geprĂŒfte Plan-Datei an: terraform apply tfplan. Dieselbe Pipeline, die bei jedem Merge Docker-Image mit GitHub Actions bauen und veröffentlichen ausfĂŒhrt, kann terraform plan auf einer Pull Request laufen lassen und terraform apply, sobald diese in main gemergt ist.

WofĂŒr die State-Datei da ist

Nach dem ersten apply schreibt Terraform terraform.tfstate — eine JSON-Datei, die jede Ressource Ihrer Konfiguration dem realen Objekt zuordnet, das sie erzeugt hat, samt ID. Das ist keine optionale Buchhaltung. So weiß plan, was bereits existiert, ohne bei jedem Lauf Ihren gesamten AWS-Account neu zu scannen, und so verbindet Terraform aws_s3_bucket.reports in Ihrem Code mit dem Bucket acme-monthly-reports-a8f3 in der RealitĂ€t.

Daraus ergeben sich zwei direkte Konsequenzen.

Der State kann Secrets enthalten. Ein als Ressourcen-Argument gesetztes Datenbankpasswort landet im Klartext in der State-Datei, weil Terraform die vollstÀndigen Ressourcenattribute braucht, um Drift zu erkennen. Committen Sie terraform.tfstate niemals nach git.

Der State muss geteilt und gesperrt werden. StandardmĂ€ĂŸig ist es eine lokale Datei, die allein funktioniert und in dem Moment kaputtgeht, in dem eine zweite Person apply von ihrem eigenen Laptop ausfĂŒhrt: jetzt gibt es zwei Wahrheitsquellen. Die Lösung ist ein Remote-Backend: Der State liegt in S3, Azure Blob, GCS oder Terraform Cloud, mit Locking, das verhindert, dass zwei apply-LĂ€ufe gegeneinander laufen.

1
2
3
4
5
6
7
8
9
terraform {
  backend "s3" {
    bucket       = "acme-terraform-state"
    key          = "reports/terraform.tfstate"
    region       = "eu-west-1"
    use_lockfile = true
    encrypt      = true
  }
}

use_lockfile ist das native Locking des S3-Backends, seit Terraform 1.11 allgemein verfĂŒgbar — es schreibt eine Lock-Datei direkt in den Bucket, sodass auf aktuellen Versionen keine separate DynamoDB-Tabelle fĂŒrs Locking mehr nötig ist.

Sobald das Team auf dasselbe Backend zeigt, spiegelt der plan jedes Einzelnen das letzte apply aller anderen wider.

Wie sich eine Konfiguration mit Variablen und Modulen wiederverwenden lÀsst

eu-west-1 und einen Bucket-Namen fest zu verdrahten funktioniert fĂŒr ein FĂŒnf-Zeilen-Beispiel, nicht fĂŒr eine echte Umgebung. Terraform trennt die Form der Infrastruktur von den Werten, die sich je Umgebung Ă€ndern.

1
2
3
4
5
6
7
8
9
# variables.tf
variable "environment" {
  type    = string
  default = "staging"
}

variable "bucket_name" {
  type = string
}
1
2
3
4
5
6
7
8
# main.tf, mit Referenz auf die Variable
resource "aws_s3_bucket" "reports" {
  bucket = var.bucket_name

  tags = {
    Environment = var.environment
  }
}
1
terraform apply -var="bucket_name=acme-prod-reports" -var="environment=production"

Oder Sie legen die Werte in einer terraform.tfvars-Datei ab, damit Sie die Flags nicht bei jedem Lauf neu eintippen. outputs.tf geht den umgekehrten Weg. Es macht einen von Terraform berechneten Wert sichtbar, etwa die öffentliche IP einer Instanz oder eine generierte ARN, damit ein anderes Tool oder eine andere Terraform-Konfiguration ihn weiterverwenden kann:

1
2
3
output "bucket_arn" {
  value = aws_s3_bucket.reports.arn
}

Wiederholt sich eine Gruppe von Ressourcen projektĂŒbergreifend (ein Standard-VPC, ein Standard-Web-App-Stack), kapseln Sie sie in ein Modul: ein Verzeichnis mit .tf-Dateien, referenziert ĂŒber ein source-Argument, das Inputs entgegennimmt und Outputs zurĂŒckgibt wie eine Funktion. Die meisten Teams landen bei einer Handvoll interner Module und vielen schlanken Konfigurationen, die sie mit unterschiedlichen Variablen aufrufen.

Wann Terraform das falsche Werkzeug ist

Terraform stellt Ressourcen bereit; es konfiguriert nicht, was darauf lĂ€uft. Es erstellt eine EC2-Instanz, aber Pakete installieren, Benutzer verwalten und die Konfiguration auf dieser Instanz synchron halten ist eine andere Aufgabe — traditionell die von Ansible, einem Cloud-Init-Skript oder einem Setup, bei dem die Instanz beim Start ein Container-Image zieht und ausfĂŒhrt. Die Anwendungskonfiguration durch Terraform laufen zu lassen ist die falsche Richtung. Das VPC durch Ansible zu erstellen ist die andere falsche Richtung. Die meisten echten Setups nutzen beides, und Terraform reicht die IP der Instanz direkt ĂŒber einen Output an das Ansible-Inventory weiter.

FĂŒr einen Bucket, den Sie in einer Stunde wieder löschen, oder eine wegwerfbare Test-VM, kosten die State-Datei und der Umweg ĂŒber plan und apply mehr, als sie einsparen. Die AWS-CLI oder die Konsole sind schneller fĂŒr etwas, das Sie weder behalten noch reproduzieren wollen.

Terraform, OpenTofu und Pulumi im Vergleich

Terraform ist nicht mehr das einzige Tool, das HCL liest. HashiCorp hat es 2023 von der Open-Source-Lizenz MPL auf die Business Source License umgestellt, und die Linux Foundation pflegt inzwischen OpenTofu, einen Fork, der die MPL-Lizenz behalten hat und mit Terraforms HCL-Syntax und State-Format kompatibel geblieben ist. SpÀter zu wechseln ist eine KonfigurationsÀnderung, keine Neuschreibung.

Pulumi geht den umgekehrten Weg: Statt HCL schreiben Sie die Infrastruktur in TypeScript, Python oder Go. Das zĂ€hlt, wenn Ihr Team echte Kontrollstrukturen und Unit-Tests ĂŒber die Infrastrukturlogik will statt der engeren Ausdrucksmöglichkeiten von HCL.

Wie Sie Terraform ohne Cloud-Account ausprobieren

Terraforms Sicherheitsnetz ist plan, und Sie können den gesamten Zyklus kostenlos durchspielen, bevor Sie es auf etwas Kostenpflichtiges richten. Die Provider random und local brauchen ĂŒberhaupt keine Cloud-Credentials.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
terraform {
  required_providers {
    random = {
      source  = "hashicorp/random"
      version = "~> 3.0"
    }
  }
}

resource "random_pet" "name" {
  length = 2
}

output "generated_name" {
  value = random_pet.name.id
}

Sie fĂŒhren terraform init und terraform apply in einem leeren Verzeichnis aus und erhalten eine echte State-Datei und eine echte verwaltete Ressource, ohne dass es etwas kostet. Machen Sie das einmal, lesen Sie die Plan-Ausgabe Zeile fĂŒr Zeile, bis die Symbole +, ~ und - etwas fĂŒr Sie bedeuten, und richten Sie dieselben vier Befehle dann auf einen Provider, der stundenweise abrechnet.

Verwandte Artikel