Veröffentlicht am

CrashLoopBackOff beheben: Logs, Probes, Exit-Code

Teilen:
Authors

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

StatusWas passiertErster Blick
CrashLoopBackOffContainer lief und ist beendetlogs --previous, Exit-Code
ImagePullBackOffImage kommt nicht auf den NodeEvents: unauthorized, not found
CreateContainerConfigErrorConfigMap oder Secret fehltEvents, bevor der Prozess startet
PendingPod ist nicht geschedultPod 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

CodeBedeutungTypische Ursache
0Prozess endet „erfolgreich“RestartPolicy Always startet ihn trotzdem neu. Der Prozess darf nicht von selbst enden.
1AnwendungsfehlerFehlende Env, falsche Config, Exception beim Start
127Befehl nicht gefundencommand oder Entrypoint zeigt auf eine Binary, die im Image nicht existiert
137SIGKILLOOMKilled oder Liveness-Probe. Reason im describe entscheidet
139SIGSEGVDefektes 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