Kubernetes Pods können auf viele Arten fehlschlagen, und jeder Fehlerzustand erzählt eine andere Geschichte. Ob Sie mit CrashLoopBackOff, ImagePullBackOff, Pending, OOMKilled oder anderen Fehlerzuständen konfrontiert sind — zu wissen, wie man diese Probleme systematisch diagnostiziert und behebt, ist für jeden Kubernetes-Operator unerlässlich. Dieser Leitfaden führt Sie durch die häufigsten Pod-Fehlerzustände, die kubectl-Befehle zur Diagnose und bewährte Strategien zur Lösung jedes einzelnen Problems.
Voraussetzungen
- Ein laufender Kubernetes-Cluster (v1.24 oder neuer empfohlen)
kubectlinstalliert und mit Cluster-Zugang konfiguriert- Grundlegendes Verständnis von Kubernetes-Objekten (Pods, Deployments, Services)
- Berechtigungen zum Lesen von Pods, Events und Node-Ressourcen in Ihrem Ziel-Namespace
- Vertrautheit mit Container-Konzepten (Images, Registries, Ressourcenlimits)
Pod-Lebenszyklus und Zustände verstehen
Bevor wir in die Fehlerbehebung eintauchen, hilft es, den Kubernetes Pod-Lebenszyklus zu verstehen. Ein Pod durchläuft mehrere Phasen:
| Phase | Beschreibung |
|---|---|
| Pending | Pod wurde vom Cluster akzeptiert, aber ein oder mehrere Container laufen noch nicht |
| Running | Pod ist einem Node zugewiesen und alle Container wurden gestartet |
| Succeeded | Alle Container wurden erfolgreich beendet (Exit-Code 0) |
| Failed | Alle Container wurden beendet und mindestens einer wurde mit einem Fehler beendet |
| Unknown | Pod-Zustand kann nicht ermittelt werden, meist aufgrund eines Node-Kommunikationsfehlers |
Innerhalb dieser Phasen können Container in bestimmte Wartezustände eintreten, die anzeigen, was schiefgelaufen ist. Dies sind die Statusmeldungen, die Sie in der Ausgabe von kubectl get pods sehen — und sie sind Ihr erster diagnostischer Hinweis.
Häufige Pod-Fehlerzustände
CrashLoopBackOff
CrashLoopBackOff ist der häufigste Pod-Fehler, dem Sie begegnen werden. Er bedeutet, dass der Container startet, abstürzt und Kubernetes ihn mit steigenden Verzögerungen (10s, 20s, 40s, bis zu 5 Minuten) weiter neu startet.
Häufige Ursachen:
- Anwendungsfehler, der zum sofortigen Beenden führt (fehlende Konfiguration, unbehandelte Ausnahme)
- Fehlende Umgebungsvariablen oder eingebundene Secrets
- Falscher Befehl oder Entrypoint in der Container-Spezifikation
- Health-Check (Liveness Probe), der zu aggressiv fehlschlägt
- Abhängigkeit von einem Dienst, der nicht verfügbar ist
Diagnosebefehle:
# Pod-Status und Neustart-Zähler prüfen
kubectl get pods -o wide
# Logs des letzten Containers anzeigen
kubectl logs <pod-name> --previous
# Events für den Pod prüfen
kubectl describe pod <pod-name>
Das --previous-Flag ist entscheidend — ohne es erhalten Sie möglicherweise leere oder unvollständige Logs, da die neue Container-Instanz gerade erst gestartet wurde. Die Describe-Ausgabe zeigt den Last State mit dem Exit-Code, der Ihnen verrät, ob der Prozess abgestürzt ist (Exit-Code 1) oder beendet wurde (Exit-Code 137 für OOM, 143 für SIGTERM).
ImagePullBackOff
ImagePullBackOff bedeutet, dass Kubernetes das Container-Image nicht aus der Registry herunterladen kann. Der Pod verbleibt in diesem Zustand und versucht es mit exponentiellem Backoff erneut.
Häufige Ursachen:
- Tippfehler im Image-Namen oder Tag
- Image-Tag existiert nicht (z.B. Verweis auf
latest, wenn nur versionierte Tags gepusht werden) - Fehlende oder abgelaufene
imagePullSecrets - Private Registry ohne konfigurierte Anmeldedaten
- Netzwerkrichtlinie oder Firewall blockiert den Zugang zur Registry
- Registry-Ratenlimits (Docker Hub Drosselung)
Diagnosebefehle:
# Exakte Image-Referenz prüfen
kubectl describe pod <pod-name> | grep -A 5 "Image:"
# Pull-Fehler in Events suchen
kubectl get events --field-selector involvedObject.name=<pod-name>
# Prüfen ob imagePullSecrets existieren
kubectl get secrets -n <namespace>
Pending
Ein Pod im Pending-Zustand bedeutet, dass der Scheduler ihn noch keinem Node zugewiesen hat. Dieser Zustand kann unbegrenzt bestehen bleiben, wenn das zugrunde liegende Problem nicht behoben wird.
Häufige Ursachen:
- Unzureichende CPU oder Speicher auf allen Nodes
- Node-Selektoren, Taints oder Affinitäten, die kein Node erfüllt
- PersistentVolumeClaim (PVC) nicht gebunden — kein passendes PersistentVolume verfügbar
- ResourceQuota im Namespace überschritten
- Zu viele Pods im Cluster (max-pods-Limit auf Nodes)
Diagnosebefehle:
# Prüfen warum der Pod pending ist
kubectl describe pod <pod-name>
# Scheduler-Events anzeigen
kubectl get events --sort-by='.lastTimestamp' -n <namespace>
# Node-Ressourcen prüfen
kubectl describe nodes | grep -A 5 "Allocated resources"
# PVC-Status prüfen, wenn der Pod Volumes verwendet
kubectl get pvc -n <namespace>
OOMKilled
OOMKilled (Exit-Code 137) bedeutet, dass der Out-Of-Memory-Killer des Linux-Kernels den Container beendet hat, weil er sein Speicherlimit überschritten hat.
Häufige Ursachen:
- Speicherlimit zu niedrig für die Anwendung angesetzt
- Speicherleck in der Anwendung
- JVM-Heap-Größe nicht auf das Container-Speicherlimit abgestimmt
- Sidecar-Container verbrauchen gemeinsamen Speicher
- Große Datensätze werden in den Speicher geladen
Diagnosebefehle:
# Beendigungsgrund prüfen
kubectl describe pod <pod-name> | grep -A 3 "Last State"
# Aktuellen Speicherverbrauch anzeigen (erfordert metrics-server)
kubectl top pod <pod-name>
# Konfigurierte Limits prüfen
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[*].resources}'
Weitere Fehlerzustände
| Zustand | Bedeutung | Typische Lösung |
|---|---|---|
| CreateContainerConfigError | Fehlende ConfigMap oder Secret | Überprüfen Sie, ob referenzierte ConfigMaps und Secrets existieren |
| RunContainerError | Container-Runtime-Fehler | Sicherheitskontext, Volume-Mounts und Container-Runtime-Logs des Nodes prüfen |
| Evicted | Node unter Ressourcendruck | Node-Disk-/Speicherdruckbedingungen prüfen und korrekte Ressourcenanforderungen setzen |
| Init:Error | Init-Container fehlgeschlagen | Init-Container-Logs mit kubectl logs <pod> -c <init-container> prüfen |
| Terminating (hängt) | Finalizer blockieren Löschung | Finalizer mit kubectl get pod -o json prüfen und bei Sicherheit entfernen |
Probleme mit kubectl diagnostizieren
Der Diagnose-Workflow folgt einem konsistenten Muster, unabhängig vom Fehlertyp:
Schritt 1: Überblick verschaffen
# Alle Pods im Namespace mit Status
kubectl get pods -n <namespace> -o wide
# Aktuelle Events nach Zeit sortiert
kubectl get events --sort-by='.lastTimestamp' -n <namespace> | tail -20
Schritt 2: Pod im Detail untersuchen
# Vollständige Pod-Beschreibung mit Events
kubectl describe pod <pod-name> -n <namespace>
# Container-Logs (aktuelle Instanz)
kubectl logs <pod-name> -n <namespace>
# Container-Logs (vorherige abgestürzte Instanz)
kubectl logs <pod-name> -n <namespace> --previous
# Logs eines bestimmten Containers in einem Multi-Container-Pod
kubectl logs <pod-name> -c <container-name> -n <namespace>
Schritt 3: Node überprüfen
# Node-Bedingungen (Disk-Druck, Speicherdruck, PID-Druck)
kubectl describe node <node-name> | grep -A 10 "Conditions"
# Ressourcenzuweisung auf dem Node
kubectl describe node <node-name> | grep -A 20 "Allocated resources"
Schritt 4: Interaktives Debugging
# In einen laufenden Container einsteigen
kubectl exec -it <pod-name> -- /bin/sh
# Ephemeren Debug-Container verwenden (K8s 1.23+)
kubectl debug -it <pod-name> --image=busybox --target=<container-name>
# Debug-Pod im selben Netzwerk-Namespace starten
kubectl run debug --rm -it --image=busybox -- /bin/sh
Vergleichstabelle der kubectl-Befehle
| Fehlerzustand | Erster Befehl | Wichtige Information |
|---|---|---|
| CrashLoopBackOff | kubectl logs <pod> --previous | Anwendungsfehlerausgabe vor dem Absturz |
| ImagePullBackOff | kubectl describe pod <pod> | Image-Name, Pull-Fehler, Secret-Referenzen |
| Pending | kubectl describe pod <pod> | Scheduler-Fehlergrund im Events-Abschnitt |
| OOMKilled | kubectl describe pod <pod> | Beendigungsgrund und Exit-Code im Last State |
| CreateContainerConfigError | kubectl get configmap,secret -n <ns> | Fehlende referenzierte Ressourcen |
| Evicted | kubectl describe node <node> | Node-Ressourcendruckbedingungen |
| Init:Error | kubectl logs <pod> -c <init-container> | Fehler-Logs des Init-Containers |
Praxisszenario
Sie verwalten einen Produktionscluster, auf dem eine Microservices-Anwendung läuft. Nach einem Deployment startet der Pod payment-service ständig neu und zeigt CrashLoopBackOff. So diagnostizieren Sie das Problem:
$ kubectl get pods -n production
NAME READY STATUS RESTARTS AGE
payment-service-7d4f8b9c6-x2k9m 0/1 CrashLoopBackOff 5 8m
api-gateway-5c8f7d6b4-h3j7n 1/1 Running 0 2d
user-service-6b7c8d9e5-m4n8p 1/1 Running 0 2d
Sie prüfen die Logs des vorherigen Containers:
$ kubectl logs payment-service-7d4f8b9c6-x2k9m --previous
2026-02-28 10:15:03 ERROR: Failed to connect to database
ConnectionRefused: tcp://db-service:5432
2026-02-28 10:15:03 FATAL: Cannot start without database connection. Exiting.
Die Anwendung benötigt eine Datenbankverbindung beim Start, aber db-service ist nicht erreichbar. Sie prüfen den Service:
$ kubectl get svc db-service -n production
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db-service ClusterIP 10.96.45.123 <none> 5432/TCP 30d
$ kubectl get endpoints db-service -n production
NAME ENDPOINTS AGE
db-service <none> 30d
Keine Endpoints — der Datenbank-Pod ist ausgefallen. Sie stellen fest, dass er aufgrund von Disk-Druck auf dem Node evicted wurde:
$ kubectl get pods -n production | grep db
db-postgresql-0 0/1 Evicted 0 30d
Die Lösung: Speicherplatz auf dem Node freigeben (oder weitere Nodes hinzufügen), den Datenbank-Pod neu starten, und der Payment-Service erholt sich automatisch. Zusätzlich fügen Sie eine startupProbe mit einem großzügigen Timeout hinzu, damit der Payment-Service auf die Datenbank wartet, anstatt sofort abzustürzen.
Stolperfallen und Sonderfälle
-
Exit-Code 137 vs. 143: Exit-Code 137 bedeutet, dass der Container durch SIGKILL beendet wurde (meist OOMKilled). Exit-Code 143 bedeutet SIGTERM (ordnungsgemäßes Herunterfahren). Verwechseln Sie diese nicht — 137 erfordert eine Speicheruntersuchung, 143 ist normalerweise normal bei Rollouts.
-
CrashLoopBackOff-Verzögerung: Kubernetes verwendet exponentielles Backoff bis zu 5 Minuten zwischen Neustarts. Wenn Sie das Problem behoben haben, müssen Sie möglicherweise trotzdem warten oder den Pod löschen, um ihn sofort neu zu starten.
-
ImagePullPolicy: Always: Wenn Ihre Pod-Spezifikation
imagePullPolicy: Alwaysverwendet (der Standard fürlatest-Tags), löst jeder Pod-Neustart einen Image-Pull aus. Dies kann zu ImagePullBackOff führen, wenn die Registry vorübergehend nicht erreichbar ist, obwohl das Image zuvor auf dem Node zwischengespeichert war. -
Ressourcenanforderungen vs. Limits: Pods werden basierend auf Anforderungen (Requests) geplant, nicht auf Limits. Ein Pod, der 100Mi anfordert, aber auf 500Mi begrenzt ist, kann bei 500Mi per OOMKilled beendet werden, selbst wenn der Node 2Gi frei hat — das Limit wird unabhängig von der Node-Kapazität durchgesetzt.
-
Multi-Container-Pods: In einem Pod mit Sidecars zeigt
kubectl logsstandardmäßig den ersten Container an. Geben Sie beim Debugging von Multi-Container-Pods immer-c <container-name>an. -
Ephemeral-Storage-Evictions: Auch wenn CPU und Speicher in Ordnung sind, kann hoher ephemerer Speicherverbrauch (Logs, temporäre Dateien) eine Eviction auslösen. Prüfen Sie dies mit
kubectl describe nodeunterConditions. -
PVC in falscher Verfügbarkeitszone: In Cloud-Umgebungen kann ein PVC, das an ein Volume in
us-east-1agebunden ist, nicht von einem Pod eingebunden werden, der auf einem Node inus-east-1bgeplant ist. Der Pod bleibt ohne offensichtlichen Fehler im Pending-Zustand. -
DNS-Auflösungsverzögerung: Neu erstellte Services werden möglicherweise nicht sofort aufgelöst. Wenn Ihr Container abstürzt, weil er einen Servicenamen nicht auflösen kann, fügen Sie eine Startverzögerung oder Retry-Logik hinzu, anstatt sich auf sofortige DNS-Propagierung zu verlassen.
Zusammenfassung
- CrashLoopBackOff bedeutet, dass Ihr Container ständig abstürzt — prüfen Sie die Logs mit
--previous, um den Fehler vor dem Absturz zu sehen - ImagePullBackOff weist auf einen Image-Pull-Fehler hin — überprüfen Sie Image-Name, Tag und Registry-Anmeldedaten
- Pending bedeutet, dass der Scheduler den Pod nicht platzieren kann — prüfen Sie Ressourcenverfügbarkeit, PVC-Status und Node-Affinity-Regeln
- OOMKilled (Exit-Code 137) bedeutet, dass der Container sein Speicherlimit überschritten hat — erhöhen Sie die Limits oder optimieren Sie den Speicherverbrauch
- Beginnen Sie immer mit
kubectl describe podundkubectl get events, um den Fehlerkontext zu verstehen - Verwenden Sie
kubectl debugfür ephemere Container, wenn Sie interaktives Troubleshooting ohne Änderung der Pod-Spezifikation benötigen - Setzen Sie korrekte Ressourcenanforderungen, Limits und Probes, um viele häufige Pod-Fehler von vornherein zu vermeiden