Veröffentlicht am

Kubernetes CI/CD mit GitOps: Argo CD und Tekton einrichten

Teilen:
Authors

Kubernetes CI/CD im Enterprise-Einsatz: GitOps, Argo CD und skalierbare Pipelines

TL;DR

  • GitOps trennt CI (Build, Test, Push) sauber von CD (Cluster-Sync). Git ist die Single Source of Truth fuer den Cluster-Zustand
  • Argo CD synchronisiert den Cluster deklarativ mit dem Git-Repository und bietet eingebaute Rollbacks, Health Checks und Multi-Cluster-Support
  • Tekton laeuft Kubernetes-nativ als Pipeline-CRD -- jeder Step ist ein Container, Pipelines sind voll portabel zwischen Clustern
  • Image-Promotions ueber Git-Commits (nicht Pipeline-Pushes) machen Deployments auditierbar und reproduzierbar
  • Canary Deployments mit Argo Rollouts reduzieren das Blast Radius bei fehlerhaften Releases auf unter 5% des Traffics

Warum GitOps die bessere Architektur ist

Klassische CI/CD-Pipelines haben ein strukturelles Problem: Die Pipeline hat Schreibzugriff auf den Cluster. Das bedeutet, dass jeder CI-Server -- Jenkins, GitLab Runner, GitHub Actions -- Credentials fuer kubectl apply braucht. Bei mehreren Clustern und Teams wird das schnell ein Sicherheitsrisiko.

GitOps dreht den Kontrollfluss um. Statt dass die Pipeline in den Cluster pusht, laeuft ein Controller im Cluster (Argo CD oder Flux), der das Git-Repository ueberwacht und den Cluster-Zustand darauf synchronisiert. Die Pipeline hat nur noch Schreibzugriff auf die Container Registry und das Git-Repo -- nicht auf den Cluster selbst.

Das hat drei konkrete Vorteile. Erstens: Kein Cluster-Zugriff fuer CI-Systeme noetig. Zweitens: Jeder Cluster-Zustand ist in Git nachvollziehbar. Drittens: Drift Detection -- wenn jemand manuell per kubectl etwas aendert, stellt Argo CD den gewuenschten Zustand automatisch wieder her.

Architektur: CI und CD sauber trennen

Die Architektur besteht aus zwei unabhaengigen Loops.

CI Loop (Build-Seite):

  1. Entwickler pusht Code in das Application-Repository
  2. CI-System (Tekton, GitHub Actions, GitLab CI) baut das Image
  3. Image wird in die Container Registry gepusht
  4. CI aktualisiert den Image-Tag im Config-Repository (per Git-Commit)

CD Loop (Deployment-Seite):

  1. Argo CD beobachtet das Config-Repository
  2. Bei einem neuen Commit vergleicht Argo CD den gewuenschten Zustand mit dem Cluster
  3. Differenzen werden automatisch (oder nach manueller Freigabe) angewendet
  4. Health Checks verifizieren das erfolgreiche Deployment

Die beiden Repositories -- Application Code und Kubernetes Config -- sind bewusst getrennt. Ein Config-Aenderung (z.B. Resource Limits anpassen) erfordert keinen neuen Image-Build. Ein neues Image-Release aendert nur den Tag im Config-Repo.

Tekton: Kubernetes-native CI-Pipelines

Tekton definiert Pipelines als Kubernetes Custom Resources. Jeder Task-Step laeuft in einem eigenen Container. Das macht Pipelines portabel -- sie laufen auf jedem Kubernetes-Cluster identisch.

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: build-and-push
spec:
  params:
    - name: git-url
      type: string
    - name: image-name
      type: string
    - name: image-tag
      type: string
  workspaces:
    - name: shared-workspace
    - name: docker-credentials
  tasks:
    - name: clone
      taskRef:
        name: git-clone
      workspaces:
        - name: output
          workspace: shared-workspace
      params:
        - name: url
          value: $(params.git-url)

    - name: run-tests
      runAfter: ["clone"]
      taskRef:
        name: golang-test
      workspaces:
        - name: source
          workspace: shared-workspace

    - name: build-push
      runAfter: ["run-tests"]
      taskRef:
        name: kaniko
      workspaces:
        - name: source
          workspace: shared-workspace
        - name: dockerconfig
          workspace: docker-credentials
      params:
        - name: IMAGE
          value: "$(params.image-name):$(params.image-tag)"

    - name: update-manifests
      runAfter: ["build-push"]
      taskRef:
        name: git-update-image-tag
      params:
        - name: image-tag
          value: $(params.image-tag)
        - name: config-repo
          value: "git@github.com:org/k8s-config.git"
        - name: file-path
          value: "apps/api-gateway/deployment.yaml"

Der letzte Task (update-manifests) committet den neuen Image-Tag ins Config-Repository. Ab hier uebernimmt Argo CD.

Argo CD: Deklaratives Continuous Delivery

Argo CD laeuft als Controller im Cluster und synchronisiert Kubernetes-Ressourcen mit dem gewuenschten Zustand im Git-Repository.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: api-gateway
  namespace: argocd
spec:
  project: production
  source:
    repoURL: git@github.com:org/k8s-config.git
    targetRevision: main
    path: apps/api-gateway/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
    retry:
      limit: 3
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 1m
  ignoreDifferences:
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas  # HPA managed

Wichtige Einstellungen in dieser Spec:

  • selfHeal: true -- Manuelle kubectl-Aenderungen werden automatisch revertiert
  • prune: true -- Ressourcen, die aus Git geloescht werden, werden auch im Cluster geloescht
  • ignoreDifferences fuer Felder, die von anderen Controllern (HPA, VPA) verwaltet werden

Multi-Cluster mit ApplicationSets

Fuer Enterprise-Setups mit mehreren Clustern (Dev, Staging, Prod) bietet Argo CD ApplicationSets:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: api-gateway
  namespace: argocd
spec:
  generators:
    - list:
        elements:
          - cluster: dev
            url: https://dev-cluster.internal:6443
            revision: develop
          - cluster: staging
            url: https://staging-cluster.internal:6443
            revision: release/current
          - cluster: production
            url: https://prod-cluster.internal:6443
            revision: main
  template:
    metadata:
      name: 'api-gateway-{{cluster}}'
    spec:
      project: '{{cluster}}'
      source:
        repoURL: git@github.com:org/k8s-config.git
        targetRevision: '{{revision}}'
        path: 'apps/api-gateway/overlays/{{cluster}}'
      destination:
        server: '{{url}}'
        namespace: production

So wird dieselbe Anwendung ueber alle Cluster hinweg konsistent deployed -- mit umgebungsspezifischen Overlays und Branch-Mapping.

Deployment-Strategien: Rolling, Blue-Green, Canary

Die Wahl der Deployment-Strategie haengt vom Risikoprofil der Anwendung ab.

StrategieDowntimeRollback-ZeitRessourcen-OverheadEmpfehlung
Rolling UpdateKeineMinuten (ReplicaSet)Minimal (+25% waehrend Update)Standard fuer die meisten Services
Blue-GreenKeineSekunden (Service Switch)2x (doppelte Infrastruktur)Datenbank-Migrationen, kritische APIs
CanaryKeineSekunden (Traffic Shift)Minimal (+1 Replica)User-facing Services mit hohem Traffic

Canary Deployment mit Argo Rollouts

Argo Rollouts erweitert Kubernetes Deployments um progressive Delivery. Statt alle Pods gleichzeitig zu aktualisieren, wird Traffic schrittweise auf die neue Version verschoben.

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: api-gateway
  namespace: production
spec:
  replicas: 10
  strategy:
    canary:
      canaryService: api-gateway-canary
      stableService: api-gateway-stable
      trafficRouting:
        istio:
          virtualService:
            name: api-gateway-vsvc
            routes:
              - primary
      steps:
        - setWeight: 5
        - pause: {duration: 5m}
        - setWeight: 20
        - pause: {duration: 10m}
        - setWeight: 50
        - pause: {duration: 10m}
        - setWeight: 100
      analysis:
        templates:
          - templateName: success-rate
        startingStep: 1
        args:
          - name: service-name
            value: api-gateway-canary
  selector:
    matchLabels:
      app: api-gateway
  template:
    metadata:
      labels:
        app: api-gateway
    spec:
      containers:
        - name: api-gateway
          image: registry.internal/api-gateway:2.5.0
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: 200m
              memory: 256Mi
            limits:
              cpu: 500m
              memory: 512Mi

Der Ablauf: Zuerst bekommen 5% des Traffics die neue Version. Nach 5 Minuten wird automatisch die Error-Rate geprueft (Analysis Template). Ist sie unter dem Schwellwert, steigt der Traffic auf 20%, dann 50%, dann 100%. Bei erhoehter Error-Rate wird automatisch auf die stabile Version zurueckgerollt.

Security in der Pipeline

Drei Massnahmen sind fuer Enterprise-Pipelines nicht verhandelbar.

Image Scanning: Jedes Image wird vor dem Push in die Registry auf bekannte CVEs geprueft. Trivy ist der De-facto-Standard:

# In der CI-Pipeline nach dem Build
trivy image --severity HIGH,CRITICAL --exit-code 1 \
  registry.internal/api-gateway:${IMAGE_TAG}

# Optional: SBOM generieren fuer Supply Chain Compliance
trivy image --format spdx-json --output sbom.json \
  registry.internal/api-gateway:${IMAGE_TAG}

Signed Images: Cosign signiert Images kryptografisch. Admission Controller im Cluster (z.B. Kyverno) koennen unsignierte Images ablehnen.

Least Privilege fuer Service Accounts: CI-Service-Accounts bekommen nur Schreibzugriff auf die Registry und das Config-Repo. Kein cluster-admin, kein kubectl apply. Der einzige Aktor, der den Cluster veraendert, ist der Argo CD Controller.

DORA-Metriken: Erfolg messbar machen

Die vier DORA-Metriken sind der etablierte Standard, um CI/CD-Performance zu bewerten:

MetrikEliteHighMediumAngestrebter Zielwert
Deployment FrequencyMehrmals taeglichTaeglich bis woechentlichWoechentlich bis monatlichTaeglich
Lead Time for ChangesUnter 1 Stunde1 Tag bis 1 Woche1 Woche bis 1 MonatUnter 4 Stunden
Change Failure Rate0-5%5-10%10-15%Unter 5%
Mean Time to RecoveryUnter 1 StundeUnter 1 TagUnter 1 WocheUnter 30 Minuten

Diese Metriken lassen sich direkt aus den Pipeline-Logs und dem Git-Verlauf ableiten. Tools wie Backstage oder Apache DevLake koennen sie automatisch aggregieren.

Typische Fehler bei Enterprise-CI/CD

Monolithisches Config-Repo. Wenn alle Teams in ein einziges Config-Repo committen, blockieren sich Pull Requests gegenseitig. Loesung: Ein Repo pro Team oder Applikationsgruppe, verbunden ueber Argo CD ApplicationSets.

Keine Trennung von CI und CD. Wenn die CI-Pipeline direkt kubectl apply ausfuehrt, verliert man Auditierbarkeit und Drift Detection. Die Pipeline sollte nie direkten Cluster-Zugriff haben.

Fehlende Promotion-Strategie. Ohne klare Regeln, wie ein Image von Dev nach Staging nach Prod wandert, entstehen Ad-hoc-Prozesse. Loesung: Branch- oder Directory-basierte Promotions im Config-Repo mit Reviews als Gates.

Kein Rollback-Test. Viele Teams testen den Happy Path, aber nie den Rollback. Regelmaessige Rollback-Uebungen (mindestens quartalweise) decken Probleme auf, bevor sie in einer echten Krise relevant werden.

Weitergehende Themen


Wer Unterstuetzung beim Aufbau skalierbarer CI/CD-Pipelines braucht -- von der Architektur bis zur Argo-CD-Konfiguration -- kann sich gerne unter /kontakt melden.

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