- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Circuit Breaker: Resilienz-Patterns fuer Microservices
TL;DR
- Circuit Breaker verhindern kaskadierende Ausfaelle, indem sie Anfragen an ungesunde Services fruehzeitig abbrechen -- statt den gesamten Cluster in Mitleidenschaft zu ziehen.
- Istio/Envoy implementiert Circuit Breaking ueber DestinationRules mit Outlier Detection und Connection Pool Limits.
- Retry-Policies gehoeren auf die Infrastrukturebene (Service Mesh), nicht in den Anwendungscode -- dadurch wird die Konfiguration zentral steuerbar.
- Das Bulkhead-Pattern isoliert Failure Domains, sodass ein ueberlasteter Service nicht alle anderen blockiert.
- Die Kombination aus Circuit Breaker, Timeout, Retry und Bulkhead bildet eine vollstaendige Resilienz-Strategie.
Warum Microservices ohne Circuit Breaker gefaehrlich leben
In einer Microservice-Architektur haengt die Verfuegbarkeit des Gesamtsystems von jedem einzelnen Service ab. Wenn Service B langsam antwortet, stauen sich Requests in Service A. Service A verbraucht alle Threads und kann auch Anfragen an Service C nicht mehr bearbeiten. Innerhalb von Minuten ist der gesamte Cluster betroffen.
Dieses Muster heisst kaskadierender Ausfall und ist die haeufigste Ursache fuer grossflaechige Ausfaelle in verteilten Systemen.
Ohne Circuit Breaker:
Client */} Service A */} Service B (langsam/tot)
|
+*/} Thread-Pool voll
|
+*/} Service A wird unresponsive
|
+*/} Client-Timeout */} Gesamtausfall
Mit Circuit Breaker:
Client */} Service A */} Circuit Breaker */} OPEN
|
+*/} Sofortige Fehlerantwort (503)
|
+*/} Service A bleibt funktionsfaehig
|
+*/} Client erhaelt schnelle Antwort
Die vier Resilienz-Patterns
1. Circuit Breaker
Der Circuit Breaker hat drei Zustaende:
| Zustand | Verhalten | Uebergang |
|---|---|---|
| Closed | Alle Anfragen werden durchgelassen | Oeffnet bei Fehlerquote ueber Schwellwert |
| Open | Alle Anfragen werden sofort abgelehnt | Wechselt nach Timeout zu Half-Open |
| Half-Open | Begrenzte Anzahl Probe-Requests | Schliesst bei Erfolg, oeffnet bei Fehler |
2. Timeout
Jeder ausgehende Request braucht ein explizites Timeout. Ohne Timeout wartet ein Service potenziell unendlich auf eine Antwort.
3. Retry
Fehlgeschlagene Requests werden automatisch wiederholt -- aber nur bei transienten Fehlern (5xx, Connection Reset), nie bei Client-Fehlern (4xx).
4. Bulkhead
Ressourcen werden pro Abhaengigkeit isoliert. Ein separater Thread-Pool oder Connection-Pool pro Service verhindert, dass eine langsame Abhaengigkeit alle Ressourcen aufbraucht.
Circuit Breaker mit Istio/Envoy
Istio implementiert Circuit Breaking ueber zwei Mechanismen in der DestinationRule:
- Connection Pool Settings: Begrenzen die maximale Anzahl gleichzeitiger Verbindungen
- Outlier Detection: Erkennt ungesunde Endpoints und entfernt sie temporaer
Grundlegende DestinationRule
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: order-service-resilience
namespace: production
spec:
host: order-service.production.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
connectTimeout: 5s
http:
h2UpgradePolicy: DEFAULT
http1MaxPendingRequests: 50
http2MaxRequests: 200
maxRequestsPerConnection: 10
maxRetries: 3
outlierDetection:
consecutive5xxErrors: 3
interval: 10s
baseEjectionTime: 30s
maxEjectionPercent: 50
minHealthPercent: 30
connectionPool erklaert:
maxConnections: 100-- Maximal 100 gleichzeitige TCP-Verbindungen zu diesem Servicehttp1MaxPendingRequests: 50-- Maximal 50 Requests in der Warteschlangehttp2MaxRequests: 200-- Maximal 200 gleichzeitige HTTP/2-RequestsmaxRequestsPerConnection: 10-- Nach 10 Requests wird die Verbindung geschlossen und neu aufgebaut
outlierDetection erklaert:
consecutive5xxErrors: 3-- Nach 3 aufeinanderfolgenden 5xx-Fehlern wird der Endpoint entferntinterval: 10s-- PruefintervallbaseEjectionTime: 30s-- Minimale Dauer der Entfernung (wird bei wiederholtem Ejection multipliziert)maxEjectionPercent: 50-- Maximal 50% der Endpoints duerfen gleichzeitig entfernt werdenminHealthPercent: 30-- Outlier Detection deaktiviert sich, wenn weniger als 30% der Endpoints gesund sind
Fortgeschrittene Konfiguration pro Subset
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: payment-service-resilience
namespace: production
spec:
host: payment-service.production.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
http:
http1MaxPendingRequests: 25
maxRetries: 2
outlierDetection:
consecutive5xxErrors: 2
interval: 5s
baseEjectionTime: 60s
maxEjectionPercent: 30
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
connectionPool:
http:
http1MaxPendingRequests: 10
- name: v2
labels:
version: v2
trafficPolicy:
connectionPool:
http:
http1MaxPendingRequests: 50
Das erlaubt unterschiedliche Circuit Breaker-Einstellungen fuer verschiedene Versionen eines Service -- nuetzlich bei Canary Deployments. Details zu Deployment-Strategien finden Sie unter Kubernetes Deployment Strategien.
Retry und Timeout mit Istio VirtualService
Retries und Timeouts werden in Istio ueber VirtualServices konfiguriert:
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: order-service-routing
namespace: production
spec:
hosts:
- order-service
http:
- route:
- destination:
host: order-service
port:
number: 8080
timeout: 8s
retries:
attempts: 3
perTryTimeout: 3s
retryOn: "5xx,reset,connect-failure,retriable-4xx"
retryRemoteLocalities: true
Wichtig: Das Gesamt-Timeout muss groesser sein als attempts * perTryTimeout. In diesem Beispiel: 3 Versuche * 3 Sekunden = 9 Sekunden -- das Gesamt-Timeout von 8 Sekunden greift vorher. Passen Sie die Werte entsprechend an:
Empfehlung:
timeout >= attempts * perTryTimeout + Puffer
Beispiel: timeout: 12s, attempts: 3, perTryTimeout: 3s
Retry-Bedingungen im Detail
| Bedingung | Bedeutung |
|---|---|
5xx | Retry bei allen 5xx-Antworten |
reset | Retry bei Connection Reset |
connect-failure | Retry wenn Verbindungsaufbau fehlschlaegt |
retriable-4xx | Retry bei 409 Conflict |
gateway-error | Retry bei 502, 503, 504 |
refused-stream | Retry bei HTTP/2 REFUSED_STREAM |
Bulkhead-Pattern mit Envoy
Das Bulkhead-Pattern in Envoy wird ueber separate Connection Pools pro Upstream-Cluster realisiert. Jeder Service in der DestinationRule hat seinen eigenen Pool:
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: api-gateway-bulkhead
namespace: production
spec:
host: user-service.production.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
http:
http1MaxPendingRequests: 25
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: payment-bulkhead
namespace: production
spec:
host: payment-service.production.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 30
http:
http1MaxPendingRequests: 10
Wenn der payment-service seinen Connection Pool ausschoepft, ist der user-service davon nicht betroffen. Requests an den user-service funktionieren weiterhin normal.
Anwendungsseitige Circuit Breaker
Nicht jedes Team hat ein Service Mesh im Einsatz. Circuit Breaker lassen sich auch auf Anwendungsebene implementieren. Hier ein Beispiel-Pattern:
Go: sony/gobreaker
settings := gobreaker.Settings{
Name: "payment-service",
MaxRequests: 3,
Interval: 10 * time.Second,
Timeout: 30 * time.Second,
ReadyToTrip: func(counts gobreaker.Counts) bool {
failureRatio := float64(counts.TotalFailures) / float64(counts.Requests)
return counts.Requests >= 10 && failureRatio >= 0.5
},
}
cb := gobreaker.NewCircuitBreaker(settings)
result, err := cb.Execute(func() (interface{}, error) {
resp, err := httpClient.Get("http://payment-service/api/charge")
if err != nil {
return nil, err
}
if resp.StatusCode >= 500 {
return nil, fmt.Errorf("server error: %d", resp.StatusCode)
}
return resp, nil
})
Java: Resilience4j
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofSeconds(30))
.slidingWindowSize(10)
.minimumNumberOfCalls(5)
.permittedNumberOfCallsInHalfOpenState(3)
.build();
CircuitBreaker cb = CircuitBreaker.of("paymentService", config);
Try.ofSupplier(CircuitBreaker.decorateSupplier(cb, () -> paymentClient.charge(amount)))
.recover(CallNotPermittedException.class, e -> "Service unavailable");
Health Checks als Grundlage fuer Circuit Breaker
Circuit Breaker funktionieren nur zuverlaessig, wenn Health Checks korrekt konfiguriert sind. Ohne Readiness Probes sendet Kubernetes Traffic an Pods, die noch nicht bereit sind -- und der Circuit Breaker interpretiert die resultierenden Fehler als Service-Ausfall.
Stellen Sie sicher, dass jeder Service eine Readiness Probe definiert, die den tatsaechlichen Zustand der Anwendung widerspiegelt (nicht nur den HTTP-Server-Status). Die korrekte Konfiguration wird in Kubernetes Health Checks und Probes ausfuehrlich behandelt.
Monitoring und Alerting fuer Circuit Breaker
Envoy/Istio Metriken
# Circuit Breaker Overflow-Metriken
kubectl exec -n production deploy/order-service -c istio-proxy -- \
curl -s localhost:15000/stats | grep circuit_breaker
# Wichtige Metriken:
# upstream_rq_pending_overflow -- Requests abgelehnt wegen vollem Pending-Pool
# upstream_cx_pool_overflow -- Connection Pool Overflow
# upstream_rq_retry -- Anzahl der Retries
# upstream_rq_retry_success -- Erfolgreiche Retries
# Outlier Detection Metriken
kubectl exec -n production deploy/order-service -c istio-proxy -- \
curl -s localhost:15000/stats | grep outlier_detection
Prometheus Alerting Rules
Drei Alerts, die in jeder Istio-Installation aktiv sein sollten:
| Alert | PromQL (vereinfacht) | Schwellwert |
|---|---|---|
| CircuitBreakerTripped | rate(envoy_cluster_upstream_rq_pending_overflow[5m]) | Ueber 0.1 fuer 2 Minuten |
| HighOutlierEjections | envoy_cluster_outlier_detection_ejections_active | Mehr als 2 Endpoints ejected fuer 5 Minuten |
| HighRetryRate | rate(upstream_rq_retry[5m]) / rate(upstream_rq_total[5m]) | Ueber 20% fuer 5 Minuten |
Resilienz-Strategie: Alle Patterns kombinieren
Eine vollstaendige Resilienz-Konfiguration kombiniert alle vier Patterns:
# DestinationRule: Circuit Breaker + Bulkhead
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: complete-resilience
namespace: production
spec:
host: critical-service.production.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100 # Bulkhead: TCP-Limit
connectTimeout: 3s # Timeout: Verbindungsaufbau
http:
http1MaxPendingRequests: 50 # Bulkhead: Request-Queue
http2MaxRequests: 200 # Bulkhead: Parallele Requests
maxRetries: 3 # Retry: Max Versuche
outlierDetection:
consecutive5xxErrors: 3 # Circuit Breaker: Fehler-Schwelle
interval: 10s
baseEjectionTime: 30s
maxEjectionPercent: 40
---
# VirtualService: Timeout + Retry
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: critical-service-routing
namespace: production
spec:
hosts:
- critical-service
http:
- route:
- destination:
host: critical-service
port:
number: 8080
timeout: 12s # Timeout: Gesamt
retries:
attempts: 3
perTryTimeout: 3s # Timeout: Pro Versuch
retryOn: "5xx,reset,connect-failure"
Haeufige Fehler und Anti-Patterns
Retries ohne Idempotenz: Retry-Policies funktionieren nur sicher mit idempotenten Operationen. Ein POST-Request, der eine Bestellung erstellt, darf nicht ohne Weiteres wiederholt werden. Verwenden Sie Idempotency-Keys oder beschraenken Sie Retries auf GET-Requests.
Circuit Breaker zu aggressiv: Ein consecutive5xxErrors: 1 fuehrt dazu, dass einzelne sporadische Fehler sofort den Circuit oeffnen. Beginnen Sie mit 3-5 Fehlern und passen Sie basierend auf Beobachtung an.
maxEjectionPercent zu hoch: Bei maxEjectionPercent: 100 kann Outlier Detection alle Endpoints entfernen und den Service komplett unerreichbar machen. Setzen Sie den Wert auf maximal 50%.
Timeout-Kette nicht aufeinander abgestimmt: Wenn der Client ein Timeout von 5s hat, der Gateway ein Timeout von 30s und der Backend-Service ein Timeout von 60s, greift immer das Client-Timeout. Stellen Sie sicher, dass Timeouts von aussen nach innen abnehmen.
Fuer die Absicherung der Kommunikation zwischen Services in einem Service Mesh eignet sich Kubernetes Istio Ambient Mesh als sidecar-freie Alternative.
Fazit
Resilienz in Microservice-Architekturen ist kein optionales Feature -- es ist eine Voraussetzung fuer produktionsfaehige Systeme. Circuit Breaker, Timeout, Retry und Bulkhead bilden zusammen eine Verteidigungslinie gegen kaskadierende Ausfaelle. Istio/Envoy bietet die beste Infrastrukturebene dafuer, aber auch anwendungsseitige Implementierungen mit Resilience4j oder gobreaker sind valide Optionen. Starten Sie mit Timeouts und einfachem Retry, fuegen Sie Outlier Detection hinzu und ueberwachen Sie die Metriken, bevor Sie die Schwellwerte verfeinern.
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
Istio Service Mesh auf Kubernetes einrichten
Istio Service Mesh auf Kubernetes installieren und konfigurieren: Sidecar-Injection, Traffic-Routing mit VirtualService und mTLS zwischen Services.
Resilience Patterns für Kubernetes Microservices
Resilience Patterns für Kubernetes-Microservices: Retry, Circuit Breaker, Bulkhead, Timeout, Health Checks und PDB mit YAML-Konfigurationen.
Kubernetes Retry Pattern mit Istio konfigurieren
Retry-Strategien in Kubernetes mit Istio und Envoy: Exponential Backoff mit Jitter, Idempotenz und Circuit Breaker Integration praxisnah erklärt.
Kubernetes CQRS Pattern Microservices in Deutschland optimal nutzen
Optimieren Sie Skalierbarkeit und Performance Ihrer komplexen Microservices auf Kubernetes in Deutschland mit dem CQRS Pattern. Erfahren Sie, wie diese zukunftsweisende Architektur Compliance-Anforderungen erfüllt und digitale Souveränität für deutsche Unternehmen sichert.
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.