- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Resilience Patterns: Ausfallsicherheit fuer produktive Cluster
TL;DR
- Resilienz in Kubernetes ergibt sich nicht automatisch -- sie erfordert bewusste Konfiguration von Probes, Resource Limits, Anti-Affinity und PodDisruptionBudgets
- Pod Anti-Affinity verteilt Replicas ueber Nodes und Availability Zones, damit ein einzelner Ausfall nicht alle Instanzen trifft
- PodDisruptionBudgets (PDB) schuetzen vor zu aggressiven Node-Drains bei Upgrades oder Cluster-Autoscaler-Aktionen
- Circuit Breaker und Retries gehoeren in die Anwendung oder in ein Service Mesh, nicht in Kubernetes selbst
- Chaos Engineering (z.B. mit Litmus oder chaos-mesh) deckt Schwachstellen auf, bevor die Produktion sie zeigt
Kubernetes ist nicht von allein ausfallsicher
Eine verbreitete Fehleinschaetzung: "Kubernetes ist fehlertolerant." Das stimmt nur zur Haelfte. Kubernetes startet abgestuerzte Pods neu und verteilt Workloads auf verfuegbare Nodes. Aber es macht keine Aussage darueber, ob Ihre Anwendung den Ausfall eines Pods ueberlebt, ob Ihre Daten konsistent bleiben, oder ob ein Node-Drain waehrend eines Upgrades den gesamten Service kurzzeitig offline nimmt.
Resilience Patterns sind die bewussten Architektur-Entscheidungen, die den Unterschied zwischen "Kubernetes startet den Pod neu" und "der Service bleibt fuer Endnutzer verfuegbar" ausmachen.
Pattern 1: Pod Anti-Affinity und Topology Spread
Das Grundproblem: Der Kubernetes Scheduler platziert Pods standardmaessig dort, wo Ressourcen frei sind. Ohne weitere Konfiguration koennen alle drei Replicas einer Anwendung auf demselben Node landen. Faellt der Node aus, sind alle drei weg.
Pod Anti-Affinity
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- order-service
topologyKey: kubernetes.io/hostname
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- order-service
topologyKey: topology.kubernetes.io/zone
containers:
- name: order-service
image: registry.example.com/order-service:1.5.2
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
Die Konfiguration hat zwei Ebenen:
- required auf Hostname-Ebene: Zwei Pods der gleichen App duerfen nie auf demselben Node laufen. Hart erzwungen.
- preferred auf Zone-Ebene: Kubernetes versucht, die Pods ueber Availability Zones zu verteilen, erzwingt es aber nicht. Das ist sinnvoll, weil bei kleinen Clustern nicht immer genug Zonen vorhanden sind.
TopologySpreadConstraints (Alternative)
Seit Kubernetes 1.19 gibt es topologySpreadConstraints als feingranularere Alternative zu Anti-Affinity. Der Vorteil: Sie definieren einen maxSkew, der angibt, wie ungleich die Verteilung maximal sein darf.
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: order-service
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: order-service
maxSkew: 1 bedeutet: Der Unterschied zwischen der Zone mit den meisten und der Zone mit den wenigsten Pods darf maximal 1 betragen. Fuer die meisten Services ist das die richtige Einstellung.
Pattern 2: PodDisruptionBudgets
PodDisruptionBudgets (PDB) werden oft vergessen und sind trotzdem eines der wichtigsten Resilience-Tools. Sie definieren, wie viele Pods einer Anwendung gleichzeitig offline sein duerfen -- etwa bei einem Node-Drain, einem Cluster-Upgrade oder einer Cluster-Autoscaler-Aktion.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: order-service-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: order-service
Ohne PDB kann kubectl drain alle Pods eines Nodes gleichzeitig evicten. Mit minAvailable: 2 und drei Replicas darf immer nur ein Pod gleichzeitig heruntergefahren werden.
| PDB-Einstellung | Effekt | Empfohlener Einsatz |
|---|---|---|
| minAvailable: 2 | Mindestens 2 Pods muessen immer laufen | Services mit 3+ Replicas |
| maxUnavailable: 1 | Maximal 1 Pod darf gleichzeitig fehlen | Gleicher Effekt, andere Semantik |
| minAvailable: "50%" | Mindestens die Haelfte muss laufen | Groessere Deployments (10+ Pods) |
| maxUnavailable: 0 | Kein Pod darf entfernt werden | Nur fuer absolute Notfaelle, blockiert Upgrades |
Achtung: maxUnavailable: 0 blockiert Node-Drains komplett. Das kann sinnvoll sein fuer kritische Datenbankprozesse, fuehrt aber dazu, dass Cluster-Upgrades haengen bleiben. Verwenden Sie es nur, wenn Sie einen manuellen Freigabeprozess haben.
Mehr Details zum Thema Kapazitaetsplanung und wie PDBs mit dem Cluster Autoscaler zusammenspielen finden Sie unter Kubernetes Capacity Planning.
Pattern 3: Health Checks richtig konfigurieren
Liveness- und Readiness-Probes sind keine optionalen Features. Ohne sie weiss Kubernetes nicht, ob ein Container tatsaechlich funktioniert -- er weiss nur, ob der Prozess laeuft.
Haeufige Fehler:
- Liveness-Probe auf eine Dependency zeigen lassen. Wenn die Liveness-Probe die Datenbank prueft und die DB kurz nicht erreichbar ist, werden alle Pods gekillt. Genau das Gegenteil von Resilienz.
- Zu kurze initialDelaySeconds. Die Anwendung ist noch nicht gestartet, aber Kubernetes prueft schon und killt den Pod. CrashLoopBackoff.
- Identische Liveness- und Readiness-Probes. Die Liveness-Probe soll pruefen: "Laeuft der Prozess noch?" Die Readiness-Probe soll pruefen: "Kann der Prozess Requests beantworten?" Das sind zwei verschiedene Fragen.
Best Practices:
livenessProbe:
httpGet:
path: /healthz # Prueft nur den Prozess selbst, keine Dependencies
port: 8080
initialDelaySeconds: 15 # Genug Zeit zum Starten
periodSeconds: 10
failureThreshold: 3 # Drei Fehlversuche bevor der Pod gekillt wird
timeoutSeconds: 3
readinessProbe:
httpGet:
path: /ready # Prueft Prozess UND kritische Dependencies
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 2 # Schneller reagieren, Pod wird nur aus Service genommen
timeoutSeconds: 3
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30 # 30 * 5s = 150s maximale Startzeit
periodSeconds: 5
Die startupProbe ist seit Kubernetes 1.20 stabil und loest ein altes Problem: Anwendungen mit langer Startzeit. Ohne startupProbe mussten Sie initialDelaySeconds auf der Liveness-Probe hochsetzen, was die Erkennung von tatsaechlich toten Pods verzoegert.
Pattern 4: Circuit Breaker und Retries
Circuit Breaker und Retries sind streng genommen kein Kubernetes-Feature. Sie gehoeren entweder in die Anwendung (z.B. via resilience4j in Java, polly in .NET) oder in ein Service Mesh.
Warum ein Service Mesh sinnvoll sein kann
Ein Service Mesh wie Istio oder Linkerd setzt Circuit Breaker und Retries transparent auf Netzwerk-Ebene um. Der Vorteil: Sie muessen nicht jeden Service einzeln anpassen.
Vergleich der Optionen:
| Ansatz | Vorteile | Nachteile |
|---|---|---|
| In der Anwendung (Libraries) | Volle Kontrolle, kein Infrastruktur-Overhead | Muss in jedem Service implementiert werden |
| Service Mesh (Istio/Linkerd) | Transparent, einheitliche Policy | Zusaetzliche Komplexitaet, Resource-Overhead |
| API Gateway (z.B. Kong, Envoy) | Nur fuer externen Traffic | Deckt Service-zu-Service-Kommunikation nicht ab |
Fuer Cluster mit weniger als 10 Services reicht meist ein anwendungsseitiger Ansatz. Ab 20+ interagierenden Services wird ein Service Mesh wirtschaftlich sinnvoll.
Wer tiefer in das Thema Load Balancing und Traffic Management einsteigen will, findet unter Kubernetes Load Balancing weiterfuehrende Details.
Pattern 5: Chaos Engineering
Chaos Engineering bedeutet nicht "zufaellig Sachen kaputtmachen". Es bedeutet: Hypothesen ueber das Systemverhalten formulieren, kontrolliert Stoerungen einfuegen, beobachten, ob die Hypothese zutrifft.
Einfacher Einstieg mit kubectl:
# Hypothese: "Wenn ein Pod des order-service ausfaellt,
# bemerken Endnutzer keine Unterbrechung."
# Schritt 1: Monitoring oeffnen (Grafana, kubectl top, etc.)
# Schritt 2: Einen Pod loeschen
kubectl delete pod -l app=order-service --field-selector=status.phase=Running \
| head -1
# Schritt 3: Beobachten
# - Wird der Pod automatisch neu erstellt? (Ja, durch das ReplicaSet)
# - Gibt es Fehler in den Logs der anderen Pods?
# - Steigt die Error-Rate im Monitoring?
# - Wie lange dauert es, bis der neue Pod ready ist?
# Schritt 4: Ergebnis dokumentieren
Fuer systematischere Chaos-Tests gibt es Tools wie Litmus, chaos-mesh oder Gremlin. Der Artikel zu Kubernetes Chaos Engineering geht darauf im Detail ein.
Resilienz-Checkliste fuer produktive Cluster
Bevor Sie einen Service als "production-ready" betrachten, sollten diese Punkte erfuellt sein:
| Kategorie | Check | Prioritaet |
|---|---|---|
| Replicas | Mindestens 3 Replicas fuer kritische Services | Hoch |
| Anti-Affinity | Pods auf verschiedene Nodes verteilt | Hoch |
| Probes | Liveness, Readiness und Startup konfiguriert | Hoch |
| PDB | PodDisruptionBudget definiert | Hoch |
| Resource Limits | Requests und Limits fuer CPU und Memory gesetzt | Hoch |
| HPA | Autoscaling fuer variable Workloads konfiguriert | Mittel |
| Topology Spread | Verteilung ueber Availability Zones | Mittel |
| Backups | Persistent Volumes regelmaessig gesichert | Hoch |
| Chaos Tests | Grundlegende Ausfallszenarien getestet | Mittel |
| Runbooks | Incident-Response-Playbooks dokumentiert | Mittel |
Diese Checkliste laesst sich gut in ein CI/CD-Gate integrieren. Tools wie OPA/Gatekeeper oder Kyverno koennen viele dieser Checks automatisiert erzwingen. Fuer Details zur Absicherung der CI/CD-Pipeline empfehle ich den Artikel zu Kubernetes GitOps Security.
Monitoring: Die andere Haelfte der Resilienz
Resilienz-Patterns sind nur so gut wie Ihr Monitoring. Wenn ein Pod stirbt und automatisch neu startet, aber niemand es bemerkt, haben Sie ein Problem, das sich langsam akkumuliert.
Relevante Metriken:
- Pod Restart Count: Steigende Restart-Zahlen deuten auf instabile Pods hin.
- Request Error Rate: Anteil der 5xx-Responses pro Service.
- Request Latency (p50, p95, p99): Steigende Latenz ist oft ein Fruehindikator fuer Probleme.
- PDB Disruptions Allowed: Zeigt an, ob ein Node-Drain aktuell blockiert wuerde.
- Node Conditions: NotReady-Nodes muessen sofort untersucht werden.
Wer seinen Observability Stack noch aufbauen muss, findet unter Kubernetes Observability Stack eine praxisnahe Anleitung.
Haeufige Fehler und wie man sie vermeidet
Fehler 1: Keine Resource Limits setzen. Ohne Limits kann ein einzelner Pod einen ganzen Node auslasten und andere Pods per OOM-Kill beenden. Das ist das "Noisy Neighbor"-Problem. Setzen Sie immer Requests und Limits. Details dazu unter Kubernetes OOM-Kills vermeiden.
Fehler 2: PDBs vergessen. Ihr Service hat drei Replicas und Anti-Affinity -- aber ohne PDB kann ein kubectl drain alle drei Pods gleichzeitig evicten, wenn sie zufaellig auf Nodes liegen, die nacheinander gedrained werden.
Fehler 3: Readiness-Probe fehlt. Ohne Readiness-Probe schickt Kubernetes Traffic an Pods, die noch starten oder deren Dependencies noch nicht bereit sind. Das fuehrt zu Fehlern bei Rolling Updates.
Fehler 4: Zu aggressive Liveness-Probe. periodSeconds: 1 mit failureThreshold: 1 bedeutet: Ein einziger langsamer Health Check toetet den Pod. Bei kurzzeitigen Lastspitzen reisst das die gesamte Anwendung herunter.
Fehler 5: Kein Chaos Testing. Sie wissen nicht, ob Ihr System resilient ist, bis Sie es testen. "Es sollte funktionieren" ist keine Grundlage fuer Produktionsbetrieb.
Fazit
Resilienz in Kubernetes ist kein einzelnes Feature, das man einschaltet. Es ist eine Sammlung von Patterns, die zusammenwirken: Anti-Affinity verteilt Pods, PDBs schuetzen vor zu aggressiven Drains, Probes erkennen fehlerhafte Container, und Chaos Engineering deckt die Luecken auf, die man in der Theorie uebersieht.
Fangen Sie mit den Basics an: Replicas, Probes, Resource Limits, PDB. Das deckt 80% der Ausfallszenarien ab. Die fortgeschrittenen Patterns (Service Mesh, Multi-Region) kommen spaeter, wenn die Grundlagen stehen.
Wenn Sie Unterstuetzung bei der Analyse und Optimierung Ihrer Cluster-Resilienz brauchen, stehen wir Ihnen gern zur Verfuegung unter /kontakt.
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
Kubernetes Deutschland: Retry Pattern für resiliente Systeme
Erfahren Sie, wie das Retry Pattern die Resilienz und Fehlertoleranz von Kubernetes-Anwendungen in Deutschland optimiert. Steigern Sie die Verfügbarkeit Ihrer Systeme und gewährleisten Sie mit intelligenten Wiederholungsstrategien eine robuste Performance auch in anspruchsvollen Umgebungen.
Capacity Planning: Kubernetes-Autoscaling richtig nutzen
HPA, VPA, Cluster Autoscaler und KEDA kombinieren für Capacity Planning in Kubernetes. Mit Praxisbeispielen und Entscheidungshilfe.
Chaos Engineering: Kubernetes-Resilienz mit Litmus
LitmusChaos auf Kubernetes installieren und Chaos-Experimente durchführen. Pod-Delete, Netzwerk-Latenz und Node-Drain testen deine Cluster-Resilienz.
Cluster Autoscaler: Kubernetes-Nodes optimal skalieren
Cluster Autoscaler optimieren mit Expander-Strategien, Scale-Down-Tuning und Priority-Konfiguration für kosteneffiziente Node-Skalierung.
Custom Metrics: Kubernetes-Autoscaling mit Prometheus
HPA mit Custom Metrics aus Prometheus konfigurieren. Prometheus Adapter installieren, Metriken registrieren und Pods nach Requests pro Sekunde skalieren.