Terraform, Crossplane und IaC-Strategien
Wann Terraform, wann Crossplane — und wie Platform-Teams IaC kuratieren.
Lernziele
Nach dieser Lektion kannst du erklären, wie Terraform und Crossplane Infrastruktur verwalten und worin sich Run-basierte und Controller-basierte IaC fundamental unterscheiden. Du kannst eine Layering-Strategie skizzieren — welches Tool welche Schicht der Plattform-Infrastruktur besitzt — und im Interview begründen, warum „Terraform oder Crossplane” meist die falsche Frage ist.
Das Problem: Infrastruktur per Ticket skaliert nicht
Ein Stream-Team braucht eine Postgres-Datenbank, einen S3-Bucket und eine Message Queue. Der klassische Weg: Ticket ans Plattform-Team, jemand klickt oder schreibt Terraform, drei Tage später ist die Ressource da. Bei zehn Teams ist das lästig, bei hundert Teams ist das Plattform-Team der Engpass des gesamten Unternehmens.
Die naive Gegenbewegung — jedes Team bekommt Cloud-Zugang und macht selbst — endet in unkontrollierten Kosten, vergessenen Ressourcen und Security-Findings. Was du brauchst, ist Self-Service mit Leitplanken: Entwickler fordern Infrastruktur deklarativ an, das Plattform-Team kuratiert, wie sie entsteht. Infrastructure as Code ist dafür die Grundlage — aber „IaC” ist kein homogenes Konzept. Es gibt zwei grundverschiedene Ausführungsmodelle, und die Wahl prägt deine gesamte Plattform-Architektur.
Terraform: Run-basiert mit explizitem Plan
Terraform beschreibt Infrastruktur in HCL und gleicht sie bei jedem Lauf mit der Realität ab. Drei Dinge musst du sicher erklären können:
State. Terraform merkt sich in einer State-Datei, welche realen Ressourcen zu welchem Code-Block gehören. Ohne State weiß Terraform nicht, ob es eine Datenbank anlegen, ändern oder in Ruhe lassen soll. Der State ist damit ein kritisches Artefakt: Er gehört in ein Remote-Backend mit Locking (z. B. einen Object Store), nie ins Git-Repo — auch weil er Klartext-Werte wie Passwörter enthalten kann.
Plan/Apply. terraform plan zeigt vor jeder Änderung exakt, was passieren würde — anlegen, ändern, zerstören. Dieses Preview ist Terraforms größte Stärke: Ein Plan im Pull Request ist ein reviewbares Änderungsprotokoll, bevor irgendetwas passiert.
Run-basiert. Terraform wird nur aktiv, wenn jemand einen Lauf startet — manuell oder über CI. Zwischen zwei Läufen beobachtet nichts die Infrastruktur. Ändert jemand eine Ressource in der Cloud-Konsole, fällt das erst beim nächsten plan auf. Self-Service mit Terraform heißt deshalb in der Praxis: Pull Request ins Infrastruktur-Repo, Plan im Review, Apply über die Pipeline.
Plattform-Teams kuratieren Terraform über Module: Statt dass jedes Team rohe Cloud-Ressourcen zusammensteckt, gibt es ein versioniertes Modul postgres-instance, das Verschlüsselung, Backups und Tagging fest verdrahtet. Der Modul-Katalog ist die Terraform-Variante eines Golden Path.
Crossplane: Infrastruktur als Kubernetes-API
Crossplane dreht das Modell um: Es läuft als Controller im Cluster und macht Cloud-Ressourcen zu Kubernetes-Objekten. Ein Provider installiert CRDs für z. B. AWS-Ressourcen; legst du so ein Objekt an, sorgt der Controller dafür, dass die echte Ressource entsteht — und reconciled kontinuierlich: Ändert jemand die Ressource an Crossplane vorbei, stellt der Controller den deklarierten Zustand wieder her. Drift wird nicht erst beim nächsten Lauf entdeckt, sondern laufend korrigiert.
Der eigentliche Plattform-Hebel sind Compositions: Du definierst eine eigene, schlanke API — etwa eine CRD PostgresInstance mit drei Feldern (Größe, Region, Backup-Klasse) — und hinterlegst eine Composition, die daraus die echten Cloud-Ressourcen inklusive aller Guardrails baut. Entwickler schreiben dann ein fünfzeiliges YAML und committen es ins GitOps-Repo (Lektion 25); Netzwerk, Verschlüsselung und IAM hat das Plattform-Team in der Composition entschieden. Das ist Self-Service über genau die API-Maschinerie, die deine Teams ohnehin kennen.
Die ehrlichen Kosten: Es gibt kein Plan-Preview — was eine Änderung bewirkt, siehst du erst im Status der Ressourcen. Debugging läuft über Conditions und Events statt über eine lesbare Diff-Ausgabe. Und du betreibst eine zusätzliche kritische Komponente: Fällt der Crossplane-Controller aus, entstehen keine neuen Ressourcen mehr.
Die Layering-Strategie: beide haben einen Platz
In reifen Plattformen ist die Antwort selten ein Entweder-oder, sondern eine Schichtung:
- Foundation Layer (Landing Zone aus Lektion 9, die Cluster selbst, Basis-Networking, IAM-Grundgerüst): Terraform. Diese Schicht ändert sich selten, Änderungen sind riskant — das Plan-Review ist hier Gold wert. Außerdem löst Terraform das Henne-Ei-Problem: Crossplane braucht erst einen Cluster, auf dem es laufen kann (Bootstrap-Reihenfolge aus Lektion 26).
- Application-nahe Ressourcen (Datenbanken, Buckets, Queues pro Team): Crossplane-Claims über GitOps. Hier zählen Self-Service, kontinuierliche Reconciliation und die Kubernetes-native API mehr als ein Plan-Preview.
Alternativen solltest du benennen können: Manche Organisationen bleiben Terraform-only und bauen Self-Service über einen Modul-Katalog plus PR-Automatisierung — weniger neue Technologie, dafür bleibt der PR-Workflow die einzige Schnittstelle. Cloud-spezifische Controller (etwa AWS Controllers for Kubernetes) sind ein Mittelweg ohne Compositions-Schicht. Entscheidend ist in jedem Fall: Module wie Compositions werden versioniert (SemVer) und Breaking Changes bekommen einen Migrationspfad — sonst zerbricht der Self-Service beim ersten Refactoring.
Praxis: beide Ausführungsmodelle anfassen
Erst das Run-Modell mit Terraform, ganz ohne Cloud-Account:
mkdir tf-lab && cd tf-lab
cat > main.tf <<'EOF'
terraform {
required_providers {
local = { source = "hashicorp/local" }
}
}
resource "local_file" "hello" {
filename = "${path.module}/hello.txt"
content = "provisioniert von terraform"
}
EOF
terraform init
terraform plan # Preview: 1 to add
terraform apply -auto-approve
head -n 20 terraform.tfstate # der State: Mapping Code -> Realität
rm hello.txt && terraform plan # Drift wird erst beim Lauf erkannt
Dann das Controller-Modell — Crossplane in einem lokalen kind-Cluster:
kind create cluster --name iac-lab
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane crossplane-stable/crossplane \
--namespace crossplane-system --create-namespace
kubectl get pods -n crossplane-system # ein dauerhaft laufender Controller
kubectl api-resources | grep crossplane # Infrastruktur als API-Typen
Vergleiche bewusst: Terraform tat nur etwas, als du es aufgerufen hast — der gelöschte hello.txt blieb gelöscht, bis du wieder plan ausgeführt hast. Crossplane dagegen ist ein Prozess, der nie aufhört zu beobachten.
Typische Stolperfallen
State im Git-Repo oder ohne Locking: Zwei parallele Applies auf denselben State korrumpieren ihn. Remote-Backend mit Locking ist nicht optional.
Crossplane wie Terraform behandeln: Wer vor dem Merge ein „Plan-Preview” erwartet, wird enttäuscht. Die Absicherung verschiebt sich auf Schema-Validierung, Policies (nächste Lektion) und Staging-Umgebungen.
Doppelte Ownership: Verwaltet Terraform und Crossplane dieselbe Ressource, korrigieren sie sich gegenseitig in einer Endlosschleife. Pro Ressource genau ein Owner — die Layering-Grenze muss dokumentiert sein.
Compositions ohne Versionierung: Eine Composition, die sich unter laufenden Claims ändert, ist ein Breaking Change für alle Teams gleichzeitig. SemVer und Migrationsfenster von Anfang an.
Interview-Vorbereitung
Auf „Terraform oder Crossplane?” antwortest du nicht mit Tool-Präferenz, sondern mit drei Kriterien: Ausführungsmodell (Run mit Plan-Preview vs. kontinuierliche Reconciliation), Konsument (Plattform-Engineers im PR-Workflow vs. Entwickler-Self-Service über eine Kubernetes-API) und Schicht (Foundation vs. application-nahe Ressourcen) — und schließt mit dem Layering-Muster.
Typische Follow-ups:
- „Warum ist der Terraform-State so kritisch?” — Er ist das einzige Mapping zwischen Code und realen Ressourcen, enthält teils Secrets, braucht Locking; Verlust oder Korruption macht die Umgebung faktisch unverwaltbar.
- „Wie erkennt Crossplane Drift?” — Gar nicht als Sonderfall: Der Reconcile-Loop vergleicht permanent Soll und Ist und korrigiert automatisch.
- „Kann man Crossplane-Änderungen vorher prüfen?” — Nur eingeschränkt (Schema-Validierung, Policies, Staging); das fehlende Plan-Preview ehrlich zu benennen wirkt stärker als es wegzureden.
- „Womit startest du auf der grünen Wiese?” — Terraform für Cluster und Landing Zone, Crossplane erst, wenn Self-Service für Teams gebraucht wird.
Zusammenfassung
Terraform ist Run-basiert: explizites Plan-Preview, State als kritisches Artefakt, kuratierbar über versionierte Module — ideal für die Foundation-Schicht. Crossplane ist Controller-basiert: kontinuierliche Reconciliation, eigene Plattform-APIs über Compositions — ideal für Entwickler-Self-Service auf application-naher Infrastruktur. Reife Plattformen schichten beide und ziehen eine klare Ownership-Grenze. Self-Service ohne Kontrolle wäre allerdings fahrlässig — wie du Leitplanken als Code erzwingst, statt sie in Reviews zu erbitten, ist Thema der nächsten Lektion: Policy-as-Code.