Die Einführung von GitOps in produktive Umgebungen erfordert einen durchdachten, risikoarmen Ansatz. Dieser Leitfaden beschreibt eine bewährte Strategie zur störungsfreien Migration bestehender Deployments zu GitOps-Praktiken.
Inventarisierung bestehender Deployments:
# Alle Deployments erfassen
kubectl get deployments --all-namespaces -o wide
# Aktuelle Konfigurationsquellen identifizieren
kubectl get deployments -o jsonpath='{.items[*].metadata.annotations}' | grep -E "(helm|kustomize|ci|pipeline)"
# Manuelle Änderungen aufspüren
kubectl get events --sort-by=.metadata.creationTimestamp | grep -E "(kubectl|manual)"Repository-Audit:
# ArgoCD mit restriktiven Einstellungen
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: legacy-app-observer
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/k8s-manifests
targetRevision: main
path: apps/legacy-app
destination:
server: https://kubernetes.default.svc
namespace: legacy-app
syncPolicy:
# WICHTIG: Kein automatisches Sync!
syncOptions:
- CreateNamespace=false
- ApplyOutOfSyncOnly=false
- Validate=true
- DryRun=true # Nur Validierung, keine Änderungen# ArgoCD CLI für Drift-Analyse
argocd app get legacy-app-observer --show-params
argocd app diff legacy-app-observer
# Regelmäßige Drift-Reports
cat > drift-monitor.sh << 'EOF'
#!/bin/bash
echo "$(date): Drift Report" >> drift-log.txt
argocd app list --output wide | grep OutOfSync >> drift-log.txt
echo "---" >> drift-log.txt
EOF
# Cron Job für tägliche Drift-Überwachung
0 8 * * * /opt/scripts/drift-monitor.shAuswahlkriterien:
Anti-Pattern vermeiden:
# Repository-Struktur für Pilotprojekt
mkdir -p pilot-gitops/{apps,environments,argocd}
# Pilot App Struktur
pilot-gitops/
├── apps/
│ └── pilot-app/
│ ├── base/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── kustomization.yaml
│ └── overlays/
│ ├── staging/
│ └── production/
├── environments/
│ ├── staging/
│ │ └── pilot-app.yaml
│ └── production/
│ └── pilot-app.yaml
└── argocd/
└── applications/
├── pilot-staging.yaml
└── pilot-production.yaml# Staging-Environment als ArgoCD-Test
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: pilot-app-staging
namespace: argocd
spec:
project: pilot-project
source:
repoURL: https://github.com/your-org/pilot-gitops
targetRevision: main
path: environments/staging
destination:
server: https://kubernetes.default.svc
namespace: pilot-staging
syncPolicy:
automated:
prune: false # Zunächst konservativ
selfHeal: false # Manueller Sync erforderlich
syncOptions:
- CreateNamespace=true
- ApplyOutOfSyncOnly=trueVorbereitung:
# Pre-Sync Validation
argocd app diff pilot-app-staging
argocd app sync pilot-app-staging --dry-run
# Sync mit Überwachung
argocd app sync pilot-app-staging --prune=falsePost-Sync Verification:
# Application Health Check
argocd app get pilot-app-staging
kubectl get pods -n pilot-staging
kubectl get events -n pilot-staging --sort-by=.metadata.creationTimestampStandard Operating Procedures (SOP):
# 1. Drift-Ursache analysieren
kubectl describe deployment pilot-app -n pilot-staging
kubectl get events -n pilot-staging | grep pilot-app
# 2. Entscheidungsmatrix anwenden
if [ "$DRIFT_TYPE" == "emergency" ]; then
echo "Emergency drift - temporary accept"
# Dokumentation für spätere Git-Update
elif [ "$DRIFT_TYPE" == "operational" ]; then
echo "Operational drift - evaluate for formalization"
else
echo "Unauthorized drift - initiate correction"
argocd app sync pilot-app-staging
fi# Bei wertvollen manuellen Änderungen
git checkout -b formalize-drift-$(date +%Y%m%d)
# Manuelle Änderung ins Git übertragen
kubectl get deployment pilot-app -n pilot-staging -o yaml > apps/pilot-app/base/deployment.yaml
git add apps/pilot-app/base/deployment.yaml
git commit -m "Formalize production adjustment: increase memory limits"
git push origin formalize-drift-$(date +%Y%m%d)
# Pull Request für ReviewKriterien für Automatic Sync:
# Upgrade zu Automatic Sync
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground# ApplicationSet für skalierte Einführung
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: production-apps
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/your-org/production-gitops
revision: HEAD
directories:
- path: apps/*
template:
metadata:
name: '{{path.basename}}'
spec:
project: production
source:
repoURL: https://github.com/your-org/production-gitops
targetRevision: HEAD
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: trueapiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: production
namespace: argocd
spec:
description: Production Applications
sourceRepos:
- 'https://github.com/your-org/production-gitops'
destinations:
- namespace: 'app-*'
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ''
kind: Namespace
namespaceResourceWhitelist:
- group: 'apps'
kind: Deployment
- group: ''
kind: Service
- group: 'networking.k8s.io'
kind: Ingress
roles:
- name: developers
policies:
- p, proj:production:developers, applications, get, production/*, allow
- p, proj:production:developers, applications, sync, production/*, allow
groups:
- your-org:developers
- name: operators
policies:
- p, proj:production:operators, applications, *, production/*, allow
groups:
- your-org:platform-team# Canary-Deployment Integration
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: progressive-app
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 10
- pause: {duration: 30s}
- setWeight: 50
- pause: {duration: 2m}
analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: progressive-app
selector:
matchLabels:
app: progressive-app
template:
metadata:
labels:
app: progressive-app
spec:
containers:
- name: app
image: nginx:1.20# Cluster-spezifische Applications
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: multi-cluster-apps
spec:
generators:
- clusters: {}
template:
metadata:
name: '{{name}}-guestbook'
spec:
project: multi-cluster
source:
repoURL: https://github.com/your-org/apps
targetRevision: HEAD
path: apps/guestbook
destination:
server: '{{server}}'
namespace: guestbook# ArgoCD mit Health-Check Integration
spec:
syncPolicy:
automated:
prune: true
selfHeal: true
retry:
limit: 3
backoff:
duration: 5s
factor: 2
maxDuration: 3m# Emergency Procedures
cat > emergency-rollback.sh << 'EOF'
#!/bin/bash
APP_NAME=$1
PREVIOUS_REVISION=$2
echo "EMERGENCY ROLLBACK for $APP_NAME to revision $PREVIOUS_REVISION"
argocd app history $APP_NAME
argocd app rollback $APP_NAME $PREVIOUS_REVISION
kubectl rollout status deployment/$APP_NAME -n $(argocd app get $APP_NAME -o json | jq -r '.spec.destination.namespace')
EOF
chmod +x emergency-rollback.shCurriculum für Development Teams:
Curriculum für Operations Teams:
Stakeholder Mapping:
# GitOps Adoption Metrics
gitops_applications_total
gitops_sync_success_rate
gitops_drift_detection_frequency
gitops_manual_interventions_total
gitops_deployment_frequency
gitops_lead_time_for_changes
gitops_mean_time_to_recovery
# Grafana Dashboard Query Examples
- expr: |
sum(argocd_app_info{sync_status="Synced"}) / sum(argocd_app_info) * 100
legendFormat: "Sync Success Rate %"
- expr: |
increase(argocd_app_sync_total{phase="Succeeded"}[24h])
legendFormat: "Successful Deployments per Day"
- expr: |
sum by (name) (argocd_app_info{sync_status="OutOfSync"})
legendFormat: "Applications with Drift"Kritische Erfolgsfaktoren:
Häufige Fallstricke vermeiden:
Die erfolgreiche GitOps-Einführung ist kein technisches, sondern ein organisatorisches Transformation-Projekt. Der Schlüssel liegt in der systematischen, risikoarmen Herangehensweise mit kontinuierlicher Team-Einbindung und transparenter Kommunikation über Fortschritte und Herausforderungen.