Layer 8Ehrlicher Tech-Support
SoftwareSchweregrad: LästigCrashLoopBackOff

Kubernetes: Pod in CrashLoopBackOff

CrashLoopBackOff ist kein Fehler von Kubernetes, sondern die Meldung, dass dein Container beim Start abbricht. So kommst du an die Ursache.

Aufwand:
ca. 20 Min.
Voraussetzung:
kubectl, Lesezugriff auf den Namensraum
Gilt für:
Kubernetes (Standardverhalten des kubelet)

Das Symptom

Der Pod steht in der Übersicht auf CrashLoopBackOff, die Spalte mit den Neustarts zählt munter weiter, und die Anwendung ist nie erreichbar. Wer kubectl logs aufruft, bekommt entweder gar nichts oder eine Fehlermeldung, dass der Container gerade nicht läuft. Und je länger man zusieht, desto träger wird das Ganze: Anfangs versucht es der Pod im Sekundentakt, später vergehen Minuten zwischen zwei Versuchen.

Die „Layer 8“-Wahrheit

CrashLoopBackOff ist keine Fehlfunktion von Kubernetes. Es ist ein Lagebericht, und zwar ein erstaunlich präziser: Dein Container startet, bricht ab, startet wieder und bricht wieder ab – und weil das kubelet nicht bereit ist, den Knoten deswegen mit tausend Startversuchen pro Minute zu beschäftigen, wartet es zwischen den Versuchen jedes Mal länger. Die Dokumentation nennt die Reihe ausdrücklich: 10 Sekunden, 20, 40, und so weiter, gedeckelt bei 300 Sekunden, also fünf Minuten. Läuft der Container zehn Minuten am Stück fehlerfrei, wird der Zähler zurückgesetzt. Das ist kein Defekt, das ist eine Bremse.

Der eigentliche Denkfehler sitzt eine Ebene höher, nämlich beim Wort „Logs“. Der naheliegende Griff nach kubectl logs zeigt den laufenden Container – und der ist im Wartefenster schlicht nicht vorhanden. Es sieht also so aus, als schwiege die Anwendung, dabei hat sie bei jedem einzelnen Todesfall etwas hinterlassen. Man muss nur den vorherigen Durchlauf anfordern. Genau dafür existiert --previous, und genau dieser eine Schalter trennt die Leute, die eine Stunde ratlos auf ein leeres Terminal starren, von denen, die nach dreißig Sekunden die fehlende Umgebungsvariable in der Hand halten.

Der Rest ist unspektakulär. Die Dokumentation zählt die üblichen Verdächtigen nüchtern auf: Fehler in der Anwendung, falsche oder fehlende Konfiguration, zu knapp bemessener Speicher, fehlschlagende Health-Checks, überempfindliche Liveness- oder Startup-Probes. Kubernetes hat keinen dieser Fehler gemacht. Es meldet ihn nur hartnäckiger, als es einem lieb ist – und in wachsenden Abständen, damit man Zeit hat, darüber nachzudenken.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Status und Zahl der Neustarts ablesen

    Zuerst die nüchterne Übersicht. Die Spalte RESTARTS zeigt, wie oft es das kubelet schon versucht hat, die Spalte STATUS den Zustand. Eine dreistellige Zahl bedeutet: Das Problem besteht seit Stunden und niemand hat hingesehen.

    kubectl get pods
    
  2. 2.

    Zustand und Ereignisse des Pods lesen

    Der eine Befehl, mit dem laut Kubernetes-Dokumentation jede Pod-Fehlersuche beginnt. Er zeigt den Zustand jedes Containers samt Grund sowie die letzten Ereignisse – dort steht, ob überhaupt gestartet wurde, wann und mit welchem Ergebnis er endete.

    kubectl describe pod POD-NAME
    
  3. 3.

    Die Logs des vorherigen Durchlaufs holen

    Hier steht in aller Regel die Antwort: die letzte Ausgabe, bevor der Container starb. Ohne diesen Schalter sieht man den aktuellen – oft noch gar nicht existierenden – Durchlauf und damit nichts. Bei mehreren Containern im Pod den gewünschten mit -c benennen.

    kubectl logs POD-NAME --previous
    kubectl logs POD-NAME -c CONTAINER-NAME --previous
    
  4. 4.

    Grund und Exit-Code des letzten Laufs auslesen

    Der vollständige Zustand als YAML enthält unter lastState.terminated den Grund und den Exit-Code der letzten Beendigung. Steht dort OOMKilled, ist es kein Programmfehler, sondern das Speicherlimit. Steht dort ein Exit-Code ungleich null, hat sich die Anwendung selbst beendet.

    kubectl get pod POD-NAME -o yaml
    
  5. 5.

    Die Ereignisse gezielt nach Warnungen filtern

    Ereignisse sind flüchtig, aber aussagekräftig: fehlgeschlagene Probes, nicht einhängbare Volumes, abgelehnte Images. Der Befehl zeigt sie für genau diesen Pod, bei Bedarf beschränkt auf Warnungen.

    kubectl events --for pod/POD-NAME
    kubectl events --types=Warning
    
  6. 6.

    Die gefundene Ursache beheben, nicht den Zustand

    Fehlende Umgebungsvariable, falscher Pfad, nicht erreichbare Datenbank, zu kleines Speicherlimit, zu strenge Liveness-Probe: Erst wenn der Container einen vollen Durchlauf übersteht, hört die Schleife auf. Nach zehn Minuten fehlerfreiem Lauf setzt das kubelet die Wartezeit ohnehin selbst zurück – ein Löschen des Pods ist dafür nicht nötig.

Häufige Fragen (FAQ)

?Warum sind die Logs leer, obwohl der Pod im Sekundentakt abstürzt?

Weil `kubectl logs` standardmäßig den aktuellen Durchlauf zeigt – und der existiert gerade gar nicht. Der Container ist tot, der Ersatz wartet noch auf seine Wartezeit, also gibt es nichts auszugeben. Die interessanten Zeilen stehen im vorherigen Durchlauf, und genau dafür gibt es den Schalter `--previous` (kurz `-p`). Die kubectl-Referenz beschreibt ihn wörtlich mit: If true, print the logs for the previous instance of the container in a pod if it exists. Wer diesen Schalter nicht kennt, hält den Container für stumm, obwohl er beim Sterben jedes Mal etwas gesagt hat.

?Warum dauert es immer länger, bis der Pod es wieder versucht?

Das ist der Backoff, also die absichtlich wachsende Wartezeit zwischen zwei Startversuchen. Die Kubernetes-Dokumentation zum Pod-Lebenszyklus beschreibt es so: Nachdem Container in einem Pod beendet wurden, startet das kubelet sie mit einer exponentiellen Backoff-Verzögerung neu (10s, 20s, 40s, …), die auf 300 Sekunden (5 Minuten) begrenzt ist. Sobald ein Container 10 Minuten lang fehlerfrei ausgeführt wurde, setzt das kubelet den Timer für diesen Container zurück. Der Sinn ist nicht Schikane, sondern Selbstschutz: Ein kaputter Container soll den Knoten nicht mit endlosen Startversuchen überlasten.

?Ist CrashLoopBackOff selbst der Fehler, den ich beheben muss?

Nein, es ist die Anzeige, dass die Wartezeit gerade greift. Die Dokumentation nennt als typische Auslöser: Anwendungsfehler, die den Container beenden, Konfigurationsfehler wie falsche Umgebungsvariablen oder fehlende Konfigurationsdateien, zu knappe Ressourcen, fehlschlagende Health-Checks und Liveness- oder Startup-Probes, die ein Failure zurückgeben. Behoben wird immer einer dieser Punkte – am Zustandsnamen selbst gibt es nichts zu reparieren.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

SWAnfängerfehlerImagePullBackOff

Kubernetes: ImagePullBackOff und ErrImagePull

Der Pod wartet, weil das Abbild nicht kommt: falscher Name, falsches Tag, fehlende Zugangsdaten. So liest du die Ursache statt zu raten.