5 Self-Healing Patterns für Kubernetes die du kennen solltest

Kubernetes kann sich selbst heilen - wenn du es richtig konfigurierst. Diese 5 Patterns reduzieren deine Incidents um bis zu 60%.

Zurueck zur Uebersicht
10. März 2026
KI-Ops Team
KubernetesBest Practices

Das Problem: Manuelle Intervention

Klassisches Szenario:

  • 3 AM: Pod crasht
  • 3:05 AM: Monitoring alert
  • 3:08 AM: SRE wacht auf
  • 3:15 AM: SRE logged sich ein, prüft logs
  • 3:20 AM: SRE restarts pod
  • 3:21 AM: Service funktioniert wieder

18 Minuten Downtime für etwas, das Kubernetes hätte selbst machen können.

Mit Self-Healing Patterns machen sich deine Systeme selbst gesund – ohne menschliche Intervention. Das ist das Versprechen von Kubernetes, aber die meisten Teams implementieren diese Patterns falsch.

Pattern 1: Liveness Probe (Pod Gesundheit überwachen)

Ein Liveness Probe prüft, ob ein Container noch "lebt" oder "tot" ist. Wenn der Probe scheitert, startet Kubernetes den Container automatisch neu.

apiVersion: v1
kind: Pod
metadata:
  name: api-service
spec:
  containers:
  - name: api
    image: my-api:v1
    ports:
    - containerPort: 8080

    # Liveness Probe: Prüfe alle 10 Sekunden ob /health OK ist
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 30    # Gib dem Container Zeit zu starten
      periodSeconds: 10          # Prüfe alle 10 Sekunden
      timeoutSeconds: 2          # Timeout nach 2 Sekunden
      failureThreshold: 3        # Erst nach 3 Failures restarten

Was der Probe macht:

  1. Alle 10 Sekunden macht Kubernetes einen HTTP GET auf http://localhost:8080/health
  2. Wenn der Container antwortet mit Status 200, alles gut
  3. Wenn die Probe 3x hintereinander fehlschlägt, startet Kubernetes den Container neu
  4. Das alles passiert automatisch ohne menschliches Zutun

Häufiger Fehler: Zu aggressiver Probe

# FALSCH: Restarts den Container sekündlich bei kleinen Problemen
livenessProbe:
  periodSeconds: 1     # 🚫 Zu häufig!
  failureThreshold: 1  # 🚫 Zu streng!

# RICHTIG: Gibt dem Container Zeit sich zu erholen
livenessProbe:
  periodSeconds: 10    # ✅ Alle 10 Sekunden
  failureThreshold: 3  # ✅ Nach 3 Fehlern restarten
  initialDelaySeconds: 30  # ✅ 30s zum Startup

Real-World Beispiel:

# Node.js Express Service
livenessProbe:
  httpGet:
    path: /health
    port: 3000
  initialDelaySeconds: 15
  periodSeconds: 10
  failureThreshold: 3

# In deinem App Code:
app.get('/health', (req, res) => {
  // Prüfe ob Database noch erreichbar ist
  if (db.connection.isConnected) {
    res.status(200).json({ status: 'alive' });
  } else {
    res.status(503).json({ status: 'unhealthy' });
  }
});

Pattern 2: Readiness Probe (Ist der Service bereit für Traffic?)

Unterschied zu Liveness Probe:

  • Liveness: "Lebt der Container noch?" → Restart ihn wenn nicht
  • Readiness: "Kann dieser Container Traffic handlen?" → Gib ihm keinen Traffic wenn nicht
apiVersion: v1
kind: Pod
metadata:
  name: api-service
spec:
  containers:
  - name: api
    image: my-api:v1

    # Readiness: Prüfe ob Service Traffic verarbeiten kann
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5     # Prüfe nach 5 Sekunden
      periodSeconds: 5           # Alle 5 Sekunden
      successThreshold: 1        # Mindestens 1 Success
      failureThreshold: 2        # Nach 2 Fehlern: kein Traffic

Klassisches Scenario:

10:00 - Pod startet
10:00 - Kubernetes fragt Liveness Probe: "Lebst du?" → JA
10:00 - Kubernetes schickt Traffic hin
10:02 - Database Connection Pool wird aufgebaut (dauert 2 Min)
10:02 - Container kann noch keine Database Queries verarbeiten
10:02 - Error Rate 100% weil API noch nicht ready ist

Besser mit Readiness:
10:00 - Pod startet
10:00 - Kubernetes fragt Liveness: "Lebst du?" → JA
10:00 - Kubernetes fragt Readiness: "Kannst du Traffic?" → NEIN (DB Pool noch nicht ready)
10:00 - Kubernetes **schickt keinen Traffic hin**
10:02 - Readiness sagt JA (DB Pool ready)
10:02 - **Jetzt schickt Kubernetes Traffic hin**
10:02 - Error Rate 0% weil alles ready ist

In deinem Code:

// Readiness Endpoint
app.get('/ready', async (req, res) => {
  const checks = {
    database: await db.isConnected(),
    cache: await redis.ping(),
    externalAPI: await checkExternalServiceHealth(),
  };

  if (Object.values(checks).every(c => c === true)) {
    res.status(200).json({ ready: true });
  } else {
    res.status(503).json({ ready: false, details: checks });
  }
});

Pattern 3: Pod Disruption Budgets (PDB)

Wenn Kubernetes dein Cluster updatet, drains es Nodes – das heißt, es verschiebt Pods auf andere Nodes. Ohne PDB können alle deine Pods gleichzeitig runter gehen.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-service-pdb
spec:
  minAvailable: 2        # Mindestens 2 Replicas müssen immer laufen
  selector:
    matchLabels:
      app: api-service

Was das macht:

  • Wenn dein Cluster 5 api-service Pods hat und Kubernetes updatet
  • Kubernetes versucht, mindestens 2 Replicas laufen zu halten
  • Es stoppt maximal 3 Pods zur gleichen Zeit
  • Dadurch bleibt der Service verfügbar

Scenario ohne PDB:

Before: 5 API Pods laufen
Cluster Update startet
Kubernetes: "Ich stoppe alle 5 Pods, um sie zu updaten"
Alle 5 Pods down
Service hat 100% Downtime für 5 Minuten

Scenario mit PDB (minAvailable: 2):
Before: 5 API Pods laufen
Cluster Update startet
Kubernetes: "Ich muss mindestens 2 behalten"
Stoppt 3 Pods → 2 Pods laufen noch
Traffic geht an die 2 laufenden Pods
3 Pods updaten
3 Pods starten wieder
Deine 2 anderen Pods stoppen
Die anderen 2 updaten und starten
Service hatte ~0% Downtime

Best Practice:

# Für stateless Services
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-pdb
spec:
  minAvailable: 2       # Mindestens 2 müssen laufen
  selector:
    matchLabels:
      tier: api

---
# Für Datenbank oder stateful Services
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: db-pdb
spec:
  minAvailable: 1       # Nur 1 muss laufen (wichtig für Quorum)
  selector:
    matchLabels:
      tier: database

Pattern 4: Horizontal Pod Autoscaling (HPA)

Wenn Last ansteigt, skaliere mehr Pods. Wenn Last sinkt, skaliere weniger.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-service

  minReplicas: 2
  maxReplicas: 10

  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70    # Skaliere wenn CPU > 70%

  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80    # Skaliere wenn Memory > 80%

  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300  # 5 Min. bevor down-scaling
    scaleUp:
      stabilizationWindowSeconds: 0    # Sofort skalieren

Scenario:

10:00 - Traffic normal: 2 Pods laufen
10:05 - Black Friday Sale startet: Traffic 10x
10:06 - CPU erreicht 75%
10:07 - HPA sieht das, erstellt 2 neue Pods
10:08 - 4 Pods laufen, Traffic besser verteilt
10:09 - CPU sinkt auf 65%, alles gut
11:00 - Sale vorbei, Traffic normal
11:05 - CPU unter 70%, HPA startet Downscaling
11:10 - Nur noch 2 Pods (sparen Kosten)

Häufiger Fehler:

# FALSCH: Zu aggressive Thresholds
metrics:
- resource:
    name: cpu
    target:
      averageUtilization: 30  # 🚫 Skaliert ständig rauf und runter

# RICHTIG: Vernünftige Thresholds
metrics:
- resource:
    name: cpu
    target:
      averageUtilization: 70  # ✅ Gibt dir noch Buffer

Pattern 5: Resource Limits und Requests

Resource Limits verhindern, dass ein Pod alle Ressourcen des Nodes aufbraucht und andere Pods erstickt.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-service
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: api
        image: my-api:v1

        # Request: Was der Pod mindestens braucht
        # Kubernetes schedulet auf einen Node mit genug Platz
        resources:
          requests:
            cpu: 250m           # 250 milliCPU = 1/4 CPU
            memory: 256Mi       # 256 MB

        # Limit: Maximum was der Pod nutzen darf
        # Wenn Pod über Limit geht, wird er killed
          limits:
            cpu: 500m           # Maximum 500 milliCPU
            memory: 512Mi       # Maximum 512 MB

Scenario ohne Limits:

10:00 - Pod hat Memory Leak, nutzt immer mehr Memory
10:15 - Pod nutzt 90% des Node Memory
10:16 - Andere Pods können nicht starten
10:17 - Cluster ist praktisch down
10:30 - SRE findet das Leak

Scenario mit Limits (512Mi):
10:00 - Pod hat Memory Leak
10:05 - Pod nutzt 512Mi (= Limit)
10:06 - Kubernetes killed den Pod (OOMKilled)
10:07 - Kubernetes startet neuen Pod Replica
10:08 - Neue Instanz läuft, alte war weg
10:09 - SRE sieht die OOMKilled Events und findet das Problem
Downtime: ~1-2 Minuten statt 30 Minuten

Best Practices für Limits:

# Node hat 4 CPUs, 16GB RAM
# Du planst 5 Pods darauf

# Pro Pod
requests:
  cpu: 700m    # 5 × 700m = 3500m = 3.5 CPUs (unter 4)
  memory: 2Gi  # 5 × 2Gi = 10Gi (unter 16Gi)
limits:
  cpu: 1000m   # Gib etwas Buffer
  memory: 3Gi

Wie KI-Ops damit hilft

KI-Ops kann detektieren, wenn deine Self-Healing Patterns falsch konfiguriert sind:

ki-ops validate --namespace production

# Output:
❌ api-service: Keine Liveness Probe
   Empfehlung: Füge /health Endpoint mit Liveness Probe hinzu

❌ api-service: Memory Limit zu klein (256Mi)
   Aktueller Verbrauch: ~450Mi durchschnittlich
   Empfehlung: Erhöhe auf 512Mi um OOMKills zu vermeiden

⚠️  api-service: Nur 1 Replica, aber PDB sagt minAvailable: 1
   Empfehlung: Erhöhe Replicas auf mindestens 2 für HA

✅ api-service: HPA und Resource Limits richtig konfiguriert

Messbare Vorteile

Mit allen 5 Patterns:

| Metrik | Vorher | Nachher | Verbesserung | |--------|--------|---------|------------| | Unerwarteter Downtime | 20h/Monat | 2h/Monat | 90% weniger | | Manuelles Restarten | 40x/Monat | 0x/Monat | Automatisch | | MTTR | 45 Min | 5 Min | 89% schneller | | SRE Time für Ops | 80h/Monat | 10h/Monat | 88% weniger Toil | | Cluster Update Downtime | 30 Min | 0 Min | Völlig seamless |

Das Checkliste

Für jeden Production Service:

  • [ ] Liveness Probe (prüft ob Container lebt)
  • [ ] Readiness Probe (prüft ob Container Traffic kan)
  • [ ] Resource Requests gesetzt (scheduling)
  • [ ] Resource Limits gesetzt (no noisy neighbors)
  • [ ] HPA konfiguriert (auto-scale)
  • [ ] PDB mit minAvailable (cluster updates)
  • [ ] mindestens 2 Replicas (High Availability)

Wenn all das gesetzt ist, ist dein Service 99.9% selbst-heilend.


Nächster Schritt: Nutze KI-Ops um diese Patterns in deinem Cluster zu überprüfen.

Fragen oder Feedback?

Schreib uns – wir freuen uns ueber technische Diskussionen.

Kontakt aufnehmen