Fix Kubernetes FailedScheduling: 0/N nodes are available

Quick answer
A Pod stuck Pending with FailedScheduling means the scheduler looked at every node and rejected all of them. The Events line tells you why — here's how to read it and fix each cause.
- What this error means
- Step 1: See the actual error
- Cause 1: Insufficient cpu or memory
- Cause 2: node(s) had untolerated taint
- Cause 3: nodeSelector or nodeAffinity mismatch
9 min read · Kubernetes
Fix Kubernetes FailedScheduling: 0/N nodes are available
You deploy something, it never comes up, and kubectl get pods shows it stuck in Pending. When you look closer, the Events have a FailedScheduling warning that reads something like 0/5 nodes are available.
This means the scheduler evaluated every node in the cluster and rejected all of them. The good news: the message almost always tells you exactly why. You just need to read it carefully.
What this error means
The Kubernetes scheduler has one job — find a node that satisfies every constraint on your Pod, then bind the Pod to it. If no node passes, the Pod stays Pending and the scheduler records a FailedScheduling event with a per-reason breakdown:
0/5 nodes are available: 3 Insufficient cpu, 2 node(s) had untolerated taint {role: gpu}.
The numbers in front of each reason add up to your total node count. Your job is to figure out which reason blocks the nodes you actually want, and remove that constraint — either on the Pod or on the nodes.
Step 1: See the actual error
Start with the Pod's events. This is where the scheduler writes its verdict.
kubectl describe pod <pod-name>Look at the Events section at the bottom:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 25s (x4 over 2m) default-scheduler 0/5 nodes are available: 3 Insufficient memory, 2 node(s) had untolerated taint {dedicated: db}.
Then get the lay of the land — how many nodes exist and how loaded they are:
kubectl get nodes
kubectl describe node <node-name> # look at Allocatable vs Allocated resourcesThe bottom of describe node shows the Allocated resources table — the sum of all Pod requests already on that node. Compare it to Allocatable (total minus system reserved). If Allocated cpu/memory is near Allocatable, that node is full.
Cause 1: Insufficient cpu or memory
The most common cause. The reason reads Insufficient cpu or Insufficient memory. Either your Pod's requests are too high for any single node, or the cluster is genuinely full.
Scheduling is based on requests, not actual usage — a node with idle CPU can still reject a Pod if the sum of existing requests leaves no room for your request.
Fix — lower the request if it's oversized:
resources:
requests:
cpu: "250m" # not "4" unless the app truly needs 4 cores
memory: "256Mi"Fix — add capacity if the cluster is full. Scale the node group manually, or let autoscaling do it:
# Manually scale a managed node group (example: EKS)
eksctl scale nodegroup --cluster my-cluster --name workers --nodes 5For hands-off scaling, run Cluster Autoscaler or Karpenter so new nodes are provisioned when Pods go Pending for lack of resources. Karpenter in particular reads the pending Pod's requests and launches a right-sized node within seconds.
Cause 2: node(s) had untolerated taint
The reason reads node(s) had untolerated taint {key: value}. Those nodes are tainted, and your Pod doesn't tolerate the taint, so the scheduler skips them. This is common with GPU pools, dedicated database nodes, and control-plane nodes.
Check the taints:
kubectl describe node <node-name> | grep -i taint
# Taints: dedicated=db:NoScheduleFix — add a matching toleration if the Pod belongs on those nodes:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "db"
effect: "NoSchedule"Fix — remove the taint if it shouldn't be there:
kubectl taint nodes <node-name> dedicated=db:NoSchedule- # trailing - removes itCause 3: nodeSelector or nodeAffinity mismatch
The reason reads node(s) didn't match Pod's node affinity/selector. Your Pod requires a label that no schedulable node carries.
Check what your Pod asks for versus what nodes actually have:
kubectl get pod <pod-name> -o jsonpath='{.spec.nodeSelector}'
kubectl get nodes --show-labelsFix — correct the selector to match a real label, or label the node so it qualifies:
kubectl label node <node-name> disktype=ssdA frequent trap is a typo or stale value in requiredDuringSchedulingIgnoredDuringExecution — a required nodeAffinity is hard, so a single wrong value blocks scheduling entirely. If the preference is soft, use preferredDuringScheduling... instead so the scheduler falls back rather than failing.
Stuck on this in production?
We debug exactly this kind of issue for platform teams — usually in a single working session.
Cause 4: podAntiAffinity or topology spread can't be satisfied
The reason mentions node(s) didn't match pod anti-affinity rules or node(s) didn't match pod topology spread constraints. You've told Kubernetes to spread replicas apart, but there aren't enough distinct nodes or zones to honor the rule.
For example, a requiredDuringScheduling podAntiAffinity that forbids two replicas on the same node needs at least as many nodes as replicas. A topologySpreadConstraints with whenUnsatisfiable: DoNotSchedule and maxSkew: 1 will block Pods once the skew would be exceeded.
Fix — add nodes/zones, or relax the constraint so it's a preference:
1topologySpreadConstraints:
2 - maxSkew: 1
3 topologyKey: topology.kubernetes.io/zone
4 whenUnsatisfiable: ScheduleAnyway # was DoNotSchedule
5 labelSelector:
6 matchLabels:
7 app: apiScheduleAnyway keeps the spread as a best-effort goal without leaving Pods Pending.
Cause 5: volume node or zone affinity conflict
The reason reads node(s) had volume node affinity conflict. The Pod uses a PersistentVolume that lives in one availability zone, but the only schedulable nodes are in a different zone. EBS and most cloud block-storage volumes are zonal — a Pod bound to a zone-a volume can only run on a zone-a node.
Check where the PV is pinned:
kubectl get pv <pv-name> -o yaml | grep -A5 nodeAffinityFix — the cleanest long-term answer is to use a StorageClass with volumeBindingMode: WaitForFirstConsumer, so the volume is created in the same zone the Pod lands in:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumerFor an existing stuck Pod, make sure you have a schedulable node in the volume's zone.
Cause 6: too many pods on the node
The reason reads Too many pods. Each node has a max-pods cap (default 110, often lower on smaller instances), and on AWS VPC CNI the real limit is IP addresses per node — every Pod needs a routable IP, and small instance types have very few.
kubectl describe node <node-name> | grep -i pods
# Capacity: pods: 29
# Allocatable: pods: 29Fix — add nodes, choose larger instance types that support more pods/IPs, or enable prefix delegation on the VPC CNI to multiply the IPs per node:
kubectl set env ds aws-node -n kube-system ENABLE_PREFIX_DELEGATION=trueQuick reference
# The three commands that solve almost every FailedScheduling
kubectl describe pod <name> # read the FailedScheduling reason
kubectl get nodes --show-labels # confirm labels for selector/affinity
kubectl describe node <name> # Allocatable vs Allocated, taints, pod cap| Reason in Events | Root cause | First fix |
|---|---|---|
| Insufficient cpu / memory | Requests too high or cluster full | Lower requests or add nodes |
| had untolerated taint | Node taint, no toleration | Add toleration or remove taint |
| didn't match node affinity/selector | Label mismatch | Fix selector or label the node |
| didn't match pod topology spread | Not enough nodes/zones | Relax to ScheduleAnyway |
| volume node affinity conflict | PV in another zone | WaitForFirstConsumer StorageClass |
| Too many pods | max-pods / IP exhaustion | Bigger nodes or prefix delegation |
Frequently Asked Questions
Why is my Pod Pending when kubectl top nodes shows free CPU?
Because the scheduler counts requests, not live usage. A node can be 10% utilized yet reject your Pod if the sum of all Pod requests already reserves nearly all Allocatable CPU. Right-size your requests to the workload's real needs so the scheduler's math matches reality.
What's the difference between FailedScheduling and a Pending Pod?
Pending is the Pod phase — it hasn't been bound to a node yet. FailedScheduling is the reason it's still Pending: the scheduler tried and failed. A Pod can also be Pending because an init container or image pull is in progress, which is not a scheduling failure at all.
How do I read "0/5 nodes are available" quickly?
Read the reasons after the colon and note that the counts sum to your node total. If one reason covers all nodes, that single constraint is your whole problem. If several reasons split the nodes, you must clear every reason blocking the specific nodes you want the Pod to land on.
Can Cluster Autoscaler fix FailedScheduling automatically?
Only when the reason is a lack of resources. Cluster Autoscaler and Karpenter watch for Pods that are Pending due to insufficient cpu/memory and add nodes. They will not help with taints, affinity mismatches, or volume zone conflicts — those are constraints you have to correct on the Pod or node.
Why does my Pod schedule fine but a StatefulSet replica stays Pending?
Usually a volume zone conflict or a topology spread rule. StatefulSets bind each replica to its own PersistentVolume, and if that PV lives in a zone with no free node, the replica can't schedule. Using a WaitForFirstConsumer StorageClass avoids pinning the volume before the Pod is placed.
See also
- How to Taint a Node in Kubernetes — and When You Actually Should
- Pod Topology Spread Constraints for High Availability
- Fix: Kubernetes Pending Pods — the broader guide to every reason a Pod stays Pending
- Kubernetes Scheduling: Taints, Affinity, and Priority — how the scheduler decides placement
- Kubernetes Resource Requests and Limits — right-sizing requests so the scheduler can pack Pods
Stuck on a scheduling failure that doesn't match any of these? Talk to us at Coding Protocols — we run production Kubernetes clusters and can get your workloads scheduling reliably.
Official References
- Assigning Pods to Nodes — nodeSelector, affinity and anti-affinity semantics
- Taints and Tolerations — how taints repel pods and how tolerations override them
Was this article helpful?
Be the first to rate this article
Related Topics
Found this useful? Share it.


