The Error
Error from server (Forbidden): pods "my-pod" is forbidden: exceeded quota: my-quota, requested: cpu=500m, used: cpu=900m, limited: cpu=1
Your namespace has a ResourceQuota cap, and this pod pushed it over. The error message spells out the math: quota limit is 1000m CPU, 900m is already claimed, and you're requesting 500m more β that's 1400m total. Kubernetes rejects it outright.
The pod never enters Pending state. It gets blocked at the API server before the scheduler even sees it.
Step 1: Check the Current Quota Usage
Start by seeing exactly what's consumed versus what's allowed:
# Replace 'my-namespace' with your actual namespace
kubectl describe resourcequota -n my-namespace
Output looks like:
Name: my-quota
Namespace: my-namespace
Resource Used Hard
-------- ---- ----
cpu 900m 1
memory 512Mi 2Gi
pods 8 10
CPU is the culprit here β 900m used out of a 1000m hard limit. Only 100m left, nowhere near enough for a pod requesting 500m.
To scan quotas across all namespaces at once:
kubectl get resourcequota --all-namespaces
Step 2: Find What's Consuming the Quota
Before touching anything, identify which pods are eating up that 900m:
kubectl get pods -n my-namespace -o custom-columns=NAME:.metadata.name,CPU:.spec.containers[*].resources.requests.cpu
Got metrics-server installed? kubectl top shows actual usage, not just declared requests:
kubectl top pods -n my-namespace
Watch for the mismatch. A pod requesting 500m CPU but averaging 30m in practice is a prime right-sizing target.
Step 3: Fix Options
Option A β Reduce the Pod's Resource Request
Inflated requests are the most common culprit. If the pod doesn't genuinely need 500m, dial it down in your manifest:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
namespace: my-namespace
spec:
containers:
- name: my-container
image: my-image:latest
resources:
requests:
cpu: "100m" # was 500m, reduced to 100m
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"
Run kubectl top pods first to pick a realistic value. Setting requests to 100m for a pod that averages 80m gives a safe buffer without wasting quota.
Option B β Increase the ResourceQuota Limit
Sometimes the namespace just needs more headroom. Check the current quota definition first:
kubectl get resourcequota my-quota -n my-namespace -o yaml
Patch it directly:
kubectl patch resourcequota my-quota -n my-namespace \
--type='json' \
-p='[{"op": "replace", "path": "/spec/hard/cpu", "value": "2"}]'
Or, if you manage quotas as YAML files (the recommended approach), update and apply:
apiVersion: v1
kind: ResourceQuota
metadata:
name: my-quota
namespace: my-namespace
spec:
hard:
cpu: "2" # increased from 1 to 2
memory: 4Gi
pods: "20"
kubectl apply -f resourcequota.yaml
Option C β Delete Unused Pods or Scale Down Deployments
Completed and failed pods still count against the quota until deleted. Clean up the graveyard:
# Delete completed/failed pods
kubectl delete pods -n my-namespace --field-selector=status.phase==Succeeded
kubectl delete pods -n my-namespace --field-selector=status.phase==Failed
# Scale down a deployment that's no longer needed
kubectl scale deployment old-deployment -n my-namespace --replicas=0
Worth checking before anything else β a namespace full of stale Completed jobs can quietly hold hundreds of millicores. You might free up enough quota without touching the limit at all.
Step 4: Verify the Fix
Once you've made your changes, confirm the quota has headroom before retrying:
# Check updated quota usage
kubectl describe resourcequota -n my-namespace
# Try creating the pod again
kubectl apply -f my-pod.yaml
# Confirm it's running
kubectl get pod my-pod -n my-namespace
Expected output:
NAME READY STATUS RESTARTS AGE
my-pod 1/1 Running 0 10s
Tips for Next Time
- Always set resource requests and limits β namespaces with ResourceQuota reject pods that have no requests/limits defined at all. Use a
LimitRangeto set namespace-wide defaults if you don't want to specify them on every pod. - Pair LimitRange with ResourceQuota β
LimitRangesets per-container defaults;ResourceQuotacaps the namespace total. They're designed to work together. - Gate your CI/CD on quota checks β add a pre-deploy step that runs
kubectl describe resourcequota -n $NAMESPACEand fails the pipeline if available CPU drops below your deployment's request size. - Base requests on real metrics, not guesses β use
kubectl top podsor pull a week of p95 CPU data from Prometheus. That's a far better input than "500m sounds about right." - Quota is policy, not physics β this error means you've hit an administrative cap, not a physical resource shortage. The node may have plenty of free CPU. ResourceQuota is purely a governance limit set by your cluster admin.

