Warum Helm und GitOps zusammengehören

Kubernetes-Manifeste von Hand zu verwalten funktioniert bei einem Service in einem Environment. Bei zehn Services in drei Environments wird es unübersichtlich. Bei zwanzig Services mit unterschiedlichen Konfigurationen pro Stage ist es nicht mehr beherrschbar.

Helm Charts und GitOps lösen dieses Problem auf unterschiedlichen Ebenen: Helm abstrahiert die Kubernetes-Manifeste zu parametrierbaren Templates. GitOps stellt sicher, dass der Zustand im Cluster dem Zustand im Git-Repository entspricht. Zusammen ergeben sie einen reproduzierbaren, auditierbaren Deployment-Prozess.

Helm Chart Struktur

Ein gut strukturiertes Helm Chart folgt Konventionen, die Wartbarkeit und Wiederverwendbarkeit fördern:

charts/vop-service/
├── Chart.yaml
├── values.yaml              # Default-Werte
├── values-dev.yaml          # Environment-spezifisch
├── values-qa.yaml
├── values-prod.yaml
├── templates/
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── configmap.yaml
│   ├── hpa.yaml             # Horizontal Pod Autoscaler
│   ├── networkpolicy.yaml
│   ├── serviceaccount.yaml
│   └── _helpers.tpl         # Template-Hilfsfunktionen
└── tests/
    └── test-connection.yaml

Values per Environment

Der Kern von Helm ist die Trennung von Template und Konfiguration. Ein values.yaml enthält die Defaults, environment-spezifische Values überschreiben gezielt:

# values.yaml (Defaults)
replicaCount: 1
image:
  repository: registry.rypox.de/vop-service
  tag: latest
resources:
  requests:
    cpu: 100m
    memory: 256Mi
  limits:
    cpu: 500m
    memory: 512Mi
kafka:
  bootstrapServers: kafka:9092
  consumerGroup: vop-service

# values-prod.yaml (Produktion)
replicaCount: 3
image:
  tag: "1.4.2"
resources:
  requests:
    cpu: 500m
    memory: 1Gi
  limits:
    cpu: "2"
    memory: 2Gi
kafka:
  bootstrapServers: kafka-prod.vop-system:9093
  consumerGroup: vop-service-prod

Best Practices für Helm Charts

Einige Regeln, die sich in unseren Projekten bewährt haben:

  • Keine Secrets in Values, Secrets gehören in Vault oder Kubernetes Secrets, nicht in Values-Dateien
  • Resource Limits immer setzen, Ein Pod ohne Limits kann den gesamten Node destabilisieren
  • Health Checks konfigurieren, Liveness und Readiness Probes sind Pflicht, nicht optional
  • Labels konsistent halten, app.kubernetes.io/name, app.kubernetes.io/version, app.kubernetes.io/component nach den Kubernetes-Empfehlungen
  • Chart-Versionen semantisch vergeben, Das Chart hat eine eigene Version, unabhängig von der Applikationsversion

GitLab CI Pipeline

Unsere CI/CD-Pipeline in GitLab CI bildet den gesamten Lifecycle ab: Build, Test, Deploy auf Test, Deploy auf QA und Deploy auf Produktion.

Pipeline-Stages

stages:
  - build
  - test
  - package
  - deploy-test
  - integration-test
  - deploy-qa
  - deploy-prod

build:
  stage: build
  script:
    - ./gradlew build -x test
  artifacts:
    paths:
      - build/libs/*.jar

test:
  stage: test
  script:
    - ./gradlew test
  artifacts:
    reports:
      junit: build/test-results/test/*.xml

package:
  stage: package
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

deploy-test:
  stage: deploy-test
  script:
    - helm upgrade --install vop-service ./charts/vop-service
        -f ./charts/vop-service/values-test.yaml
        --set image.tag=$CI_COMMIT_SHA
        --namespace vop-test
  environment:
    name: test

deploy-qa:
  stage: deploy-qa
  script:
    - helm upgrade --install vop-service ./charts/vop-service
        -f ./charts/vop-service/values-qa.yaml
        --set image.tag=$CI_COMMIT_SHA
        --namespace vop-qa
  environment:
    name: qa
  when: manual

deploy-prod:
  stage: deploy-prod
  script:
    - helm upgrade --install vop-service ./charts/vop-service
        -f ./charts/vop-service/values-prod.yaml
        --set image.tag=$CI_COMMIT_SHA
        --namespace vop-prod
  environment:
    name: production
  when: manual
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

Wichtige Designentscheidungen

  • Test-Deployment automatisch, Jeder Merge in den Develop-Branch deployt automatisch auf Test. Schnelles Feedback
  • QA und Produktion manuell, Ein Klick in der Pipeline, aber bewusst. Kein versehentliches Produktions-Deployment
  • Image-Tag ist Commit-SHA, Jedes Deployment ist exakt einem Commit zuordenbar. Kein latest-Tag in Produktion
  • Integration Tests zwischen Test und QA, Nach dem Test-Deployment laufen automatisierte API-Tests gegen die Test-Umgebung

Deployment-Strategien

Rolling Update (Standard)

Kubernetes’ Standard-Strategie ersetzt Pods schrittweise. Konfiguriert über die Deployment-Spec:

strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0

maxUnavailable: 0 stellt sicher, dass während des Updates keine Kapazität verloren geht. Neue Pods müssen ihre Readiness Probe bestehen, bevor alte Pods terminiert werden.

Canary Deployments

Für kritische Services deployen wir zunächst eine einzelne Instanz der neuen Version und überwachen die Metriken:

  1. Helm Release mit replicaCount: 1 und neuer Version deployen
  2. Traffic Split über Istio VirtualService: 10% auf Canary
  3. Metriken vergleichen: Error Rate, Latenz, Business-Metriken
  4. Bei Erfolg: Vollständiges Rollout. Bei Problemen: Rollback

Rollback

Helm speichert Revisions. Ein Rollback ist ein einzelner Befehl:

helm rollback vop-service 3 --namespace vop-prod

Das stellt die dritte Revision wieder her, inklusive aller Konfigurationswerte. In Kombination mit dem Commit-SHA als Image-Tag ist jeder Zustand reproduzierbar.

GitOps mit ArgoCD

Für die langfristige Entwicklung evaluieren wir Argo CD als GitOps-Controller. Der Unterschied zu unserer aktuellen Pipeline: Statt dass die CI-Pipeline helm upgrade ausführt, überwacht ArgoCD ein Git-Repository und synchronisiert den Cluster-Zustand automatisch.

Vorteile:

  • Git als Single Source of Truth, Der gewünschte Zustand ist im Repository, nicht im Cluster
  • Drift Detection, Manuelle Änderungen am Cluster werden erkannt und korrigiert
  • Self-Healing, Gelöschte Ressourcen werden automatisch wiederhergestellt
  • Audit Trail, Jede Änderung ist ein Git-Commit mit Autor und Zeitstempel

Fazit

Die Kombination aus Helm Charts und einer durchdachten CI/CD-Pipeline ist die Grundlage für zuverlässige Deployments in Kubernetes. Helm abstrahiert die Komplexität der Kubernetes-Manifeste, environment-spezifische Values halten die Konfiguration sauber getrennt, und die Pipeline automatisiert den Weg von Code zu laufendem Service. Das Ziel ist immer dasselbe: Deployments sollen langweilig sein, vorhersagbar, wiederholbar und schnell rückgängig zu machen.