Pod Pending in Kubernetes: 23 Ursachen, Decision-Tree, Fix-Workflow
Pod hängt im Status Pending? Die 23 häufigsten Ursachen in 5 Kategorien, mit kubectl-Befehlen, Decision-Tree und Workflow zur Diagnose in unter 5 Minuten.
TL;DR - Pending ist kein Bug, sondern ein Zustand: Kubernetes hat den Pod akzeptiert, kann oder will ihn aber gerade nicht starten. Die Ursache steht in 90% der Fälle direkt im Events-Bereich von
kubectl describe pod- aber sie verteilt sich auf 23 verschiedene Patterns in 5 Kategorien. Dieser Workflow findet die richtige in unter 5 Minuten.
🔖 Nur die Befehle? Hier ist der interaktive Pod-Pending-Cheatsheet - mit Copy-Buttons, vollständigem 23-Ursachen-Index und Druck-Ansicht. Lesezeichen empfohlen.
Was Pending wirklich bedeutet
Pending ist die zweite Pod-Phase nach Created. Heißt:
- Kubernetes-API hat das Pod-Objekt akzeptiert
- Der Scheduler hat aber noch keinen Node ausgewählt - oder
- Der Kubelet auf dem zugewiesenen Node startet die Container noch nicht
In etwa 70% der Fälle hängt der Pod beim Scheduler. Die anderen 30% verteilen sich auf Volume-, Image- und Node-Health-Themen. Beide Ursachen sehen für den Operator gleich aus (STATUS: Pending), brauchen aber komplett unterschiedliche Workflows.
Wichtig: ein Pending-Pod verbraucht keine Cluster-Ressourcen außer einem Eintrag in etcd. Sie können ihn beliebig lange so liegen lassen, ohne Side-Effects - außer dass die App nicht läuft.
Der 3-Schritt-Workflow
Diese drei Befehle laufen immer zuerst, egal welche Ursache.
Schritt 1: Events lesen
kubectl describe pod <name> | tail -20
Scrolle direkt zum Events:-Bereich am Ende. Beispiel-Output:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 2m default-scheduler 0/5 nodes are available: 3 Insufficient cpu, 2 node(s) had untolerated taint {dedicated: gpu}.
Das ist die Antwort. Insufficient cpu plus untolerated taint sind zwei konkrete Ursachen aus unserer 23er-Liste.
Schritt 2: Scheduler-Events clusterweit
Wenn der Pod-Describe nichts hergibt - z. B. wenn das Event-Retention-Window abgelaufen ist:
kubectl get events --field-selector reason=FailedScheduling -A --sort-by=.lastTimestamp | tail -20
Findet alle Scheduling-Probleme cluster-weit, zeitlich sortiert. Hilft auch bei kaskadierten Problemen, wo ein Node-Ausfall plötzlich 30 Pods pending werden lässt.
Schritt 3: Node-Health prüfen
Bei Verdacht auf cluster-weite Probleme:
kubectl get nodes
kubectl describe node <node> | grep -A 10 "Conditions"
NotReady, DiskPressure, MemoryPressure oder PIDPressure sind die wichtigsten Conditions, die Pods am Starten hindern.
Die 23 Ursachen, kategorisiert
Kategorie 1: Resource-Constraints (4 Ursachen)
Der Scheduler findet keinen Node mit genug freien Ressourcen.
Kubernetes Debugging - systematisch statt raten
Echte Production-Incidents nachstellen, kubectl-Workflows verinnerlichen, Root-Causes in Minuten finden.
Workshop-Details ansehen1.1 Insufficient CPU - kein Node hat genug freie CPU, summiert über alle bereits gescheduleten Pods.
kubectl describe node <node> | grep -A 5 "Allocated resources"
# CPU Requests: 3800m / 4000m (95%)
Fix: Pod-Requests senken (sind sie realistisch?), Node-Pool skalieren, oder Cluster Autoscaler/Karpenter einsetzen.
1.2 Insufficient Memory - dasselbe für RAM. Bei Burstable-QoS-Pods sieht man oft RAM-Overcommit, beim Scheduler zählen aber Requests, nicht Limits.
1.3 Insufficient ephemeral-storage - Node-Filesystem voll, Scheduler verweigert neue Pods. Klassiker auf Nodes mit großen Container-Images im Cache.
kubectl describe node <node> | grep -A 2 "ephemeral-storage"
Fix: Image-Garbage-Collection-Schwellen anpassen oder Node mit größerer Root-Disk neu starten.
1.4 Container-Requests > Node-Kapazität - ein einzelner Container fordert mehr als der größte Node insgesamt hat. Pod kann nirgendwo platziert werden, egal wie leer der Cluster ist.
resources:
requests:
memory: "32Gi" # aber Node hat nur 16Gi total
Fix: Requests reduzieren oder Node-Pool mit größeren Instanzen anlegen.
Kategorie 2: Scheduler-Constraints (6 Ursachen)
Der Pod hat Regeln, die kein Node erfüllt.
2.1 NodeSelector-Mismatch - der Pod will auf einen Node mit Label tier: gpu, aber kein Node hat das Label.
kubectl get nodes -l tier=gpu
# No resources found
Fix: Node mit dem Label labeln (kubectl label node <node> tier=gpu) oder Selector im Manifest korrigieren.
2.2 NodeAffinity (required) erfüllt nicht - requiredDuringSchedulingIgnoredDuringExecution mit zu strikten Regeln, kein Node passt.
Events: 0/3 nodes are available: 3 node(s) didn't match Pod's node affinity/selector.
Fix: Affinity-Regeln entweder lockern, auf preferredDuringScheduling... umstellen, oder passende Nodes provisionieren.
2.3 Taint ohne passende Toleration - Node hat Taint (z. B. dedicated=gpu:NoSchedule), Pod hat keine matching Toleration.
kubectl describe nodes | grep -A 1 "Taints:"
Fix:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
2.4 PodAntiAffinity - Pod darf nicht auf Nodes laufen, wo bereits gleichartige Pods sind. Bei requiredDuringSchedulingIgnoredDuringExecution über topologyKey: kubernetes.io/hostname mit 5 Replicas aber nur 3 Nodes → 2 Pods bleiben Pending.
Fix: Replicas reduzieren, mehr Nodes provisionieren, oder PodAntiAffinity auf preferred... weichmachen.
2.5 TopologySpreadConstraints maxSkew überschritten - Spread-Constraints (z. B. “max 2 Pods Unterschied zwischen Zonen”) können bei ungleich verteilten Nodes Pods blockieren.
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
Fix: whenUnsatisfiable: ScheduleAnyway, größeren maxSkew, oder Node-Verteilung über Zonen angleichen.
2.6 Pod-Topology-Constraint “DoNotSchedule” - Sonderfall der 2.5, wenn die Constraints buchstäblich kein Schedule erlauben.
Kategorie 3: Volume-Probleme (4 Ursachen)
Der Pod kommt nicht in Phase Running, weil ein Volume nicht bereit ist.
3.1 PVC nicht Bound - PersistentVolumeClaim hat keinen passenden PV gefunden.
kubectl get pvc -A | grep -v Bound
Häufige Ursachen: keine StorageClass mit default: true, falsche accessModes, falsche storageClassName-Referenz.
3.2 PVC bound, aber RWO-Volume schon woanders gemounted - der Pod soll auf Node-A, aber das RWO-Volume hängt noch an Node-B. Bei StatefulSet-Restarts klassisch.
Events: Multi-Attach error for volume "pvc-xxx" Volume is already exclusively attached to one node.
Fix: alten Pod erst sauber terminieren (oder Force-Delete), dann Volume freigeben lassen.
3.3 Volume-Topology-Konflikt - PV ist in Zone-A, Scheduler will Pod aber auf Node in Zone-B platzieren.
Events: 0/3 nodes are available: 3 node(s) had volume node affinity conflict.
Fix: volumeBindingMode: WaitForFirstConsumer in der StorageClass setzen - dann wird PV erst bei Pod-Scheduling erstellt, an der passenden Zone.
3.4 StorageClass nicht vorhanden - PVC referenziert storageClassName: gp3, aber Cluster kennt nur standard.
kubectl get sc
Fix: StorageClass anlegen, oder PVC umschreiben, oder StorageClass-Mapping in der Migration.
Kategorie 4: Image- und Container-Probleme (4 Ursachen)
Der Pod ist gescheduled, kommt aber nicht in Running.
4.1 ImagePullBackOff - Image existiert nicht, falsche Tag, oder Registry erreichbar aber langsam. Reason im Status: ImagePullBackOff.
kubectl describe pod <name> | grep -A 3 "Failed"
# Failed to pull image "myapp:v1.2.3": rpc error: ... not found
Fix: Image-Tag prüfen, in der Registry verifizieren, ggf. imagePullPolicy: IfNotPresent vs Always kontrollieren.
4.2 ErrImagePull - erster Pull-Versuch fehlgeschlagen (vor BackOff). Meist DNS-Probleme oder Registry-Auth-Fehler.
4.3 InvalidImageName - Image-Reference ist syntaktisch ungültig (Doppel-Doppelpunkte, ungültige Tags).
image: registry.io/foo::v1 # invalid - double colon
4.4 Fehlende imagePullSecrets - Private Registry, aber kein Secret oder falsches Secret referenziert.
Events: Failed to pull image: pull access denied, repository does not exist or may require authorization.
Fix:
spec:
imagePullSecrets:
- name: my-registry-secret
Plus passendes kubernetes.io/dockerconfigjson-Secret im Namespace.
Kategorie 5: Node-Health & Quota (5 Ursachen)
Cluster-weite oder Namespace-weite Probleme.
5.1 NodeNotReady - Node ist offline, hat Kubelet-Crash, oder Network-Plugin ist tot.
kubectl get nodes
# node-3 NotReady <none> 3d v1.30.1
Fix: Node-SSH, journalctl auf Kubelet, Network-Plugin-Pods checken.
5.2 DiskPressure - Kubelet hat Disk-Pressure-Eviction-Schwelle erreicht und blockiert neue Pods.
kubectl describe node <node> | grep -A 5 "Conditions"
# DiskPressure True ...
Fix: Disk aufräumen, Image-GC anstoßen, größere Disk, oder Eviction-Schwellen anpassen.
5.3 MemoryPressure / PIDPressure - dasselbe Pattern für RAM oder Process-IDs.
5.4 ResourceQuota überschritten - Namespace hat ResourceQuota, neuer Pod würde die überschreiten.
Events: exceeded quota: compute-quota, requested: requests.memory=2Gi, used: requests.memory=8Gi, limited: requests.memory=10Gi, requested would exceed quota.
Fix: Quota erhöhen, andere Pods reduzieren, oder Namespace-Strategie überarbeiten.
5.5 LimitRange-Verletzung - Namespace hat LimitRange, Pod-Requests/Limits passen nicht in die erlaubten Bereiche.
Fix: Pod-Manifest an LimitRange anpassen, oder LimitRange lockern.
Decision Tree
Events sagen "FailedScheduling"?
↓ ja
"Insufficient cpu/memory/storage"? → Kategorie 1 (Resources)
↓ nein
"didn't match Pod's node affinity"? → 2.1 / 2.2 (Selector / Affinity)
↓ nein
"had untolerated taint"? → 2.3 (Taint)
↓ nein
"didn't satisfy anti-affinity"? → 2.4 (PodAntiAffinity)
↓ nein
"volume node affinity conflict"? → 3.3 (Topology)
↓ nein
"unschedulable" + Quota-Message? → 5.4 (ResourceQuota)
↓ nein
Events sagen "FailedMount" / PVC? → Kategorie 3 (Volumes)
↓ nein
Events sagen "ImagePullBackOff"? → Kategorie 4 (Images)
↓ nein
"node(s) had condition" Pressure? → 5.2 / 5.3 (Node Pressure)
↓ nein
Kein Node in NodeNotReady? → 5.1 (NodeNotReady)
↓ nein
Selten: LimitRange (5.5) oder Topology Spread (2.5)
Was die Workshops nicht ersetzen
Dieser Workflow löst die 23 dokumentierten Ursachen. Was nicht drin steckt:
- Custom Scheduler-Plugins - bei Volcano, Yunikorn oder eigenen Scheduler-Erweiterungen gibt es eigene Pending-Reasons, die nicht in dieser Liste auftauchen
- Webhook-Admissions, die Pods stillschweigend rejecten - manche Validating-Webhooks setzen Pods auf Pending statt Failed; in den Logs des Webhook-Controllers nachsehen
- Kubelet-Bugs unter Last - sehr selten, aber Kubelet 1.28-1.30 hatte Edge-Cases bei massivem Parallel-Scheduling
- CSI-Driver-Bugs - PVC bleibt Pending obwohl alle Parameter stimmen, weil der CSI-Provisioner einen Internen Bug hat
Diese Pattern brauchen System-Verständnis und Tools wie kubectl get events --watch -A, journalctl -u kubelet auf den Nodes, und ein gutes Verständnis vom Scheduler-Framework.
Wie es weitergeht
Im Kubernetes Debugging Workshop spielen wir 8 echte Production-Incidents nach - inklusive zweier Pod-Pending-Edge-Cases (TopologySpread-Skew unter Skalierung und CSI-Driver-Hang während eines Node-Updates) - und drillen den Workflow, bis er sitzt. 1 Tag, 8 Stunden, danach lösen Sie Pod-Pending systematisch und nicht durch Raten.
Verwandt aus unserer Debugging-Serie:
- OOMKilled in Kubernetes - 6 Ursachen, Right-Sizing-Formel, Runtime-Limits für JVM/Node/Go
- CrashLoopBackOff systematisch fixen - 7 Ursachen, 1 Workflow
- kubectl Debugging Cheatsheet - die 12 Befehle, die jede Pod-Inspektion abdecken
- Pod-Pending-Cheatsheet (interaktiv) - 12 Befehle mit Copy-Button, vollständiger 23-Ursachen-Index, drucktauglich
Kubernetes Debugging - systematisch statt raten
Echte Production-Incidents nachstellen, kubectl-Workflows verinnerlichen, Root-Causes in Minuten finden.
Workshop-Details ansehenWeiterlesen
OOMKilled in Kubernetes: 6 Ursachen, kubectl-Workflow, Right-Sizing
Pod stirbt mit Exit 137? Die 6 Ursachen für OOMKilled in Kubernetes - mit kubectl-Befehlen, JVM-Fallen und Decision-Tree zum Right-Sizing in unter 10 Minuten.
10 min
CrashLoopBackOff systematisch fixen: 7 Ursachen, 1 Workflow
Die 7 häufigsten Ursachen für CrashLoopBackOff - mit kubectl-Befehlen, echten Outputs und einem Decision-Tree, der jede Ursache in unter 5 Minuten findet.
9 min
kubectl Debugging Cheatsheet: 12 Befehle für Production-Incidents
Strukturierter Debugging-Workflow für Kubernetes in Production: 12 kubectl-Befehle in der richtigen Reihenfolge - von Pod-Status bis ephemeral debug containers.
8 minBrauchen Sie eine zweite Meinung zu Ihrem Cluster?
Buchen Sie einen kostenfreien 30-Minuten Kubernetes Health-Check. Wir schauen uns Ihr Setup an und geben konkrete Hinweise, ohne Verkaufsgespräch.
Termin buchen