GitOps ArgoCD Flux CI/CD Kubernetes

GitOps: Automatisierte Deployments mit ArgoCD und Flux

Das Git-Repository ist die einzige Quelle der Wahrheit — für Infrastruktur und für Applikationen. GitOps eliminiert Click-Ops und schafft Nachvollziehbarkeit, Audit-Trails und automatisierte Rollbacks. ArgoCD und Flux machen Kubernetes-Deployments so sicher wie ein Git-Push.

Was ist GitOps? Das Prinzip erklärt

GitOps = Git als Single Source of Truth für deklarative Konfigurationen. Die Idee:

1 Entwickler pushed Code ins Git-Repo
2 CI-Pipeline baut Container-Image → taggt es mit Git-Commit-SHA
3 Pipeline updated Kubernetes-Manifest in Git (neues Image-Tag)
4 GitOps-Tool (ArgoCD/Flux) erkennt Änderung → synced zum Cluster
5 Deployment läuft automatisch, kein human intervention nötig

Der entscheidende Unterschied zu traditionellem CI/CD: Die desired State (in Git) und der actual State (im Cluster) werden permanent abgeglichen. Drift (unbeabsichtigte Änderungen) wird erkannt und korrigiert.

Drift Detection: Wenn jemand manuell einen Pod löscht oder eine ConfigMap ändert, erkennt ArgoCD/Flux das sofort und reconciled — es stellt den Git-Stated-Zustand wieder her. Manuelles Chaos hat keine Chance.

ArgoCD vs. Flux — Was nutzen?

KriteriumArgoCDFlux v2
AnsatzPush-basiert (ArgoCD pullt aus Git)Push + GitOps Toolkit (modular)
UIEingebaute Web-UI (gut für Nicht-DevOps)Keine native UI (CLI + Dashboard als Extra)
Multi-ClusterApplication Set + FederationFlux Multi-Tenant Operator
SecurityRBAC + SSO (Dex + OIDC)SOPS-Integration, secrets encryption
Image-UpdatesArgoCD Image Updater (Plugin)Flux Image Reflector + Automation
EinstiegSchneller, mehr GUI, mehr "batteries included"Mehr modular, besser für Kubernetes-first Teams
MaintenanceRelativ heavyweight (many CRDs)Leichterer Operator, gute GitHub-Integration

Für die meisten Teams ist ArgoCD der bessere Einstieg — die Web-UI macht GitOps für das ganze Team zugänglich, auch ohne CLI-Erfahrung.

Schritt 1: ArgoCD installieren

# Namespace erstellen und ArgoCD installieren kubectl create namespace argocd kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.11.0/manifests/install.yaml # Oder via Helm (empfohlen für Produktion) helm repo add argo https://argoproj.github.io/argo-helm helm repo update helm install argocd argo/argo-cd -n argocd \n --set server.service.type=LoadBalancer # Initiales Admin-Passwort (aus Secret) kubectl -n argocd get secret argocd-initial-admin-secret \n -o jsonpath="{.data.password}" | base64 -d

Nach Installation: UI auf https://argocd.$(minikube ip) oder via Ingress. Login mit User admin und dem Initial-Password.

Schritt 2: Applications in ArgoCD definieren

Eine ArgoCD Application ist ein deklaratives Kubernetes-Manifest, das ArgoCD sagt: "Synce diesen Git-Repo-Pfad zu diesem Cluster-Pfad."

# application.yaml — Application für die Webapp apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: webapp-production namespace: argocd finalizers: - resources-finalizer.argocd.argoproj.io spec: project: default source: repoURL: https://github.com/dein-org/k8s-config.git targetRevision: main path: apps/webapp/production kustomize: images: # Automatisch: Image-Updater setzt dieses Tag - webapp:deinregistry.io/webapp=registry.io/webapp:v1.2.3 destination: server: https://kubernetes.default.svc namespace: production syncPolicy: automated: prune: true # Alte Resources automatisch löschen selfHeal: true # Drift automatisch korrigieren allowEmpty: false syncOptions: - CreateNamespace=true retry: limit: 5 backoff: duration: 5s factor: 2 maxDuration: 3m

prune: true + selfHeal: true sind die Kern-Features: ArgoCD erkennt Unterschiede zwischen Git und Cluster und fixt sie automatisch.

Schritt 3: Kustomize für Umgebungen

Ein zentrales Git-Repo mit Kustomize-overlays für prod/staging/dev — keine Duplikation, klare Hierarchie.

# apps/webapp/base/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - deployment.yaml - service.yaml - ingress.yaml commonLabels: app: webapp images: - name: registry.io/webapp newName: registry.io/webapp newTag: latest
# apps/webapp/production/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: production bases: - ../base patches: - patch-replicas.yaml - patch-resources.yaml images: - name: registry.io/webapp newTag: v1.2.3 # Production → pinned Tag (kein latest!)
# apps/webapp/staging/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: staging bases: - ../base replicas: - name: webapp count: 1 # Staging: nur 1 Replica images: - name: registry.io/webapp newTag: staging-$(IMAGE_TAG_SUFFIX) # Automatisch aus Pipeline

Pinned Tags statt latest: Production sollte nie latest verwenden. Nutze semantische Tags (v1.2.3) oder Git-Commit-SHAs. latest macht Rollbacks unmöglich — du weißt nicht, was "latest" gestern war.

Schritt 4: CI-Pipeline — Image bauen und Git aktualisieren

Pipeline-Ablauf: Build → Push → Update Image-Tag in Git → ArgoCD synced. GitOps-typisch: Pipeline pushed NIEMALS direkt in den Cluster, nur ins Git.

# .github/workflows/deploy.yml name: Build and Deploy on: push: branches: [main] jobs: build-and-push: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Docker Build run: | docker build -t registry.io/webapp:${GITHUB_SHA::8} . - name: Push to Registry run: | docker push registry.io/webapp:${GITHUB_SHA::8} - name: Update image tag in Git run: | # Kubernetes Repo klonen git clone https://github.com/dein-org/k8s-config.git cd k8s-config # Tag in kustomization.yaml updaten sed -i "s|newTag:.*|newTag: ${GITHUB_SHA::8}|" apps/webapp/production/kustomization.yaml git config user.name "GitHub Actions" git config user.email "actions@github.com" git add -A git commit -m "chore: deploy ${GITHUB_SHA::8}" git push origin main

Schritt 5: Image-Updater — automatisches Sync ohne Pipeline

ArgoCD Image Updater scannt Container-Registries automatisch und updated Image-Tags im Git — ohne dass die CI-Pipeline Git ändern muss. Pipeline baut nur das Image; alles andere passiert automatisch.

# image-updater mit GitHub Container Registry apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: webapp-production annotations: # Image Updater aktivieren argocd.argoproj.io/image-updater.autoupdate: "true" argocd.argoproj.io/image-updater.sync-policy: "automated" argocd.argoproj.io/image-updater.argocd.notification.address: "" spec: source: kustomize: images: # Wenn neues Image vorhanden → update Git und sync - image: registry.io/webapp images: - registry.io/webapp:{{ argocd-image-updater.tag }} update_strategy: semver # Automatisch neueste v1.x.y → deployed, kein Commit nötig

Rollbacks: Git als Sicherheitsnetz

GitOps macht Rollbacks trivial — du reverst den Git-Commit, ArgoCD synced automatisch.

# Per CLI (kubectl + argocd CLI) argocd app rollback webapp-production # Per Git — Commit revertieren git revert HEAD git push origin main # ArgoCD erkennt Änderung und synced auf vorherige Version # Per ArgoCD UI: Compare → Revision wählen → Sync

Ohne GitOps war ein Rollback eine komplexe Operation (altes Image manuell deployen, Confmaps wiederherstellen, etc.). Mit GitOps: ein git revert.

Multi-Cluster-Setup

Für Production empfehlen sich getrennte Cluster pro Umgebung (nicht Namespaces im gleichen Cluster). ArgoCD mit ApplicationSet managed mehrere Cluster aus einem Repo.

# application-set.yaml — deployed auf prod + staging automatisch apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: webapp-all-envs spec: generators: - clusters: values: environment: production - name: staging server: https://staging-cluster.k8s.local values: environment: staging template: spec: source: repoURL: https://github.com/dein-org/k8s-config.git path: apps/webapp/{{ values.environment }} targetRevision: main destination: server: "{{ server }}" namespace: "{{ values.environment }}" syncPolicy: automated: prune: true selfHeal: true

Security: Secrets in Git

Secrets (DB-Passwörter, API-Keys) gehören NICHT unverschlüsselt in Git. Workflow:

# sealed-secret.yaml — unverschlüsselt in Git, aber nicht lesbar ohne Cluster-Key apiVersion: bitnami.com/v1alpha1 kind: SealedSecret metadata: name: webapp-secrets namespace: production spec: encryptedData: DB_PASSWORD: AgA... # Verschlüsselt mit Cluster-Key API_KEY: AgB... # Nur Cluster kann entschlüsseln template: metadata: name: webapp-secrets namespace: production

Branch-Strategie für GitOps

BranchWas passiertZielumgebung
mainAuto-sync nach ApprovalProduction
staging/*Auto-sync ohne ApprovalStaging
feature/*Preview-Namespace auf AnfrageFeature-Cluster
hotfix/*Fast-Track → main → ProductionProduction (beschleunigt)

GitOps-Spickzettel: Deine Checkliste

  • Git-Repo = Single Source of Truth — Keine manuelle Änderungen direkt im Cluster erlaubt
  • ArgoCD oder Flux — Beide sind production-ready. ArgoCD hat bessere UI; Flux ist modularer
  • Pinned Tags (v1.2.3), niemals latest — Rollbacks funktionieren nur mit expliziten Tags
  • Sync-Policy: selfHeal + prune — Drift wird automatisch korrigiert, kein Chaos-Admin kann den Cluster brechen
  • Secrets verschlüsseln (Sealed Secrets / SOPS / ESO) — Plaintext-Secrets in Git = Kompromittierung
  • ApplicationSets für Multi-Cluster — ein Repo, viele Cluster, automatisierte Reconciliation
  • Pipeline updated Git, GitOps-Tool synced den Cluster — Pipeline pushet NIEMALS direkt auf Kubernetes
  • Rollbacks = git revert + auto-sync — einfachste, sicherste Recovery-Methode

Das könnte Sie auch interessieren

Mehr erfahren

Kubernetes auf eigener Infrastruktur: Einstieg für Entwickler

Mehr erfahren

.htaccess & Nginx-Konfiguration: Perfekte Webserver-Einstellungen

Mehr erfahren

API Gateway Hosting: Microservices richtig aufsetzen