KubernetesCVIII · ResourceQuotaResourceQuota
Compute quotas — CPU and memory budgets per namespace
What you'll learn
- Configure compute quotas (requests.cpu, requests.memory, limits.cpu, limits.memory)
- Reason about requests vs limits and the overcommit strategy
- Monitor quota utilisation
- Apply the operational discipline of setting compute quotas deliberately
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
Compute quotas bound the CPU and memory that a namespace can request or limit. This lesson walks the compute quota fields, the overcommit strategy, the observability, and the operational discipline.
The compute quota fields
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: tenant-a-prod
spec:
hard:
requests.cpu: "32"
requests.memory: 64Gi
limits.cpu: "64"
limits.memory: 128Gi
The four fields:
- requests.cpu. Sum of all Pods’ CPU requests cannot exceed 32 cores.
- requests.memory. Sum of all Pods’ memory requests cannot exceed 64 GiB.
- limits.cpu. Sum of all Pods’ CPU limits cannot exceed 64 cores.
- limits.memory. Sum of all Pods’ memory limits cannot exceed 128 GiB.
The scheduler uses requests to decide if a Pod fits on a node. The kubelet uses limits to enforce runtime limits. The quota bounds both, and it does so at admission — before the scheduler ever sees the Pod.
The overcommit strategy
flowchart LR
A[Requests] --> B[Drives scheduling]
A --> C[Used for bin-packing]
D[Limits] --> E[Runtime ceiling]
D --> F["CPU throttling, memory OOM"]
G["Overcommit: requests < limits"]
G --> H[70% of limits as requests]
H --> I[30% headroom for bursting]
The overcommit strategy:
- requests at 70% of limits. A Pod requests 70% of its limit; the scheduler reserves 70% but the Pod can burst to 100%.
- 30% headroom. The scheduler has headroom for bursting workloads (rollouts, scaling events).
- Quality of Service. Pods with requests == limits are Guaranteed; Pods with requests < limits are Burstable.
The trade-off: more headroom allows more bursting but reduces scheduling efficiency; less headroom maximises density but risks OOM kills.
LimitRange for defaults
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: tenant-a-prod
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
max:
cpu: 2
memory: 4Gi
LimitRange supplies the values for Pods that do not set
their own. Without it, a Pod submitted into a namespace
that has a compute quota and that declares neither
requests nor limits for the constrained resource is
rejected at admission. The quota is not bypassed — the
Pod simply never gets created, and the workload author
sees a forbidden: failed quota error instead of a
running Pod.
Observability
kubectl describe resourcequota compute-quota -n tenant-a-prod
Name: compute-quota
Namespace: tenant-a-prod
Resource Used Hard
-------- ---- ----
requests.cpu 24 32
requests.memory 48Gi 64Gi
limits.cpu 48 64
limits.memory 96Gi 128Gi
The Used column shows current usage; the Hard
column shows the quota. Monitor the Used vs Hard
ratio to detect approaching-quota namespaces.
kube_resourcequota{resource="requests.cpu", type="used"} / kube_resourcequota{resource="requests.cpu", type="hard"}
The type label is what separates the two series;
without it the numerator matches both used and hard
and the expression returns nothing useful.
Alert when utilisation exceeds 80%:
- alert: ResourceQuotaNearLimit
expr: kube_resourcequota{resource="requests.cpu", type="used"} / kube_resourcequota{resource="requests.cpu", type="hard"} > 0.8
for: 5m
annotations:
summary: "Namespace {{ $labels.namespace }} is approaching CPU quota"
Setting compute quotas
flowchart LR
A[Setting compute quotas] --> B[Start with observed usage]
B --> C[Add 30-50% headroom]
C --> D[Set as requests quota]
D --> E[Set limits at 2x requests]
E --> F[Monitor and adjust]
The discipline:
- Start with observed usage. Use metrics to determine current CPU and memory consumption.
- Add 30-50% headroom. Allow room for growth and bursts.
- Set as requests quota.
requests.cpuandrequests.memory. - Set limits at 2x requests.
limits.cpuandlimits.memoryallow bursting. - Monitor and adjust. Quarterly review.
Quiz
Knowledge check · 4 questions
Q1. Why can a namespace hit its `requests.cpu` quota while its Pods use little CPU?
Q2. Raising a ResourceQuota is the correct first response to a namespace that has exhausted it.
Q3. An HPA cannot scale out although the namespace's CPU request budget has headroom; find the exhausted quota key and clear it.
`checkout` has an HPA with `maxReplicas: 40` and has been pinned at 32 replicas for an hour while CPU utilisation sits at 92 per cent. `kubectl describe resourcequota compute -n checkout-prod` shows `requests.cpu 25600m / 64` and `limits.cpu 64 / 64`. The ReplicaSet's events read `exceeded quota: compute, requested: limits.cpu=2, used: limits.cpu=64, limited: limits.cpu=64`. Each container declares `requests.cpu: 800m` and `limits.cpu: 2`.
Q4. A namespace's `requests.cpu` quota is 32 and the cluster has 200 idle cores. A Pod requesting 40 cores is rejected. Which component rejected it, and does raising the quota make the Pod schedulable?
Passing score: 75%. Answers are checked in this browser.
The operational discipline
Compute quotas in production rest on five non-negotiable elements:
- LimitRange for defaults. Every Pod gets requests, so nothing is rejected for omitting them.
- requests at 70% of limits. Bursting headroom.
- Monitor utilisation. Alert when approaching quota.
- Set quotas deliberately. Not too tight, not too loose.
- Review quarterly. Workloads change; quotas must adapt.
Compute quotas are production contracts. Treat them deliberately and monitor the contract.