Self-Service Provisioning Patterns
Infrastructure-on-demand: GitOps, Crossplane, Terraform-Module und Approval-Flows.
Lernziele
Nach dieser Lektion kannst du die drei großen Self-Service-Provisioning-Patterns erklären und gegeneinander abgrenzen: Terraform-Module hinter einer Pipeline, Kubernetes-native Provisionierung mit Crossplane und GitOps-PRs als universelles Interface. Du verstehst, warum Approval-Flows der heikelste Designpunkt sind, und kannst für ein gegebenes Szenario begründen, welches Pattern du wählst.
Das Problem: Infrastruktur per Ticket
Ein Entwicklerteam braucht eine PostgreSQL-Datenbank für einen neuen Service. Der klassische Weg: Jira-Ticket ans Infrastruktur-Team, drei Rückfragen zu Größe und Backup-Anforderungen, fünf Tage Wartezeit, dann Zugangsdaten per — hoffentlich nicht — E-Mail. Multipliziere das mit 50 Teams und allem, was Teams sonst brauchen (Buckets, Queues, DNS-Einträge, Repositories), und das Infrastruktur-Team ist ein Ticket-Backoffice, dessen Backlog die Lead Time der gesamten Organisation diktiert.
Die naive Gegenbewegung — allen Teams Cloud-Konsole und Admin-Rechte geben — tauscht das Bottleneck gegen Wildwuchs: unverschlüsselte Buckets, vergessene Instanzen, keine Kostenzuordnung. Self-Service Provisioning ist der Mittelweg: Teams bekommen Infrastruktur on demand, aber durch eine Schnittstelle, die Standards, Policies und Kostenzuordnung erzwingt. Die Frage ist nur: Wie sieht diese Schnittstelle aus?
Pattern 1: Terraform-Module hinter einer Pipeline
Das verbreitetste Pattern, weil es auf vorhandenem IaC-Wissen aufbaut. Das Platform-Team pflegt ein Modul-Repository: postgres, s3-bucket, service-account — jeweils mit eingebauten Defaults (Verschlüsselung an, Backups an, Tags Pflicht). Teams konsumieren die Module in ihrem eigenen Terraform-Code oder über ein dünnes Interface — etwa eine YAML-Datei im Repo, aus der eine Pipeline den Modul-Aufruf generiert:
module "orders_db" {
source = "git::https://git.acme.io/platform/tf-modules//postgres?ref=v3.2.0"
name = "orders"
size = "small" # abstrahiert Instance-Typ, Storage, IOPS
team = "team-orders" # erzwingt Kostenzuordnung
}
Die Pipeline (oft mit einem TACOS wie Atlantis, Terraform Cloud oder Spacelift) führt plan und apply aus, Policy-Checks laufen gegen den Plan.
Stärken: deckt alles ab, was ein Terraform-Provider kann; State und Plan-Diff geben Vorhersagbarkeit; das Modul ist die natürliche Stelle für Standards. Schwächen: Provisionierung ist ein Pipeline-Lauf, keine Reconciliation — Drift zwischen State und Realität fällt erst beim nächsten Plan auf. Und das Interface bleibt HCL-nah: Für Teams ohne Terraform-Erfahrung ist auch ein Modul-Aufruf eine Hürde.
Pattern 2: Crossplane — Infrastruktur als Kubernetes-API
Crossplane dreht den Spieß um: Infrastruktur wird zur Kubernetes-Ressource. Das Platform-Team definiert eine eigene API — eine Composite Resource Definition (XRD) — und hinterlegt in einer Composition, wie sie auf echte Cloud-Ressourcen abgebildet wird (RDS-Instanz, Subnet-Gruppe, Security Group, Secret). Das Team sieht nur die Abstraktion:
apiVersion: platform.acme.io/v1alpha1
kind: PostgreSQLInstance
metadata:
name: orders-db
namespace: team-orders
spec:
size: small
region: eu-central-1
kubectl apply, und der Crossplane-Provider erzeugt die Cloud-Ressourcen — und reconciled sie dauerhaft: Löscht jemand die Security Group in der Konsole, stellt der Controller sie wieder her. Das ist der fundamentale Unterschied zu Pattern 1: Control Loop statt Pipeline-Lauf.
Der zweite Gewinn: Die Plattform-API ist eine echte API mit Schema-Validierung, RBAC und Audit — die Developer Contracts aus Lektion 18 bekommen hier ihre technische Form. Der Preis: Du betreibst Crossplane und seine Provider selbst, Compositions sind deutlich schwerer zu schreiben und zu testen als Terraform-Module, und das Ökosystem an fertigen Bausteinen ist kleiner. Crossplane lohnt sich, wenn Kubernetes ohnehin das Zentrum deiner Plattform ist — nicht als Erstinvestition.
Pattern 3: GitOps-PR als Interface — und die Approval-Frage
Orthogonal zu beiden steht die Frage des Eingangs: Wie äußert ein Team seinen Wunsch? Das robusteste Muster ist der Pull Request gegen ein Git-Repo. Ob dahinter Terraform oder Crossplane-Manifeste liegen, ist sekundär — der PR liefert gratis, was jede Governance verlangt: Review, Audit-Trail, Rollback per Revert. Ein Backstage-Template (Lektion 14) kann das Formular davor sein, das den PR generiert — Portal als Frontend, Git als API.
Damit zum heikelsten Designpunkt: Wer genehmigt? Ein menschliches Approval für jede Datenbank reproduziert das Ticket-Bottleneck mit anderen Mitteln. Die reife Antwort ist gestaffelt:
- Policy statt Mensch für den Normalfall: Was Policy-Checks besteht (richtige Region, Größe im Limit, Tags vollständig — z. B. mit OPA/Conftest gegen den Terraform-Plan oder Kyverno gegen Manifeste), wird automatisch gemergt oder nur vom eigenen Team reviewt.
- Mensch nur für Ausnahmen: Produktions-Datenbank über Größe X, neue Ressourcen-Typen, Policy-Exceptions — hier ist ein explizites Approval des Platform- oder Security-Teams gerechtfertigt, weil es selten ist.
- Budget als Leitplanke statt als Gate: Quotas und Kosten-Alerts pro Team (Lektion 21 vertieft das) erlauben Freiheit im Rahmen, statt jede Einzelentscheidung zu prüfen.
Die Kennzahl, an der du das Design misst: Wie viele Provisionierungen pro Monat brauchen keinen menschlichen Eingriff? Wenn die Antwort „fast keine” ist, hast du Self-Service nur umbenannt.
Praxis: eine Plattform-API mit Crossplane bauen
In einem lokalen kind-Cluster kannst du das XRD/Composition-Muster ohne Cloud-Account üben, indem du als Ziel einfache Kubernetes-Ressourcen komponierst:
kind create cluster --name xp-lab
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm install crossplane crossplane-stable/crossplane \
--namespace crossplane-system --create-namespace
kubectl get pods -n crossplane-system # warten bis Running
Definiere dann eine XRD Database mit einem spec.size-Feld (Enum: small, medium) und eine Composition, die daraus zunächst nur eine ConfigMap mit den abgeleiteten Parametern erzeugt — der Mechanismus (Claim → XR → komponierte Ressourcen) ist identisch zum Cloud-Fall. Beobachte mit kubectl get composite und kubectl describe, wie der Claim durch die Schichten läuft. Wenn du einen Cloud-Account zur Verfügung hast, ersetze die ConfigMap im zweiten Schritt durch echte Provider-Ressourcen. Ziel der Übung: einmal selbst erleben, dass die Abstraktion (was sieht das Team?) und die Implementierung (was entsteht wirklich?) getrennte Artefakte sind.
Typische Stolperfallen
Self-Service ohne Abstraktion: Wer Teams rohe Terraform-Provider oder alle 200 Crossplane-Ressourcentypen freigibt, hat keinen Golden Path, sondern eine Cloud-Konsole in YAML. Die Plattform-API muss Entscheidungen wegnehmen (Instance-Typ, Verschlüsselung, Netzwerk), nicht nur durchreichen.
Day-2 vergessen: Provisionieren ist die leichte Hälfte. Wer ändert die Größe, wer spielt Minor-Upgrades ein, was passiert beim Löschen mit den Daten? Ein Self-Service ohne Update- und Deletion-Pfad produziert verwaiste Ressourcen.
Secrets als Nachgedanke: Die Zugangsdaten der provisionierten Datenbank müssen automatisch in einem Secret-Store landen (External Secrets, Vault), nicht im PR-Kommentar. Das gehört ins Pattern, nicht in die Doku.
Approval-Theater: Ein Pflicht-Review durch ein Team, das 40 PRs pro Tag abnickt, ist kein Sicherheitsgewinn, sondern Latenz plus Alibi. Entweder die Prüfung ist automatisierbar (dann automatisieren) oder sie ist selten (dann ist menschliches Review okay).
Interview-Vorbereitung
Auf „Wie würdest du Self-Service-Provisioning bauen?” antwortest du am stärksten szenariobasiert: Problem (Ticket-Bottleneck vs. Wildwuchs) → Interface-Entscheidung (abstrahierte Plattform-API, eingehend per PR/Portal) → Implementierungs-Wahl mit Begründung (Terraform-Module: breite Abdeckung, Pipeline-Modell; Crossplane: Reconciliation und native K8s-API, höhere Betriebskosten) → Governance (Policy-as-Code für den Normalfall, menschliches Approval nur für Ausnahmen, Quotas als Rahmen).
Wahrscheinliche Follow-ups:
- „Terraform oder Crossplane?” — keine Glaubensfrage: Terraform bei heterogener Infrastruktur und vorhandenem IaC-Know-how, Crossplane bei Kubernetes-zentrischer Plattform und Bedarf an kontinuierlicher Reconciliation; Mischbetrieb ist verbreitet.
- „Wie verhinderst du, dass Self-Service die Cloud-Rechnung explodieren lässt?” — Größen-Enums statt freier Parameter, Quotas pro Team, Tags für Kostenzuordnung erzwungen im Modul/in der Composition, Alerts vor Limits.
- „Was passiert bei Drift?” — Crossplane korrigiert automatisch per Reconciliation; bei Terraform fällt Drift erst beim Plan auf, daher regelmäßige Drift-Detection-Läufe einplanen.
- „Wie kommen die Credentials zum Team?” — nie über den sichtbaren Kanal: Provider schreibt sie in ein Kubernetes-Secret bzw. Vault, die Anwendung konsumiert sie von dort.
Zusammenfassung
Self-Service Provisioning ersetzt das Ticket durch eine Plattform-API mit eingebauten Standards. Terraform-Module hinter einer Pipeline sind der pragmatische Einstieg mit breiter Abdeckung; Crossplane macht Infrastruktur zur reconcilten Kubernetes-Ressource und die Plattform-API zur echten API; der GitOps-PR ist in beiden Welten das robusteste Eingangs-Interface. Über Erfolg entscheidet die Approval-Architektur: Policies prüfen den Normalfall maschinell, Menschen nur die Ausnahme.
Ob das alles den Entwicklern tatsächlich hilft, ist eine empirische Frage — die nächste Lektion zeigt, wie du Developer Experience misst, statt sie zu behaupten.