debugging 9 min Lesezeit ·

CrashLoopBackOff systematisch fixen: 7 Ursachen, 1 Workflow

Die 7 häufigsten Ursachen für CrashLoopBackOff - mit kubectl-Befehlen, echten Outputs und einem Decision-Tree, der jede Ursache in unter 5 Minuten findet.

Clemens Christen
Clemens Christen Certified Kubernetes Administrator (CKA)

TL;DR - CrashLoopBackOff ist kein Bug, sondern ein Zustand: der Container ist gestartet, abgestürzt und wartet auf den nächsten Restart-Versuch. Die Ursache liegt nie in Kubernetes - immer im Container, im Manifest oder in der Umgebung. Dieser Workflow findet 90% aller Ursachen in unter 5 Minuten: Exit-Code lesen, vorherige Logs ansehen, Events prüfen, dann gezielt die häufigste der 7 Ursachen testen.

Was CrashLoopBackOff wirklich bedeutet

Der Begriff verwirrt mehr Engineers als nötig. CrashLoopBackOff heißt:

  1. Kubernetes hat den Container gestartet
  2. Der Container ist mit einem Exit-Code != 0 terminiert
  3. Kubelet hat versucht, ihn neu zu starten
  4. Wieder Crash
  5. Kubelet wartet jetzt mit exponentiellem Backoff bis zum nächsten Versuch (10s, 20s, 40s, 80s, … bis maximal 5 Minuten)

Der Container läuft also gar nicht. Die Logs des aktuellen Versuchs sind leer, weil noch kein Restart passiert ist. Sie brauchen die Logs des vorherigen Crashs - das ist die wichtigste Erkenntnis für alles, was folgt.

Der 3-Schritt-Workflow

Egal welche Ursache: Diese drei Befehle laufen immer zuerst.

Schritt 1: Exit-Code lesen

kubectl describe pod <name>

Scrolle zum Bereich Last State:

Last State:     Terminated
  Reason:       Error
  Exit Code:    137
  Started:      Mon, 04 May 2026 14:20:15 +0200
  Finished:     Mon, 04 May 2026 14:20:18 +0200

Der Exit-Code ist die wichtigste Information:

Exit-CodeBedeutung
0Sauberer Exit (sollte nicht in CrashLoop landen, prüfen Sie restartPolicy)
1Generic application error - Logs lesen
2Misuse of shell builtins - meist Tippfehler im Command
126Command not executable - Permission-Problem
127Command not found - falscher Pfad oder fehlende Binary
137SIGKILL - meist OOMKilled (siehe Reason)
139SIGSEGV - Segmentation Fault, native Code hat gecrashed
143SIGTERM - sauber beendet von außen, prüfen Sie Liveness-Probe

Schritt 2: Vorherige Logs lesen

kubectl logs <pod> --previous

Der --previous Switch ist nicht optional. Ohne ihn sehen Sie die Logs des aktuellen (noch nicht gestarteten) Containers - also nichts. Mit ihm sehen Sie die Logs des letzten Crashs.

Schritt 3: System-Events prüfen

kubectl get events --sort-by=.lastTimestamp -n <namespace> | tail -20

System-Events zeigen Dinge, die der Container selbst nicht loggen kann: OOMKilled durch Memory-Limit, FailedMount bei Volumes, BackOff-Counts.

Die 7 häufigsten Ursachen

1. Application Error (Exit-Code 1)

Häufigste Ursache überhaupt. Der Code wirft eine Exception beim Start. Ursachen:

  • Fehlende oder falsche Environment-Variable
  • Datenbank nicht erreichbar (typisches Race-Condition-Symptom)
  • Migrations-Skript schlägt fehl
  • Config-Datei existiert nicht oder hat falsches Format

Fix-Workflow: kubectl logs <pod> --previous, Exception lesen, beheben. Bei DB-Race-Conditions: initContainer mit wait-for-db davor.

2. OOMKilled (Exit-Code 137, Reason: OOMKilled)

Container hat das Memory-Limit überschritten. Kernel hat ihn mit SIGKILL beendet.

kubectl describe pod <name> | grep -A 2 "Last State"
# Reason: OOMKilled
# Exit Code: 137

Fix: Memory-Limit erhöhen oder Memory-Leak im Code finden. Das Limit verdoppeln ist Symptom-Kosmetik - bei echten Leaks crasht der Pod nur später wieder. kubectl top pod zeigt den realen Verbrauch live.

resources:
  requests:
    memory: "256Mi"
  limits:
    memory: "512Mi"  # nach echtem Bedarf, nicht nach Bauchgefühl

3. Liveness-Probe schlägt fehl (Exit-Code 143, oft mit leeren Logs)

Die Liveness-Probe schlägt fehl, Kubelet beendet den Container mit SIGTERM. Wenn die Probe schon beim ersten Run fehlschlägt, sehen Sie meist gar keine Logs.

Klassischer Fail: initialDelaySeconds ist zu niedrig. Eine Spring-Boot-App braucht 30-60s zum Starten, die Probe feuert nach 10s und tötet den Container.

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 60   # statt 10
  periodSeconds: 10
  failureThreshold: 3

Diagnose:

kubectl describe pod <name> | grep -A 5 "Liveness"
kubectl get events | grep -i "liveness"
1-Tag Intensiv-Workshop

Kubernetes Debugging - systematisch statt raten

Echte Production-Incidents nachstellen, kubectl-Workflows verinnerlichen, Root-Causes in Minuten finden.

Workshop-Details ansehen

4. Command not found (Exit-Code 127)

Der Container-Image hat den im Manifest angegebenen Command nicht. Oder der Pfad ist falsch:

command: ["/usr/local/bin/myapp"]   # existiert das wirklich?

Schneller Test:

kubectl debug -it <pod> --image=busybox --target=<container>
# im debug container:
ls /proc/1/root/usr/local/bin/

Mit dem ephemeral debug container teilen Sie den Filesystem-Namespace und können sehen, was der Original-Container an Pfaden tatsächlich hatte.

5. ConfigMap oder Secret fehlt (Exit-Code 1, oft mit “no such file”)

Pod-Manifest mounted eine ConfigMap, die nicht existiert. Container startet, findet die Datei nicht, crasht.

kubectl get configmap -n <namespace>
kubectl get secret -n <namespace>

Häufige Ursache: Namespace-Verwechslung. Pod ist in prod, ConfigMap ist in default.

6. Falsche Permissions auf Volume (Exit-Code 1, “permission denied”)

Mounted PV hat UID/GID, die der Container-User nicht lesen darf. Tritt häufig bei Migration von Docker-Compose nach Kubernetes auf.

Fix: securityContext.fsGroup setzen, damit Kubelet beim Mount die Permissions anpasst:

spec:
  securityContext:
    fsGroup: 1000
  containers:
    - name: app
      image: ...

7. Race Condition gegen Datenbank (Exit-Code 1, “connection refused”)

Die App startet vor der Datenbank, kann sich nicht verbinden, crasht. Der Restart trifft die DB jetzt vielleicht - oder nicht.

Fix: initContainer mit Wait-Skript:

initContainers:
  - name: wait-for-db
    image: busybox:1.36
    command: ['sh', '-c', 'until nc -zv postgres 5432; do echo waiting for db; sleep 2; done']

Oder besser: Application-Level-Retry mit Exponential Backoff direkt im Code. initContainer ist das Pflaster, nicht die Lösung.

Decision Tree

Exit-Code 137 + Reason OOMKilled?  →  Ursache 2 (Memory)
                                  ↓ nein
Logs --previous komplett leer?     →  Ursache 3 (Liveness-Probe)
                                  ↓ nein
Logs zeigen "no such file"?        →  Ursache 5 (ConfigMap/Secret)
                                  ↓ nein
Logs zeigen "permission denied"?   →  Ursache 6 (Volume-Permissions)
                                  ↓ nein
Logs zeigen "command not found"?   →  Ursache 4 (Command/Pfad)
                                  ↓ nein
Logs zeigen "connection refused"?  →  Ursache 7 (Race Condition)
                                  ↓ nein
                                       Ursache 1 (Application Error)
                                       → Logs gründlich lesen, ggf. Stacktrace

Was die Workshops nicht ersetzen

Dieser Workflow löst die häufigsten Fälle. Was nicht in den 7 Ursachen steckt:

  • JVM-Container mit verstecktem OOM: der Java-Heap explodiert, aber Kernel sieht’s nicht als OOM. Sie sehen nur Exit-Code 1 mit Killed.
  • Network-Policy blockiert Init-Egress: App will beim Start Configs vom Vault holen, NetworkPolicy lässt nur Inbound zu, App crasht ohne Log.
  • Cluster-Autoscaler killt Node während Pod-Start: Pod wird vor Liveness-Probe von Node evicted, Restart auf neuem Node.

Diese Pattern brauchen mehr als Kommando-Reihenfolge - sie brauchen System-Verständnis. Genau das macht den Unterschied zwischen “raten und probieren” und “in 3 Minuten die Root Cause finden”.

Wie es weitergeht

Im Kubernetes Debugging Workshop spielen wir 8 echte Production-Incidents nach - inklusive der drei oben genannten Edge Cases - und drillen den Workflow, bis er sitzt. 1 Tag, 8 Stunden, danach lösen Sie CrashLoopBackOff systematisch und nicht durch Raten.

Bevor Sie buchen: Schauen Sie sich auch unseren kubectl Debugging Cheatsheet an - dort gibt es die 12 wichtigsten Befehle als kompletten Workflow.

1-Tag Intensiv-Workshop

Kubernetes Debugging - systematisch statt raten

Echte Production-Incidents nachstellen, kubectl-Workflows verinnerlichen, Root-Causes in Minuten finden.

Workshop-Details ansehen
Kostenfrei · 30 Minuten

Brauchen Sie eine zweite Meinung zu Ihrem Cluster?

Buchen Sie einen kostenfreien 30-Minuten Kubernetes Health-Check. Wir schauen uns Ihr Setup an und geben konkrete Hinweise - ohne Verkaufsgespräch.

Termin buchen