Veröffentlicht am

Crossplane einrichten: Infrastructure as Code mit Kubernetes

Teilen:
Authors

Kubernetes Crossplane: Infrastructure as Code auf Kubernetes-Ebene

TL;DR

  • Crossplane erweitert die Kubernetes API um Cloud-Ressourcen: S3 Buckets, RDS-Instanzen und Azure VNets werden zu Custom Resources, die per kubectl apply erstellt werden.
  • Compositions buendeln mehrere Managed Resources zu einer wiederverwendbaren Abstraktion. Entwickler bestellen Infrastruktur ueber Claims, ohne die dahinterliegende Komplexitaet zu kennen.
  • Im Vergleich zu Terraform bietet Crossplane native Drift Detection, weil der Kubernetes Reconciliation Loop den Soll-Zustand permanent mit dem Ist-Zustand abgleicht.
  • Die Installation erfolgt per Helm in unter 5 Minuten. Provider fuer AWS, Azure und GCP sind als separate Pakete verfuegbar.
  • In Kombination mit ArgoCD entsteht ein vollstaendiger GitOps-Workflow fuer Infrastruktur und Applikationen aus einer einzigen Pipeline.

Warum Infrastruktur in Kubernetes verwalten?

Die meisten Teams kennen das Setup: Applikationen laufen in Kubernetes, aber die Cloud-Infrastruktur darunter wird mit einem separaten Tool verwaltet -- Terraform, Pulumi oder CloudFormation. Das bedeutet zwei Toolchains, zwei State-Mechanismen, zwei Pipelines und zwei Skill-Sets im Team.

Kubernetes Crossplane loest dieses Problem, indem es Cloud-Ressourcen als Custom Resources abbildet. Alles wird ueber die Kubernetes API verwaltet, mit den gleichen Tools und Prozessen, die Teams bereits fuer ihre Workloads nutzen.

Die konkreten Vorteile:

  • Ein Toolset: kubectl, Helm, Kustomize und ArgoCD fuer alles.
  • Eingebaute Drift Detection: Der Kubernetes Controller gleicht den Soll-Zustand permanent mit dem Ist-Zustand ab. Jemand aendert manuell eine Security Group in AWS? Crossplane stellt den gewuenschten Zustand automatisch wieder her.
  • Native RBAC: Wer welche Infrastruktur bestellen darf, wird ueber Kubernetes RBAC gesteuert.
  • Self-Service: Entwickler bestellen Infrastruktur per Claim, ohne Cloud-Konsolen-Zugriff zu brauchen.

Crossplane Architektur: Die fuenf Kernkonzepte

Providers sind die Schnittstelle zu Cloud-APIs. Der AWS Provider bringt CRDs fuer S3 Buckets, RDS Instances, IAM Roles, VPCs und hunderte weitere Ressourcen mit. Offizielle Provider gibt es fuer AWS, Azure, GCP und dutzende weitere.

Managed Resources sind die 1:1-Abbildung einer Cloud-Ressource in Kubernetes:

apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
  name: my-app-data
spec:
  forProvider:
    region: eu-central-1
    tags:
      Environment: production
      Team: backend
  providerConfigRef:
    name: aws-provider-config

Composite Resource Definitions (XRDs) definieren eine neue API-Abstraktion -- ein Schema fuer euren internen Cloud-Service-Katalog.

Compositions definieren, welche Managed Resources erstellt werden, wenn jemand eine Composite Resource anlegt. Eine Composition fuer eine "Datenbank" koennte eine RDS-Instanz, eine Security Group und einen IAM-User buendeln.

Claims (XRCs) sind die Schnittstelle fuer Entwickler. Sie geben nur die Parameter an, die fuer den konkreten Use Case relevant sind.

Crossplane vs. Terraform: Technischer Vergleich

EigenschaftCrossplaneTerraform
KonfigurationsspracheYAML (Kubernetes CRDs)HCL
State ManagementKubernetes etcd (kein externer State)State-File (S3, Terraform Cloud)
Drift DetectionKontinuierlich (Reconciliation Loop)Nur bei terraform plan
AusfuehrungsmodellPermanent laufender ControllerCLI-basiert (Plan/Apply)
RBACKubernetes-native RBACTerraform Cloud / Wrapper noetig
GitOps-IntegrationNativ (ArgoCD, Flux)Ueber Wrapper (Atlantis, Spacelift)
EcosystemWachsend, aber kleinerRiesig (Tausende Module)
RollbackKubernetes-native (vorherige Version anwenden)Manuell

Crossplane vs Terraform ist keine Entweder-oder-Entscheidung. In der Praxis existieren beide Tools haeufig parallel: Terraform fuer den initialen Cluster-Aufbau, Crossplane fuer alles, was danach kommt.

Mehr zu GitOps-Workflows unter ArgoCD GitOps fuer Enterprise Kubernetes.

Installation und Provider-Setup

# Helm Repository hinzufuegen und Crossplane installieren
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update

helm install crossplane \
  crossplane-stable/crossplane \
  --namespace crossplane-system \
  --create-namespace \
  --set args='{"--enable-usages"}' \
  --wait

# Installation pruefen
kubectl get pods -n crossplane-system
# NAME                                      READY   STATUS    AGE
# crossplane-7c88c45d8f-xxxxx              1/1     Running   45s
# crossplane-rbac-manager-8b9d4c6f-xxxxx   1/1     Running   45s

AWS Provider installieren:

apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-s3
spec:
  package: xpkg.upbound.io/upbound/provider-aws-s3:v1.16.0

Provider-Credentials konfigurieren (fuer Produktion IRSA empfohlen):

kubectl create secret generic aws-credentials \
  -n crossplane-system \
  --from-file=creds=./aws-credentials.txt
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
  name: aws-provider-config
spec:
  credentials:
    source: Secret
    secretRef:
      namespace: crossplane-system
      name: aws-credentials
      key: creds

Wer die Grundlagen von Secrets-Management vertiefen will: Kubernetes Secrets Management mit Vault.

Praxis: Composition fuer S3 Bucket mit IAM Policy

Wir bauen eine Crossplane Composition, die einen S3 Bucket zusammen mit einer IAM Policy erstellt. Entwickler bestellen beides ueber einen einzigen Claim.

XRD definieren

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xobjectstorages.platform.example.com
spec:
  group: platform.example.com
  names:
    kind: XObjectStorage
    plural: xobjectstorages
  claimNames:
    kind: ObjectStorage
    plural: objectstorages
  versions:
    - name: v1alpha1
      served: true
      referenceable: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                parameters:
                  type: object
                  properties:
                    region:
                      type: string
                      default: eu-central-1
                    versioning:
                      type: boolean
                      default: true
                    environment:
                      type: string
                      enum: ["dev", "staging", "production"]
                  required:
                    - environment

Composition erstellen

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: objectstorage-aws
  labels:
    provider: aws
spec:
  compositeTypeRef:
    apiVersion: platform.example.com/v1alpha1
    kind: XObjectStorage
  resources:
    - name: s3-bucket
      base:
        apiVersion: s3.aws.upbound.io/v1beta1
        kind: Bucket
        spec:
          forProvider:
            region: eu-central-1
            tags:
              ManagedBy: crossplane
          providerConfigRef:
            name: aws-provider-config
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.parameters.region
          toFieldPath: spec.forProvider.region
        - type: FromCompositeFieldPath
          fromFieldPath: spec.parameters.environment
          toFieldPath: spec.forProvider.tags.Environment
    - name: bucket-versioning
      base:
        apiVersion: s3.aws.upbound.io/v1beta1
        kind: BucketVersioning
        spec:
          forProvider:
            bucketSelector:
              matchControllerRef: true
            versioningConfiguration:
              - status: Enabled
          providerConfigRef:
            name: aws-provider-config

Claim: Developer Self-Service

Das ist alles, was ein Entwickler schreiben muss:

apiVersion: platform.example.com/v1alpha1
kind: ObjectStorage
metadata:
  name: user-uploads
  namespace: team-backend
spec:
  parameters:
    region: eu-central-1
    versioning: true
    environment: production
  compositionSelector:
    matchLabels:
      provider: aws
kubectl apply -f object-storage-claim.yaml

kubectl get objectstorage -n team-backend
# NAME           SYNCED   READY   CONNECTION-SECRET   AGE
# user-uploads   True     True                        3m

kubectl get managed
# NAME                                              SYNCED   READY   AGE
# bucket.s3.aws.upbound.io/user-uploads-xxxxx       True     True    3m
# bucketversioning.s3.aws.upbound.io/user-uploads    True     True    3m

GitOps-Integration mit ArgoCD

ArgoCD ueberwacht ein Git Repository und synchronisiert Aenderungen in den Cluster. Crossplane nimmt diese Aenderungen und provisioniert die Cloud-Infrastruktur.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: infrastructure
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/infrastructure.git
    targetRevision: main
    path: crossplane/production
  destination:
    server: https://kubernetes.default.svc
    namespace: crossplane-system
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Der Workflow: Entwickler erstellt PR mit Claim, Platform-Team reviewt, Merge nach main, ArgoCD synchronisiert, Crossplane erstellt Cloud-Ressourcen. Kein manuelles terraform apply noetig.

Fuer den vollstaendigen ArgoCD-Setup: ArgoCD GitOps Kubernetes Tutorial.

Monitoring und Troubleshooting

# Alle Managed Resources mit Status
kubectl get managed -o wide

# Details und Events einer Ressource
kubectl describe bucket user-uploads-xxxxx

# Provider-Logs bei Fehlern
kubectl logs -n crossplane-system \
  -l pkg.crossplane.io/revision=provider-aws-s3 \
  --tail=100
FehlerUrsacheLoesung
SYNCED=FalseKein Cloud-API-ZugriffProviderConfig und Credentials pruefen
READY=False, SYNCED=TrueRessource wird noch erstelltWarten oder Cloud-Konsole pruefen
Composition not foundFalsches LabelLabels in Composition und Claim abgleichen

Best Practices

  1. Granulare Provider nutzen: provider-aws-s3 statt des monolithischen provider-aws. Spart Speicher und reduziert CRD-Anzahl.
  2. Compositions versionieren: Aenderungen am XRD-Schema ueber neue Versionen (v1alpha1, v1beta1, v1) abbilden.
  3. ProviderConfig pro Umgebung: Separate Configs fuer Dev, Staging und Production mit unterschiedlichen IAM-Rollen.
  4. Usage-Feature aktivieren: --enable-usages verhindert das Loeschen referenzierter Ressourcen.
  5. Composition Functions: Ab Crossplane 1.14 komplexe Logik in Go oder Python statt reinem Patching.

Mehr zur Kubernetes-Plattform-Strategie unter Kubernetes Platform Engineering.

Verwandte Artikel


Wenn ihr Crossplane in eurem Cluster einfuehren wollt und Unterstuetzung bei Architektur, Composition-Design oder Migration von Terraform braucht, meldet euch unter /kontakt -- wir helfen von der Konzeptphase bis zum produktiven Betrieb.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen