On this page
Why Is My Kubernetes Pod Stuck Pending?
A Pending pod has not been scheduled onto a node. Learn the causes — resources, taints, selectors, volumes — and how to diagnose each with describe.
Quick answer
- A pod is Pending when the scheduler has not placed it on a node. It has not started and it has not failed — it has nowhere to run.
- The reason is always in the pod’s events. Start with
kubectl describe podand read the scheduler’s message.- The usual causes are resource requests larger than any node has free, a node selector matching nothing, an untolerated taint, or a volume that will not bind.
- On a single-node cluster, Pending almost always means your requests exceed the node’s capacity.
What does it mean when a pod is Pending?
Pending is a scheduling state, not a failure. The API server has accepted the pod and it exists, but the scheduler (kube-scheduler) has not found any node it can run on and has not assigned it anywhere. It sits in the queue until something changes — usually a node gaining capacity, or a configuration change.
This is a different failure mode from a crash loop, and the distinction matters because the diagnosis is completely different. A CrashLoopBackOff pod ran and died; the container’s own logs are where the answer is. A Pending pod never ran, so container logs are empty and useless, and the answer is in the scheduler’s events.
Where this bites vibecoders
The specific way this bites vibecoders is a generated manifest with realistic-looking resource numbers and a small server. An assistant writes
resources: requests: cpu: 500m, memory: 512Mibecause that is a plausible-looking example, and you apply it to a 1GB VPS. The pod is Pending forever, no error is printed, and the obvious conclusion is that Kubernetes is broken. Nothing in the YAML flags that the request exceeds the machine.
Why is my pod Pending? What are the causes?
| Cause | Scheduler message | Typical situation |
|---|---|---|
| Insufficient resources | Insufficient cpu / Insufficient memory | Requests exceed what any node has free |
| Node selector matches nothing | node(s) didn't match Pod's node affinity/selector | A nodeSelector naming a label your nodes do not carry |
| Untolerated taint | had untolerated taint | A control-plane or dedicated node is excluded |
| No nodes at all | no nodes available to schedule pods | Cluster empty, or all nodes NotReady |
| Volume will not bind | pod has unbound immediate PersistentVolumeClaims | Storage class missing or PV not yet provisioned |
| Affinity conflict | node(s) didn't match pod affinity rules | A co-location rule that cannot be satisfied |
| Node selectors on values | node(s) didn't match Pod's node affinity/selector | Selector pinned to a machine type you do not have |
| Pod priority too low | preemption: no preemption victims found | A higher-priority pod holds the capacity |
Read the whole message. The scheduler lists one reason per node, and the output often contains several different failures at once — a selector problem and insufficient memory. Fixing only the first leaves the pod Pending.
How do I diagnose a Pending pod?
Three commands, in order. The first two are almost always sufficient.
1. Read the events. This is where the answer is:
kubectl describe pod my-app-7d9f8b6c4-x2k9pLook at the Events: section at the bottom. A Pending pod produces a repeating FailedScheduling entry that names the reason:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 2m default-scheduler 0/1 nodes are available: 1 Insufficient cpu.That single line tells you the node exists, and that the problem is CPU. If the node selector were wrong, the message would say node(s) didn't match Pod's node affinity/selector instead.
2. Compare requests against node capacity. For insufficient resources, check what the pod asked for against what is actually free:
# What the pod requested
kubectl describe pod my-app-7d9f8b6c4-x2k9p | grep -A5 Requests
# What the node has
kubectl describe node | grep -A8 "Allocatable"Then check what is already claimed:
kubectl top nodes
kubectl describe node | grep -A20 "Allocated resources"3. Check the node is healthy. If no nodes available appears, the node itself may be the problem:
kubectl get nodes
# STATUS should be Ready, not NotReady
kubectl describe node | grep -i taintA node stuck NotReady is a separate problem — usually networking or a kubelet failure — and it silently makes every pod Pending.
How do I fix a Pending pod?
Match the fix to the reason, and confirm it by watching the pod leave Pending.
Requests exceed capacity. Lower them, or add capacity. On a small node, the request is a floor, not a suggestion — a pod requesting 1Gi of memory on a node with 800Mi free will never run:
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512MiRequests drive scheduling; limits drive runtime enforcement. This distinction is the subject of Kubernetes Requests vs Limits.
Node selector matches nothing. Inspect the labels your nodes actually have, then correct the selector:
kubectl get nodes --show-labels
kubectl get pod my-app -o jsonpath='{.spec.nodeSelector}'A taint is not tolerated. List the taints, then add a matching toleration to your pod:
kubectl describe node | grep -i taintA volume will not bind. Check the claim and the storage class:
kubectl get pvc
kubectl get storageclass
kubectl describe pvc my-data | grep -A5 EventsAn empty kubectl get storageclass is the usual cause — nothing is configured to provision volumes, and a dynamic provisioning request waits forever. On k3s, the local-path provisioner is usually present; on managed clusters, the default class often is not.
No nodes available. Fix the node before the pod. Check kubectl get nodes, then the kubelet on that machine.
Verify the fix:
kubectl get pod -wThe pod should move to ContainerCreating and then Running. If it stays Pending, the new event message will show a different reason — re-read it rather than assuming the first fix worked.
Where AI coding assistants get this wrong
- Generating resource requests that exceed a small server’s capacity, because the numbers came from a documentation example rather than your machine.
- Omitting
resourcesentirely, which avoids Pending but leaves the pod a first target for eviction and the node unprotected. - Adding a
nodeSelectorcopied from a cloud-provider tutorial, pinning the pod to labels your nodes do not have. - Hardcoding
nodeName, which bypasses the scheduler entirely and silently skips resource checks, affinity, and taints — usenodeSelectoror affinity. - No toleration on a dedicated or control-plane node, so the pod never considers it even when it is the only node available.
- Assuming Pending means the image is bad. A missing image produces
ErrImagePullorImagePullBackOff, notFailedScheduling— see ImagePullBackOff. - Debugging container logs for a pod that has never started, where the logs are necessarily empty.
- A PVC with no storage class, so the volume stays unbound and the pod waits forever with a misleading message.
Checklist
- Run
kubectl describe podand read theFailedSchedulingevent before anything else. - Read the entire scheduler message; it usually lists several reasons.
- Compare
requestsagainst the node’sAllocatablevalues. - Check what is already allocated with
kubectl describe node | grep -A20 "Allocated resources". - Confirm the node is
Readybefore investigating pod configuration. - List actual node labels with
kubectl get nodes --show-labelsand correct anynodeSelector. - Check taints and add a matching toleration where appropriate.
- Verify a storage class exists before deploying a pod with a PVC.
- Prefer
nodeSelectoror affinity overnodeName. - Set resource requests deliberately, sized to the machine you actually have.
- Watch
kubectl get pod -wto confirm the pod leaves Pending.
FAQ
What does Pending mean on a Kubernetes pod?
Pending means the pod has been accepted by the API server but the scheduler has not yet placed it on a node. The pod object exists and is not failing — it simply has nowhere to run. The reason is always written in the pod’s events, which is where you should start looking.
Why does my pod say 0/1 nodes are available?
The scheduler tried every node in your cluster and rejected all of them, then summarised the count. The message lists each reason, such as insufficient cpu or memory, a node selector that matches nothing, or an untolerated taint. Read the full message, because the first reason shown is often only one of several.
Why is my pod Pending after a fresh install?
On a single-node cluster the most common cause is a resource request larger than the node has available. A generated manifest that asks for 500m of CPU and 512Mi of memory will sit Pending forever on a 1-vCPU, 1GB VPS. Lower the requests, or size the node to match.
How long should a pod stay Pending before I worry?
If it has been Pending for more than a minute or two, something is wrong — a healthy cluster schedules a pod in well under a second. If the events are only appearing a moment ago, a recent node addition or a scale-up may resolve it on its own.
Is Pending different from CrashLoopBackOff?
Yes, and the distinction directs you to different evidence. Pending means the pod was never scheduled, so the answer is in the scheduler’s events and the node’s capacity. CrashLoopBackOff means the pod ran and the container exited, so the answer is in the container’s logs — see How to Debug a Crash-Looping Container.
Should I set resource requests at all?
Yes, but size them to the machine you have. Requests determine where a pod can be placed, so a request that exceeds any node’s free capacity makes the pod permanently Pending. Omitting requests works but leaves the scheduler blind and makes your pod the first evicted under memory pressure.
Related topics
- How to Debug a Crash-Looping Container
- Kubernetes Requests vs Limits: Why Your Pod Gets OOMKilled
- ImagePullBackOff: What It Means and How to Fix It
- Kubernetes YAML Explained: Deployments, Services, and What Your AI Writes
- What Is a Health Check?