Skip to content

Ein Pod startet nicht

kubectl get pods zeigt dir, welchen der drei Fälle du hast. Sie scheitern an unterschiedlichen Stellen, und das ist nützlich: Der Zustand allein sagt dir, wie weit der Pod gekommen ist.

bash
kubectl get pods
kubectl describe pod <name>

Immer zuerst describe. Die Events am Ende der Ausgabe nennen den Grund fast immer direkt.

Pending

Der Pod existiert, wurde aber auf keinem Node platziert. Er ist nie gestartet, es gibt also keine Logs zu lesen.

Fast immer ist das Kontingent deines Namespace erschöpft:

bash
kubectl get resourcequota -o yaml

Vergleich used mit hard. Stehen CPU- oder Speicher-Requests am Limit, kann nichts mehr eingeplant werden, bis etwas anderes aufhört oder du den Tarif erhöhst. Das Kontingent selbst kannst du nicht anheben.

Denk daran, dass der Request zählt und nicht, was deine Pods tatsächlich verbrauchen, und dass ein Container ohne Angaben trotzdem einen Standard bekommt. Ein Namespace kann also am Kontingent hängen und dabei idle aussehen. Siehe Abrechnung und Kontingente.

Zwei seltenere Ursachen, beide in describe sichtbar:

  • Der Pod fordert mehr CPU oder Speicher an, als das gesamte Kontingent hergibt, er passt also nie.
  • Ein PVC, das er mountet, ist noch nicht gebunden, siehe Überraschungen bei Storage und Kosten.

ImagePullBackOff

Der Pod wurde platziert, aber das Image ließ sich nicht ziehen. describe nennt die Registry und den Grund.

Bei einer privaten Registry fehlen die Zugangsdaten oder sie stimmen nicht. Dein Namespace hat meistens schon ein Pull-Secret, prüf das:

bash
kubectl get secret itsh-registry

Ist es da, referenzier es im Pod-Template, das passiert nicht automatisch:

yaml
spec:
  imagePullSecrets:
    - name: itsh-registry

Fehlt es, leg eins vom Typ kubernetes.io/dockerconfigjson mit einem Registry-Token aus dem Portal an.

Bei einer öffentlichen Registry ist es fast immer der Tag oder ein Tippfehler. Ein Tag, den es nicht gibt, und ein vertippter Repository-Name erzeugen dasselbe manifest unknown.

Im Free Tier denk daran, dass ausgehender Traffic auf HTTP und HTTPS beschränkt ist. Registries nutzen HTTPS, Pulls funktionieren also, eine Registry auf einem ungewöhnlichen Port aber nicht.

CrashLoopBackOff

Der Container startet und beendet sich, immer wieder, mit wachsendem Abstand zwischen den Versuchen. Das ist der freundlichste der drei Fälle: Scheduling und Image-Pull haben geklappt, das Problem liegt also in deiner Anwendung oder ihrer Konfiguration.

Das aktuelle Log stammt vom neuesten Versuch. Um den zu sehen, der tatsächlich gescheitert ist:

bash
kubectl logs deployment/<name> --previous

Häufige Ursachen, grob nach Häufigkeit:

  • Eine fehlende Umgebungsvariable oder ein fehlendes Secret. Die Anwendung beendet sich beim Start. Das Log nennt meistens, welches.
  • Sie erreicht ihre Datenbank nicht. Im Free Tier: Prüf, ob die Datenbank in deinem Namespace läuft. Ausgehende Verbindungen auf Datenbank-Ports funktionieren dort nicht, siehe Ausgehende Verbindungen scheitern.
  • Sie wurde wegen Speicherverbrauch beendet. describe zeigt Last State: Terminated mit Reason: OOMKilled. Erhöh das Speicher-Limit, und denk daran, dass ein Container ohne Angabe auf einen kleinen Standard gedeckelt ist.
  • Eine Liveness-Probe schlägt fehl. Die Anwendung ist in Ordnung, beim Start aber zu langsam zum Antworten, wird deshalb beendet und ewig neu gestartet. Erhöh initialDelaySeconds oder nimm eine Startup-Probe.
  • Der Container beendet sich sauber. Auch Exit-Code 0 führt zum Neustart, denn die Standard-Restart-Policy interessiert nicht, warum er aufgehört hat. Ein Container, der eine Aufgabe erledigt und fertig ist, gehört in einen Job, nicht in ein Deployment.

Wie es weitergeht