🎓 Mission Debrief: Pending Pod Problem¶
What Happened¶
Your pod was stuck in Pending status because it requested 999 CPUs and 999Gi of memory—far more than any node in your cluster can provide. The Kubernetes scheduler couldn't find a node with enough resources, so the pod never started.
How Kubernetes Behaved¶
The Kubernetes scheduler is responsible for placing pods on nodes. Here's the process:
- Pod created: API server accepts your pod manifest
- Scheduler watches: Sees new unscheduled pod
- Filtering: Eliminates nodes that don't meet requirements (resources, taints, affinity)
- Scoring: Ranks remaining nodes by best fit
- Binding: Assigns pod to winning node
Your pod failed at step 3—no nodes passed the filter because none had 999 CPUs available.
The Correct Mental Model¶
Resource Requests vs Limits:
- Requests: Guaranteed minimum resources (used for scheduling)
- Limits: Maximum resources allowed (enforced at runtime)
resources:
requests: # "I need at least this much"
memory: "64Mi"
cpu: "100m"
limits: # "Don't let me use more than this"
memory: "128Mi"
cpu: "200m"
CPU units:
- 1 = 1 full CPU core
- 100m = 0.1 CPU (100 millicores)
- 1000m = 1 CPU
Memory units:
- Mi = Mebibytes (1024²)
- Gi = Gibibytes (1024³)
- M = Megabytes (1000²)
- G = Gigabytes (1000³)
What happens when a node is full:
Node capacity: 4 CPUs, 8Gi memory
Already allocated: 3 CPUs, 6Gi memory
Available: 1 CPU, 2Gi memory
Pod requests 2 CPUs → ❌ Can't schedule (insufficient CPU)
Pod requests 500m CPU, 1Gi memory → ✅ Can schedule
Real-World Incident Example¶
Company: SaaS startup (100K users) Impact: 6-hour deployment freeze, missed product deadline Cost: Lost enterprise customer worth $500K ARR
What happened:
A developer copy-pasted pod configuration from a "production-grade" blog post that set requests to cpu: 2 and memory: 4Gi for every microservice. Their dev cluster had small nodes (2 CPUs each).
When they deployed 10 microservices, only the first 1-2 pods scheduled. The rest stayed Pending.
Why it took 6 hours:
- Developers thought it was a cluster issue, contacted ops
- Ops thought nodes were unhealthy, started debugging infrastructure
- No one checked kubectl describe pod events for 5 hours
- Finally discovered via: kubectl get events --sort-by='.lastTimestamp'
The fix: Changed requests to cpu: 100m, memory: 128Mi based on actual usage. All pods scheduled immediately.
Lesson:
1. Start with small resource requests (50-100m CPU, 64-128Mi memory)
2. Monitor actual usage with kubectl top pod
3. Adjust based on real data, not guesses
Commands You Mastered¶
# Check pod status
kubectl get pod <name> -n <namespace>
# See why pod isn't scheduling (Events are key!)
kubectl describe pod <name> -n <namespace>
# Check resource requests/limits
kubectl get pod <name> -n <namespace> -o yaml | grep -A 6 resources:
# See node capacity and allocatable resources
kubectl describe nodes
# Check actual resource usage (requires metrics-server)
kubectl top pod <name> -n <namespace>
kubectl top nodes
# See all cluster events sorted by time
kubectl get events --sort-by='.lastTimestamp' -n <namespace>
Prevention Strategies¶
- Set reasonable defaults: Use LimitRanges to prevent unrealistic requests
- Monitor utilization: Deploy metrics-server and track actual usage
- Use VPA (Vertical Pod Autoscaler): Automatically adjust requests based on usage
- Cluster autoscaling: Add nodes automatically when pods are pending
- Admission webhooks: Validate resource requests before accepting pods
- Resource quotas: Prevent one team from consuming entire cluster
Understanding Scheduling Failures¶
Common reasons pods stay Pending:
| Reason | Event Message | Solution |
|---|---|---|
| Insufficient CPU | Insufficient cpu |
Reduce CPU requests or add nodes |
| Insufficient Memory | Insufficient memory |
Reduce memory requests or add nodes |
| No nodes match selector | node(s) didn't match node selector |
Fix nodeSelector labels |
| Taints prevent scheduling | node(s) had taint that pod didn't tolerate |
Add tolerations or remove taints |
| Volume not available | persistentvolumeclaim not found |
Create PVC first |
What's Next?¶
You've mastered three pod states: - ✅ CrashLoopBackOff (bad container command) - ✅ ImagePullBackOff (bad image reference) - ✅ Pending (resource constraints)
Next up: Learn how labels and selectors connect services to pods!