1. Introduction
A ResourceQuota exceeded error blocks pod creation in a namespace. When you try to deploy, scale, or create a new pod and the namespace has reached its quota limit, Kubernetes rejects the request immediately with a clear error. The deployment sits with fewer replicas than desired, HPA can't scale up, and CI/CD deployments fail — all because a quota limit was hit.
ResourceQuotas are intentional administrative controls, not bugs. This guide covers how to diagnose which quota is blocking you, how to adjust quota when appropriate, and how to avoid hitting quota limits in the first place.
2. What ResourceQuota Means
A ResourceQuota object sets hard limits on the aggregate resource consumption within a namespace. It can limit: CPU requests and limits, memory requests and limits, number of pods, number of PVCs, total storage, number of Services, ConfigMaps, Secrets, and more. When any limit is hit, all new resource creation of that type fails until usage drops below the limit.
3. Common Causes
- Quota was set conservatively and the namespace's legitimate workload has grown
- A deployment was scaled up (manually or by HPA) beyond what the quota allows
- Pods are not being cleaned up — old failed pods count against pod quota
- Memory or CPU limits are too high on pods, consuming quota faster than pods
- Multiple teams sharing a namespace, collectively exceeding the limit
- CI/CD creates temporary pods (build jobs, test runners) that count against quota
- ResourceQuota was recently added to a namespace, and existing pods now use quota
4. Step-by-Step Diagnosis and Fix
Step 1: Identify the quota and current usage
# Check all ResourceQuotas in the namespace
kubectl get resourcequota -n <namespace>
# Detailed view showing used vs hard limits
kubectl describe resourcequota -n <namespace>
# Example output:
# Name: default-quota
# Namespace: production
# Resource Used Hard
# -------- ---- ----
# limits.cpu 14 16
# limits.memory 14Gi 16Gi
# pods 45 50
# requests.cpu 7 8
# The specific failed operation will also show in:
kubectl get events -n <namespace> --field-selector reason=FailedCreate | head -10
Step 2: Find what's consuming quota
# Find memory and CPU hogs
kubectl top pods -n <namespace> --sort-by=memory | head -20
kubectl top pods -n <namespace> --sort-by=cpu | head -20
# Find pods with inflated limits vs actual usage
kubectl get pods -n <namespace> -o json | jq -r '
.items[] |
"\(.metadata.name): cpu_limit=\(.spec.containers[0].resources.limits.cpu // "none"),
mem_limit=\(.spec.containers[0].resources.limits.memory // "none")"'
# Count pods including failed ones (they count against pod quota)
kubectl get pods -n <namespace> --field-selector status.phase=Failed | wc -l
Step 3: Free up quota — clean old pods
# Delete failed/completed pods that still count against quota
kubectl delete pods -n <namespace> --field-selector status.phase=Failed
kubectl delete pods -n <namespace> --field-selector status.phase=Succeeded
# For Jobs: delete completed jobs (which keep pods)
kubectl delete jobs -n <namespace> --field-selector status.conditions[0].type=Complete
Step 4: Fix oversized resource limits
# If pods have unnecessarily high limits, right-size them
# This reduces quota consumption without removing workloads
# Example: reduce overly generous memory limits
kubectl set resources deployment my-app -n <namespace> --requests=cpu=100m,memory=256Mi --limits=cpu=500m,memory=512Mi
# Use VPA recommendations to right-size before adjusting manually:
kubectl describe vpa <vpa-name> -n <namespace>
Step 5: Increase or modify the ResourceQuota
# Edit the quota directly (requires cluster-admin or quota management permissions)
kubectl edit resourcequota <quota-name> -n <namespace>
# Or patch a specific limit:
kubectl patch resourcequota <quota-name> -n <namespace> --type='json' -p='[{"op":"replace","path":"/spec/hard/pods","value":"100"}]'
# Or create a new quota (if none exists):
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
requests.cpu: "8"
requests.memory: 16Gi
limits.cpu: "16"
limits.memory: 32Gi
pods: "100"
5. Verification Steps
# After adjusting quota or freeing resources:
kubectl describe resourcequota -n <namespace>
# Used values should be below Hard limits
# Test that new pods can be created
kubectl run test-pod --image=nginx -n <namespace> --rm --restart=Never -- echo "quota ok"
# Deployments that were blocked should now converge
kubectl get deployment -n <namespace>
# AVAILABLE should equal DESIRED
6. Common Mistakes
- Setting quota limits without setting LimitRange defaults — teams then can't create pods without explicitly setting resource requests, which breaks existing manifests
- Not monitoring quota usage — teams discover they've hit the limit during a production incident, not proactively
- Counting only Running pods when checking quota — Failed and Succeeded pods also count against pod quota
- Setting limits much higher than requests across many pods — each pod's limit counts against quota, even if it never uses that much
- Not considering CI/CD build pods — if your namespace runs build jobs, their temporary pods consume quota during builds
7. Prevention Tips
- Set up Prometheus alerts when quota usage reaches 80% — gives time to scale up or clean up before hitting the limit
- Use LimitRange alongside ResourceQuota to set default requests/limits — prevents "must specify limits" errors when quota exists
- Run CI/CD build pods in a separate namespace with its own quota, isolated from production workloads
- Right-size resource limits using VPA recommendations before setting quota — overestimated limits waste quota
- Pod evictions can indirectly relate to quota — see Fix Kubernetes Pod Evicted for resource sizing guidance for resource sizing guidance
- For HPA to scale beyond current replicas, ensure quota allows the maximum expected replica count
8. FAQ
I deleted old pods but quota usage didn't drop. Why?
Quota counts the aggregate resource requests and limits of all pods with a managed lifecycle — not just Running pods. Check if there are pods in Pending, Unknown, or Init states that are still counting against quota: kubectl get pods -n <namespace> --field-selector status.phase!=Running,status.phase!=Failed,status.phase!=Succeeded
Can I temporarily bypass ResourceQuota for an emergency deployment?
A cluster-admin can temporarily increase the quota: kubectl patch resourcequota <name> -n <namespace> --type=json -p='[{"op":"replace","path":"/spec/hard/pods","value":"200"}]'. Remember to revert after the emergency. Alternatively, deploy to a different namespace that has headroom. Never permanently relax quotas without team review.
9. Summary
| Quota type hit | Symptom | Fix |
|---|---|---|
| pods | FailedCreate: quota exceeded | Delete old pods; increase pod quota |
| requests.cpu/memory | Pod creation fails | Right-size requests; increase quota |
| limits.cpu/memory | Pod creation fails if limits set | Reduce oversized limits; increase quota |
| count/persistentvolumeclaims | PVC creation fails | Delete unused PVCs; increase pvc quota |
| requests.storage | PVC creation fails | Delete unused PVCs; increase storage quota |
Explore More in This Category
Explore more in this category: Kubernetes guides. Browse all DevOps Compass articles or jump to: Kubernetes, AWS, CI/CD, Containers, Monitoring, Networking.