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.
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:
kubectl get resourcequota -o yamlVergleich 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:
kubectl get secret itsh-registryIst es da, referenzier es im Pod-Template, das passiert nicht automatisch:
spec:
imagePullSecrets:
- name: itsh-registryFehlt 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:
kubectl logs deployment/<name> --previousHä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.
describezeigtLast State: TerminatedmitReason: 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
initialDelaySecondsoder 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
- Erstes Deployment für ein Manifest, das funktioniert
- Abrechnung und Kontingente, was das Kontingent füllt