- Authors

- Name
- Phillip Pham
- @ddppham
CrashLoopBackOff beheben: Logs, Exit-Code und Probes
TL;DR
CrashLoopBackOff heißt: der Container startet, beendet sich, und das Kubelet wartet vor dem nächsten Versuch immer länger. Der Prozess ist schon tot. Lesen Sie deshalb den vorherigen Lauf, nicht den aktuellen:
kubectl logs POD -c CONTAINER --previous
kubectl describe pod POD
In describe steht unter Last State der Exit-Code. 1 ist ein Anwendungsfehler, 137 mit Reason OOMKilled ist Speicher, 139 ist ein Segmentation Fault. Zieht das Image gar nicht, ist es kein Crash, sondern ImagePullBackOff.
Crash und Image-Pull auseinanderhalten
| Status | Was passiert | Erster Blick |
|---|---|---|
| CrashLoopBackOff | Container lief und ist beendet | logs --previous, Exit-Code |
| ImagePullBackOff | Image kommt nicht auf den Node | Events: unauthorized, not found |
| CreateContainerConfigError | ConfigMap oder Secret fehlt | Events, bevor der Prozess startet |
| Pending | Pod ist nicht geschedult | Pod Pending |
Restart Count steigt nur, wenn der Container wirklich gestartet wurde. Bleibt der Zähler bei 0, ist der Prozess nie gelaufen.
Die drei Befehle, in dieser Reihenfolge
kubectl get pod POD -o wide
kubectl describe pod POD
kubectl logs POD -c CONTAINER --previous --tail=100
describe liefert Reason und Exit-Code des letzten Laufs. --previous zeigt die Logs genau dieses Laufs. Ohne --previous sehen Sie oft nur den neuen Versuch, der noch keine Zeile geschrieben hat. Bei mehreren Containern ohne -c verweigert kubectl den Befehl. Der Containername steht in kubectl get pod POD -o jsonpath='{.spec.containers[*].name}'.
Exit-Codes, die den Fix vorgeben
| Code | Bedeutung | Typische Ursache |
|---|---|---|
| 0 | Prozess endet „erfolgreich“ | RestartPolicy Always startet ihn trotzdem neu. Der Prozess darf nicht von selbst enden. |
| 1 | Anwendungsfehler | Fehlende Env, falsche Config, Exception beim Start |
| 127 | Befehl nicht gefunden | command oder Entrypoint zeigt auf eine Binary, die im Image nicht existiert |
| 137 | SIGKILL | OOMKilled oder Liveness-Probe. Reason im describe entscheidet |
| 139 | SIGSEGV | Defektes Binary, falsche Architektur (amd64-Image auf arm64) |
Reason OOMKilled ist eindeutig Speicher. Reason Error bei Code 137 ist meist die Liveness-Probe: das Kubelet schickt SIGKILL, wenn der Check nach failureThreshold weiter fehlschlägt.
Fünf Ursachen, die fast jeden Fall erklären
Der Prozess beendet sich. Ein Job, ein Migrationsskript oder ein Shell-Einzeiler gehört nicht in ein Deployment mit restartPolicy: Always. Dafür ist ein Job da. Im Deployment muss der Prozess im Vordergrund laufen und offen bleiben.
Pflicht-Umgebung fehlt. Die Anwendung loggt eine Zeile und geht mit Code 1 raus. Steht der Name der Variable in --previous, ist der Fix ein Secret oder eine ConfigMap, nicht ein höheres Replikat.
Falsche Architektur. exec format error im Log, Exit 139 oder 1. Das Image ist für eine andere CPU gebaut als der Node. kubectl get pod POD -o wide zeigt den Node, kubectl get node NODE -o wide die Architektur.
Liveness zu scharf. initialDelaySeconds kürzer als die Startzeit, oder ein HTTP-Check auf einem Port, der erst nach dem Migrationslauf zuhört. Die Probe killt einen gesunden Start, der Restart kommt nie über den Delay hinaus. Readiness darf fehlschlagen, Liveness nicht während des Starts. Dafür gibt es startupProbe.
Speicherlimit unter dem Bedarf. Siehe Exit Code 137. Ein höheres Replica-Count ändert daran nichts. Jede Replica trifft dasselbe Limit.
Was den Loop nicht beendet
kubectl delete pod erzeugt nur einen neuen Versuch. replicas: 0 und wieder hochfahren auch. Solange Image, Befehl, Env und Limits gleich bleiben, ist der nächste Pod im selben Zustand.
Backoff ist Absicht: 10s, 20s, 40s, bis fünf Minuten. Wer in der Wartezeit am Deployment schraubt, mischt alte und neue Ursachen. Ein Change, dann describe, dann --previous.
Quellen
📖 Verwandte Artikel
Weitere interessante Beiträge zu ähnlichen Themen
Exit Code 1: die erste Zeile im Previous-Log
Exit Code 1 auf Kubernetes: die Anwendung beendet sich selbst. kubectl logs --previous zeigt die Zeile. Speicher, Image-Pull und SIGKILL sind andere Codes.
Pod startet nicht: Status lesen, dann der Fix
Pod startet nicht: ein kubectl get pod, dann der Status. Pending, ImagePull, CrashLoop, Evicted und die Befehle, die den jeweiligen Fehler wirklich zeigen.
Pod Terminating hängt: Finalizer entfernen
Pod Terminating hängt: Finalizer finden, Grace-Period abwarten, Force-Delete nur wenn der Node weg ist. Der kubectl-Patch, und wann er ein Volume beschädigt.
kubectl connection refused 6443 beheben
kubectl connection refused auf Port 6443: der API-Server antwortet nicht. kubeconfig, Kontext, Firewall, API-Prozess. Der Pod-Status kommt erst danach.
Error from server Forbidden: RBAC-Recht
kubectl Forbidden: Error from server (Forbidden) nennt User, Verb und Ressource. kubectl auth can-i zeigt das Recht, bevor jemand cluster-admin vergibt.
CreateContainerConfigError: Secret und ConfigMap
CreateContainerConfigError: fehlendes Secret, falscher Key oder Namespace. Der Container startet nicht, logs --previous bleibt leer. Das Event nennt das Objekt.
Exit Code 143: SIGTERM und Graceful Shutdown
Exit Code 143 ist SIGTERM: 128 plus 15. Beim Rollout ist das normal. Im Loop fehlt ein Handler oder die Grace-Period ist kürzer als der Stopp der Anwendung.
ImagePullBackOff beheben: Auth, Name, Limit
ImagePullBackOff beheben: Image-Name, imagePullSecrets und Registry-Rate-Limits. Welches Event den Unterschied macht und wann es kein CrashLoopBackOff ist.