GitOps ~4 Min.

Crossplane Compositions als Platform-API

XRD, Composition und Self-Service ohne Terraform für alle.

von PlatPrep

Ein Entwickler öffnet ein Ticket: “Ich brauche eine PostgreSQL-Datenbank für unseren neuen Service.” In vielen Organisationen startet damit ein mehrstufiger Prozess: Ticket, Freigabe, Infrastruktur-Team erstellt die Ressource manuell, zwei Tage später ist die Datenbank da. Schnell geht das nicht.

Mit Crossplane Compositions lässt sich das anders gestalten.

Die Idee: Das Platform-Team definiert eine CompositeResourceDefinition (XRD) — das ist die API, die Entwickler sehen. Was dahinter liegt, ob RDS, Cloud SQL oder etwas anderes, bleibt unsichtbar. Die XRD legt das Schema fest, und genau hier entsteht ein großer Teil der Developer Experience:

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xpostgresqldatabases.platform.example.org
spec:
  group: platform.example.org
  names:
    kind: XPostgreSQLDatabase
    plural: xpostgresqldatabases
  claimNames:
    kind: PostgreSQLDatabase
    plural: postgresqldatabases
  versions:
    - name: v1alpha1
      served: true
      referenceable: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                size:
                  type: string
                  enum: ["small", "medium", "large"]
                backupEnabled:
                  type: boolean
                  default: true
              required: ["size"]

Das enum ist kein Detail: Es verhindert, dass jemand “xlarge” bestellt, und das default für Backups kodiert eine Organisationsentscheidung direkt in die API. Fehler werden bei kubectl apply abgefangen — nicht zwanzig Minuten später als halb provisionierte Cloud-Ressource. Bewährt hat sich außerdem, die API bewusst klein zu halten: drei T-Shirt-Größen statt durchgereichter Instance-Typen. Jedes Feld, das du heute exponierst, ist morgen ein Kompatibilitätsversprechen.

Die Composition beschreibt dann die Implementierung: Aus einem Claim entstehen Managed Resources — eine RDS-Instance, eine Security Group, ein Subnet-Group-Objekt. Werte aus dem Claim (Region, Größe) werden in die Specs der Cloud-Ressourcen übertragen. Der klassische Patch-and-Transform-Stil stößt dabei schnell an Grenzen; seit Composition Functions GA sind, lässt sich die Logik als Pipeline ausdrücken — inklusive Schleifen und Bedingungen, etwa mit Go-Templating-Functions. Wer schon einmal versucht hat, “lege drei Subnets an, eines pro AZ” in reinen Patches auszudrücken, weiß, warum es Functions gibt.

Für den Entwickler bleibt davon nur: ein PostgreSQLDatabase-Objekt im eigenen Namespace anlegen, ein paar Minuten warten, Connection-Details als Secret bekommen (writeConnectionSecretToRef). Kein Ticket, keine Cloud-Konsole, kein Terraform-Wissen nötig — und weil der Claim eine ganz normale Kubernetes-Ressource ist, fließt er durch denselben GitOps-Workflow wie alles andere.

Die Plattform-Seite: wo die Komplexität wirklich liegt

Ehrlicherweise verschiebt Crossplane die Komplexität, es eliminiert sie nicht. Drei Dinge, die in der Praxis Zeit kosten:

Debugging über mehrere Schichten. Zwischen Claim und Cloud-Ressource liegen Composite Resource, Composition und Managed Resources — jede mit eigenen Status-Conditions. Wenn die Datenbank nicht kommt, heißt die Antwort selten “schau in ein Log”, sondern “verfolge die Kette”. Das CLI-Kommando crossplane beta trace macht genau das und zeigt den Ressourcenbaum mit dem Status jeder Ebene — das Werkzeug, das man am ersten schlechten Tag kennen sollte.

Provider-Footprint. Die großen Cloud-Provider bringen je nach Zuschnitt hunderte CRDs mit. Das belastet den API-Server und jeden Controller, der CRDs cached, spürbar. Deshalb sind die Provider inzwischen in Familien aufgeteilt (etwa provider-aws-rds statt eines Monolithen) — installiere nur, was du brauchst.

Löschsemantik. Crossplane reconciled kontinuierlich: Löscht jemand den Claim, löscht Crossplane die Datenbank. Das ist konsequentes GitOps, aber bei Stateful-Ressourcen brauchst du eine bewusste deletionPolicy und getestete Backups, bevor das erste Team produktiv geht. “Wir haben den Namespace aufgeräumt” sollte nie das Ende einer Produktionsdatenbank sein.

Gegenüber dem Alternativansatz — Terraform-Module hinter einer CI-Pipeline — tauscht man planbare, explizite Applies gegen kontinuierliche Reconciliation und eine echte API mit RBAC. Für Self-Service mit vielen Konsumenten ist das der passendere Baustein; für seltene, große Infrastruktur-Änderungen bleibt Terraform oft das einfachere Werkzeug (mehr dazu unter Terraform Remote State im Team). Viele Plattformen fahren beides.

Ein Betriebsaspekt, der erst beim zweiten Release auffällt: Eine Composition zu ändern wirkt sofort auf alle existierenden Composite Resources, die sie referenzieren — es gibt kein “nur für neue Claims”. Crossplane legt zwar automatisch CompositionRevisions an, sodass sich Composites per Update-Policy an eine Revision pinnen lassen, aber wer das nicht bewusst nutzt, rollt jede Composition-Änderung ungestaffelt über den gesamten Bestand aus. Für eine Platform-API mit echten Konsumenten heißt das: Compositions wie Software-Releases behandeln — Änderungen erst gegen eine Test-XRD in einer Staging-Umgebung fahren, dann gestaffelt promoten.

Backstage oder Port können später eine UI über die Crossplane-API legen — aber die API-Schicht darunter muss zuerst stimmen, und da ist Crossplane heute die ausgereifteste Kubernetes-native Option. Wer die Konzepte von XRD, Composition und Providern systematisch durcharbeiten will, findet sie im Crossplane-Lernpfad.

Mehr zur Platform-API-Strategie im Lernpfad Platform Engineer mit IDP-Modul.