Anomalie-Erkennung in Kubernetes: 5 Patterns, die deine Incidents früh sichtbar machen

Viele Incidents entstehen, weil Anomalien zu spät erkannt werden. Diese 5 Patterns (Liveness Probes, Readiness Probes, Resource Limits, HPA, PDB) zeigen Probleme sofort, damit KI-gestützte Diagnose Ursachen schnell klären kann.

Back to overview
March 10, 2026
Skalenta
KubernetesMonitoring

Das Problem: Invisible Anomalien

Klassisches Szenario:

  • 10:00 — Pod hat Memory-Leak (unbemerkt)
  • 10:15 — Pod nutzt 90% seines Limits (unbemerkt)
  • 10:30 — Pod OOMKilled, crasht
  • 10:31 — Alert feuert (endlich sichtbar)
  • 10:40 — SRE wacht auf, checkt Logs
  • 10:50 — SRE rätselt: "Was hat den OOM verursacht?"
  • 11:05 — Memory erhöht (Symptom behandelt, nicht Ursache)

Die Root Cause (Memory-Leak im Code) bleibt unbehandelt. Incident wiederholt sich in 2 Wochen.

Besserer Weg: Mit Patterns, die Anomalien früh sichtbar machen, können intelligente Diagnose-Tools (wie KI-Ops) Ursachen schnell klären. Dein Team versteht dann: Ist es ein Leak, ein Spike oder ein echtes Feature-Weight-Wachstum?

Pattern 1: Liveness Probes (frühes Erkennen von Deadlocks)

Eine Liveness Probe prüft, ob ein Container noch "lebt". Wenn die Probe fehlschlägt, wird das sichtbar – und KI-Ops kann analysieren, WARUM.

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

    # Liveness Probe: Check every 10 seconds if /health returns OK
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 30    # Give the container time to start
      periodSeconds: 10          # Check every 10 seconds
      timeoutSeconds: 2          # Timeout after 2 seconds
      failureThreshold: 3        # Restart only after 3 consecutive failures

Was die Probe macht:

  1. Alle 10 Sekunden schickt Kubernetes ein HTTP GET an http://localhost:8080/health
  2. Antwortet der Container mit Status 200, ist alles gut
  3. Schlägt die Probe fehl, wird das in kubectl und Prometheus sichtbar
  4. KI-Ops sieht diese Anomalie und analysiert, WARUM die Probe fehlschlägt
    • Deadlock im Code? → Code-Review nötig
    • Abhängigkeit (DB) ist down? → Diagnose für DB-Problem
    • GC stoppt die Welt? → Heap-Analyse nötig

Häufiger Fehler: Probe zu aggressiv

# WRONG: Restarts the container every second for minor issues
livenessProbe:
  periodSeconds: 1     # Too frequent!
  failureThreshold: 1  # Too strict!

# RIGHT: Gives the container time to recover
livenessProbe:
  periodSeconds: 10    # Every 10 seconds
  failureThreshold: 3  # Restart after 3 failures
  initialDelaySeconds: 30  # 30s for startup

Praxisbeispiel:

# Node.js Express service
livenessProbe:
  httpGet:
    path: /health
    port: 3000
  initialDelaySeconds: 15
  periodSeconds: 10
  failureThreshold: 3
// In your app code:
app.get('/health', (req, res) => {
  // Check if the database is still reachable
  if (db.connection.isConnected) {
    res.status(200).json({ status: 'alive' });
  } else {
    res.status(503).json({ status: 'unhealthy' });
  }
});

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

Der Unterschied zu Liveness Probes:

  • Liveness: "Lebt der Container noch?" → Wenn nicht, restart
  • Readiness: "Kann dieser Container Traffic verarbeiten?" → Wenn nicht, schick ihm keinen Traffic
# Readiness: Check if the service can process traffic
readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5     # Check after 5 seconds
  periodSeconds: 5           # Every 5 seconds
  successThreshold: 1        # At least 1 success
  failureThreshold: 2        # After 2 failures: no traffic

Klassisches Szenario ohne Readiness Probe:

10:00 - Pod starts
10:00 - Kubernetes asks Liveness: "Are you alive?" → YES
10:00 - Kubernetes sends traffic
10:02 - Database connection pool is still initializing (takes 2 min)
10:02 - Container can't process database queries yet
10:02 - Error rate 100% because API isn't ready

With Readiness Probe:
10:00 - Pod starts
10:00 - Kubernetes asks Liveness: "Are you alive?" → YES
10:00 - Kubernetes asks Readiness: "Can you handle traffic?" → NO (DB pool not ready)
10:00 - Kubernetes does NOT send traffic
10:02 - Readiness says YES (DB pool ready)
10:02 - Now Kubernetes sends traffic
10:02 - Error rate 0% because everything is ready

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 deinen Cluster updatet, drained es Nodes — und verschiebt Pods auf andere Nodes. Ohne PDB können all deine Pods gleichzeitig untergehen.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-service-pdb
spec:
  minAvailable: 2        # At least 2 replicas must always be running
  selector:
    matchLabels:
      app: api-service

Was es macht:

  • Wenn dein Cluster 5 api-service-Pods hat und Kubernetes updaten muss
  • hält Kubernetes jederzeit mindestens 2 Replicas am Laufen
  • Es stoppt maximal 3 Pods gleichzeitig
  • Der Service bleibt während des Updates verfügbar

Ohne PDB:

Before: 5 API pods running
Cluster update starts
Kubernetes: "I'll stop all 5 pods to update them"
All 5 pods down
Service has 100% downtime for 5 minutes

Mit PDB (minAvailable: 2):

Before: 5 API pods running
Cluster update starts
Kubernetes: "I need to keep at least 2 running"
Stops 3 pods → 2 pods still running
Traffic goes to the 2 running pods
3 pods update and restart
Remaining 2 pods update
Service had ~0% downtime

Best Practice:

# For stateless services
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-pdb
spec:
  minAvailable: 2       # At least 2 must run
  selector:
    matchLabels:
      tier: api

---
# For databases or stateful services
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: db-pdb
spec:
  minAvailable: 1       # Only 1 needs to run (important for quorum)
  selector:
    matchLabels:
      tier: database

Pattern 4: Horizontal Pod Autoscaling (HPA)

Steigt die Last, skaliere hoch. Sinkt die Last, skaliere runter.

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    # Scale when CPU > 70%

  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80    # Scale when memory > 80%

  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300  # Wait 5 min before scaling down
    scaleUp:
      stabilizationWindowSeconds: 0    # Scale up immediately

Szenario:

10:00 - Normal traffic: 2 pods running
10:05 - Black Friday sale starts: traffic 10x
10:06 - CPU reaches 75%
10:07 - HPA detects it, creates 2 new pods
10:08 - 4 pods running, traffic better distributed
10:09 - CPU drops to 65%, everything stable
11:00 - Sale over, traffic returns to normal
11:05 - CPU under 70%, HPA starts downscaling
11:10 - Back to 2 pods (saving costs)

Häufiger Fehler:

# WRONG: Too aggressive thresholds
metrics:
- resource:
    name: cpu
    target:
      averageUtilization: 30  # Scales up and down constantly (flapping)

# RIGHT: Reasonable thresholds
metrics:
- resource:
    name: cpu
    target:
      averageUtilization: 70  # Gives you buffer

Pattern 5: Resource Limits und Requests

Resource Limits verhindern, dass ein einzelner Pod alle Ressourcen eines Nodes frisst und andere Pods aushungert.

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

        resources:
          # Request: Minimum resources the pod needs
          # Kubernetes schedules on a node with enough capacity
          requests:
            cpu: 250m           # 250 milliCPU = 1/4 CPU
            memory: 256Mi       # 256 MB

          # Limit: Maximum the pod is allowed to use
          # If the pod exceeds the limit, it gets killed
          limits:
            cpu: 500m           # Maximum 500 milliCPU
            memory: 512Mi       # Maximum 512 MB

Ohne Limits:

10:00 - Pod has a memory leak, uses more and more memory
10:15 - Pod uses 90% of node memory
10:16 - Other pods can't start
10:17 - Cluster is effectively down
10:30 - SRE finds the leak
Total impact: 30+ minutes

With limits (512Mi):
10:00 - Pod has a memory leak
10:05 - Pod reaches 512Mi (= limit)
10:06 - Kubernetes kills the pod (OOMKilled)
10:07 - Kubernetes starts a new pod replica
10:08 - New instance runs, old one is gone
10:09 - SRE sees OOMKilled events and investigates the root cause
Downtime: ~1-2 minutes instead of 30 minutes

Best Practices für Limits:

# Node has 4 CPUs, 16GB RAM
# You plan 5 pods on it

# Per pod
requests:
  cpu: 700m    # 5 x 700m = 3500m = 3.5 CPUs (under 4)
  memory: 2Gi  # 5 x 2Gi = 10Gi (under 16Gi)
limits:
  cpu: 1000m   # Give some buffer
  memory: 3Gi

Wie KI-Ops Anomalien nutzt

KI-Ops läuft in deiner Infrastruktur (read-only) und nutzt diese Patterns, um Anomalien früh zu erkennen und zu analysieren:

$ ki-ops analyze --namespace production

🔴 api-service: Liveness Probe schlägt fehl (47 Fehler in 10 Min)
   ├─ Ursachen-Hypothesen (priorisiert):
   │  ├─ 92% Konfidenz: Deadlock im Connection-Pool
   │  ├─ 6% Konfidenz: Abhängigkeit (DB) antwortet langsam
   │  └─ 2% Konfidenz: GC-Freeze
   ├─ Logs zeigen: "Connection pool exhausted"
   └─ KI-Empfehlung: Connection-Pool-Größe überprüfen, DB-Queries optimieren

⚠️  api-service: Memory nutzt 87% des Limits (war gestern 45%)
   ├─ Trend: Steigend über 6 Stunden
   ├─ Hypothesen:
   │  ├─ 78% Konfidenz: Memory-Leak in Cache-Layer
   │  ├─ 15% Konfidenz: Höhere Last (legitimate)
   │  └─ 7% Konfidenz: GC-Overhead
   └─ KI-Empfehlung: Heap-Dump vor nächstem OOM, Leak-Analyze

✅ api-service: HPA und Resource Limits passen zusammen
   └─ Schkalierung funktioniert wie erwartet

KI-Ops analysiert Anomalien, präsentiert Hypothesen mit Konfidenz. Dein Team versteht dann, ob sie "HPA scale hochfahren" oder "Code-Leak beheben" müssen.

Messbare Ergebnisse

Mit allen 5 Patterns korrekt konfiguriert + KI-Ops Analyse:

| Metrik | Vorher | Nachher | Verbesserung | |--------|--------|---------|--------------| | MTTD (Alert bis Diagnose) | 30 Min | <5 Min | 85% schneller | | % Incidents mit klarer Root Cause | 30% | 85% | 3x mehr Klarheit | | Repeat-Incidents (gleiche Ursache) | 60% innerhalb 2 Wochen | 10% | 84% weniger Wiederholungen | | SRE-Zeit für Troubleshooting | 80h/Monat | 15h/Monat | 81% weniger Toil | | False-Alert-Rate | 40% | 8% | Weniger Noise |

Die Checkliste

Für jeden Production-Service:

  • [ ] Liveness Probe (prüft, ob der Container lebt)
  • [ ] Readiness Probe (prüft, ob der Container Traffic verarbeiten kann)
  • [ ] Resource Requests gesetzt (fürs Scheduling)
  • [ ] Resource Limits gesetzt (keine noisy neighbors)
  • [ ] HPA konfiguriert (Auto-Scaling)
  • [ ] PDB mit minAvailable (Cluster-Updates)
  • [ ] Mindestens 2 Replicas (High Availability)

Wenn das alles gesetzt ist, ist dein Service zu 99,9% self-healing.


Nächster Schritt: Zeig mir deine Cluster-Anomalien – KI-Ops analysiert sie in Echtzeit, ohne invasiv zu sein. Demo buchen und sieh, wie Root-Cause-Analyse deine Incident-Response revolutioniert.

Questions or feedback?

Drop us a line – we love technical discussions.

Get in Touch