Rolling Updates Kubernetes
Rolling Updates in Kubernetes
Rolling Updates ersetzen Pods schrittweise ohne Downtime. Lernen Sie Deployment-Strategien, Konfiguration und wie Sie fehlerhafte Rollouts beheben.
Wie Rolling Updates funktionieren
┌─────────────────────────────────────────────────────────────┐ │ ROLLING UPDATE │ ├─────────────────────────────────────────────────────────────┤ │ │ │ START: 4 Pods mit v1.0 │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │v1.0 │ │v1.0 │ │v1.0 │ │v1.0 │ │ │ └─────┘ └─────┘ └─────┘ └─────┘ │ │ │ │ SCHRITT 1: 1 neuer Pod, 1 alter terminiert │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │v1.1 │ │v1.0 │ │v1.0 │ │ ✕ │ │ │ └─────┘ └─────┘ └─────┘ └─────┘ │ │ │ │ SCHRITT 2: Weiterer Austausch │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │v1.1 │ │v1.1 │ │v1.0 │ │ ✕ │ │ │ └─────┘ └─────┘ └─────┘ └─────┘ │ │ │ │ ENDE: Alle Pods auf v1.1 │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │v1.1 │ │v1.1 │ │v1.1 │ │v1.1 │ │ │ └─────┘ └─────┘ └─────┘ └─────┘ │ │ │ └─────────────────────────────────────────────────────────────┘
Deployment Konfiguration
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 4
selector:
matchLabels:
app: myapp
# Rolling Update Strategie
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Max. zusätzliche Pods während Update
maxUnavailable: 1 # Max. nicht verfügbare Pods
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1.0
ports:
- containerPort: 8080
# Kritisch für Rolling Updates!
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
maxSurge und maxUnavailable
# Beispiel: 4 Replicas # KONSERVATIV (langsam, sicher) maxSurge: 1 # Max 5 Pods gleichzeitig (4+1) maxUnavailable: 0 # Immer 4 Pods verfügbar # → Langsam aber keine Kapazitätsreduktion # SCHNELL (mehr Ressourcen nötig) maxSurge: 2 # Max 6 Pods gleichzeitig (4+2) maxUnavailable: 0 # Immer 4 Pods verfügbar # → Schneller, braucht aber mehr Cluster-Kapazität # BALANCED maxSurge: 1 maxUnavailable: 1 # Min 3 Pods verfügbar # → Guter Kompromiss aus Geschwindigkeit und Kapazität # AGGRESSIV (schnellstes Update) maxSurge: 25% # +25% = 1 Pod bei 4 Replicas maxUnavailable: 25% # -25% = 1 Pod bei 4 Replicas # → Schnell, aber kurzzeitig weniger Kapazität # Prozent-Werte werden aufgerundet (Surge) / abgerundet (Unavailable)
Deployment durchführen
# Update durch Image-Änderung kubectl set image deployment/myapp myapp=myapp:v1.1 # Oder via YAML-Update kubectl apply -f deployment.yaml # Mit Record für Rollback-History kubectl set image deployment/myapp myapp=myapp:v1.1 --record # Update-Status beobachten kubectl rollout status deployment/myapp # Detaillierter Status kubectl describe deployment myapp # Pods während Update beobachten kubectl get pods -w -l app=myapp
Rollout History und Rollback
# Rollout-History anzeigen kubectl rollout history deployment/myapp # REVISION CHANGE-CAUSE # 1 kubectl set image... myapp:v1.0 # 2 kubectl set image... myapp:v1.1 # 3 kubectl set image... myapp:v1.2 # Bestimmte Revision anzeigen kubectl rollout history deployment/myapp --revision=2 # Rollback zur vorherigen Version kubectl rollout undo deployment/myapp # Rollback zu bestimmter Revision kubectl rollout undo deployment/myapp --to-revision=1 # Rollout pausieren (z.B. bei Problemen) kubectl rollout pause deployment/myapp # Rollout fortsetzen kubectl rollout resume deployment/myapp # Rollout neu starten (alle Pods ersetzen) kubectl rollout restart deployment/myapp
Probes richtig konfigurieren
# KRITISCH: Ohne korrekte Probes kann Rolling Update
# Traffic an nicht-bereite Pods senden!
containers:
- name: myapp
image: myapp:v1.0
# Readiness Probe: Wann Pod Traffic empfangen kann
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5 # Warten nach Container-Start
periodSeconds: 5 # Wie oft prüfen
timeoutSeconds: 3 # Timeout pro Prüfung
successThreshold: 1 # Erfolge bis "ready"
failureThreshold: 3 # Fehler bis "not ready"
# Liveness Probe: Ob Pod noch funktioniert
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15 # Mehr Zeit für App-Start
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3 # Pod wird neu gestartet
# Startup Probe: Für langsam startende Apps
startupProbe:
httpGet:
path: /health
port: 8080
failureThreshold: 30 # 30 * 10s = 5 Minuten
periodSeconds: 10
# Reihenfolge:
# 1. startupProbe (wenn definiert) muss erfolgreich sein
# 2. Dann übernehmen readiness/liveness Probes
Graceful Shutdown
spec:
template:
spec:
# Zeit für graceful shutdown
terminationGracePeriodSeconds: 30
containers:
- name: myapp
lifecycle:
preStop:
exec:
# Warten damit Load Balancer Pod entfernt
command: ["/bin/sh", "-c", "sleep 10"]
// App muss SIGTERM behandeln!
// Node.js Beispiel
process.on('SIGTERM', async () => {
console.log('SIGTERM received, shutting down gracefully');
// Neue Requests ablehnen
server.close(async () => {
console.log('HTTP server closed');
// Bestehende Verbindungen abschließen
await database.disconnect();
await cache.disconnect();
console.log('Cleanup complete');
process.exit(0);
});
// Force-Exit nach Timeout
setTimeout(() => {
console.log('Force exit after timeout');
process.exit(1);
}, 25000); // Weniger als terminationGracePeriodSeconds
});
PodDisruptionBudget
# Garantiert Mindest-Verfügbarkeit während Updates
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb
spec:
# Entweder minAvailable ODER maxUnavailable
minAvailable: 2 # Immer min. 2 Pods verfügbar
# maxUnavailable: 1 # Max. 1 Pod gleichzeitig weg
selector:
matchLabels:
app: myapp
# Wichtig für:
# - Rolling Updates
# - Node Drains
# - Cluster Autoscaling
# - Maintenance
Deployment Strategien vergleichen
# 1. ROLLING UPDATE (Standard)
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
# ✅ Zero-Downtime
# ✅ Wenig Extra-Ressourcen
# ❌ Zwei Versionen gleichzeitig aktiv
# 2. RECREATE (Alle auf einmal)
strategy:
type: Recreate
# ✅ Einfach, keine Version-Mischung
# ❌ DOWNTIME während Update
# → Nur für Entwicklung oder wenn Versionen inkompatibel
# 3. BLUE-GREEN (via 2 Deployments + Service Switch)
# Siehe separater Artikel
# 4. CANARY (via Traffic Splitting)
# Siehe separater Artikel
Troubleshooting
# Update hängt? # 1. Status prüfen kubectl rollout status deployment/myapp # 2. Events anschauen kubectl describe deployment myapp kubectl get events --sort-by='.lastTimestamp' # 3. Pod-Status prüfen kubectl get pods -l app=myapp kubectl describe podkubectl logs # Häufige Probleme: # ❌ ImagePullBackOff # → Image existiert nicht oder keine Credentials kubectl describe pod | grep -A5 "Events" # ❌ CrashLoopBackOff # → App crasht beim Start kubectl logs --previous # ❌ Readiness Probe Failed # → App antwortet nicht auf Health-Endpoint kubectl exec -- curl localhost:8080/health # ❌ Insufficient Resources # → Cluster hat nicht genug CPU/Memory kubectl describe nodes | grep -A5 "Allocated resources" # Update abbrechen und zurückrollen kubectl rollout undo deployment/myapp
# progressDeadlineSeconds für automatischen Rollback
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
# Wenn Update nicht innerhalb von 10 Min abgeschlossen
# wird es als "failed" markiert
progressDeadlineSeconds: 600
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
# Status bei Timeout:
# kubectl get deployment myapp
# READY UP-TO-DATE AVAILABLE
# 3/4 1 3
# Condition: ProgressDeadlineExceeded
💡 Best Practices:
1. Immer Readiness Probes konfigurieren
2. SIGTERM Handling in der App implementieren
3. PodDisruptionBudget für kritische Services
4. progressDeadlineSeconds setzen
5. Rollout-History mit --record aufzeichnen
2. SIGTERM Handling in der App implementieren
3. PodDisruptionBudget für kritische Services
4. progressDeadlineSeconds setzen
5. Rollout-History mit --record aufzeichnen