CKA ResourceQuota versus LimitRange the pod refused at admission and the defaults that admit it
The quota asks whether the namespace can afford the pod. The LimitRange writes the numbers the pod forgot.
<!-- hal:authoritative:yaml -->
The quota asks whether the namespace can afford the pod. The LimitRange writes the numbers the pod forgot. Read the error to learn which one spoke.
§I. Frame
CKA day, even counter. Recent CKA lessons took HPA (09-30), storage binding (09-24), Gateway API (09-18), and NetworkPolicy (09-09). Admission came up on 10-03 as a CKS attestor. Today stays on two admission plugins that kube-apiserver enables by default: LimitRanger, which mutates, and ResourceQuota, which validates. Mutation runs before validation, which is why a LimitRange can rescue a pod the quota would refuse.
Every transcript below is real output from a local k3s v1.34.12 cluster run for this lesson.
§II. Two objects, two jobs
| ResourceQuota | LimitRange | |
|---|---|---|
| Scope | Sum across the namespace | One container, pod, or PVC |
| Keys | requests.cpu, limits.memory, pods, count/... | default, defaultRequest, min, max, maxLimitRequestRatio |
| Effect | Refuses a create that breaks the sum | Fills missing values, refuses outliers |
| When | Admission, plus a live used tally | Admission only |
Neither object changes pods that already exist.
§III. The refusal
Namespace tenant-a, quota compute-quota with requests.cpu: 2, requests.memory: 2Gi, limits.cpu: 4, limits.memory: 4Gi, pods: 10. No LimitRange yet. A pod with no resources block:
$ kubectl apply -f bare-pod.yaml
Error from server (Forbidden): error when creating "bare-pod.yaml": pods "bare" is forbidden: failed quota: compute-quota: must specify limits.cpu for: app; limits.memory for: app; requests.cpu for: app; requests.memory for: app
A pod with requests but no limits:
pods "requests-only" is forbidden: failed quota: compute-quota: must specify limits.cpu for: app; limits.memory for: app
Read the Verb (named technique). failed quota ... must specify means the quota meters a key the container left empty. exceeded quota means the sum would pass hard. They need different fixes. The first needs a value on the container. The second needs smaller requests or a larger quota.
The quota demands each key it lists. Listing limits.* makes limits mandatory even when requests are set.
§IV. The fix: LimitRange defaults
apiVersion: v1
kind: LimitRange
metadata: {name: tenant-defaults, namespace: tenant-a}
spec:
limits:
- type: Container
defaultRequest: {cpu: 250m, memory: 256Mi}
default: {cpu: 500m, memory: 512Mi}
max: {cpu: "1", memory: 1Gi}
The same two manifests now pass. The bare pod got every value from the LimitRange, and the plugin left an annotation:
{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"250m","memory":"256Mi"}}
kubernetes.io/limit-ranger: LimitRanger plugin set: cpu, memory request for container app; cpu, memory limit for container app
The requests-only pod kept its own requests and took only the default limits. Then:
$ kubectl describe quota compute-quota -n tenant-a
Resource Used Hard
-------- ---- ----
limits.cpu 1 4
limits.memory 1Gi 4Gi
pods 2 10
requests.cpu 500m 2
requests.memory 512Mi 2Gi
§V. Exceeded quota, and where a Deployment hides it
After a third pod at 1 CPU / 1Gi, a fourth identical pod:
pods "big2" is forbidden: exceeded quota: compute-quota, requested: requests.cpu=1,requests.memory=1Gi, used: requests.cpu=1500m,requests.memory=1536Mi, limited: requests.cpu=2,requests.memory=2Gi
A Deployment does not show that error at create time. In tenant-c (quota requests.cpu: 1, 900m used), kubectl create deployment api printed created. Then:
$ kubectl get deploy api -n tenant-c
NAME READY UP-TO-DATE AVAILABLE AGE
api 0/1 0 0 5s
$ kubectl describe rs -n tenant-c
Warning FailedCreate 4s replicaset-controller Error creating: pods "api-9599f5f64-mmwx6" is forbidden: exceeded quota: compute-quota, requested: requests.cpu=1,requests.memory=1Gi, ...
0/1 with no pods means look at the ReplicaSet events, not the pods.
Why did api ask for a full CPU when its manifest set nothing? tenant-c had a LimitRange written with only max: {cpu: "1", memory: 1Gi}. The API server filled default from max and defaultRequest from default. kubectl get limitrange -o yaml shows all three at 1 and 1Gi. A ceiling-only LimitRange hands every bare container its ceiling as a request.
§VI. Scopes
A quota can meter a subset of pods. scopeSelector.matchExpressions takes a scopeName: BestEffort, NotBestEffort, Terminating (has activeDeadlineSeconds), NotTerminating, PriorityClass (with In/NotIn values), CrossNamespacePodAffinity, or VolumeAttributesClass for PVCs. A PriorityClass In [high] quota counts only pods with priorityClassName: high. kubectl describe quota lists every quota in the namespace, one table each.
§VII. Drill
must specify requests.memory for: app. Which object, which fix? Quota. Setrequests.memoryon the container or add a LimitRangedefaultRequest.- Deployment
0/3, no pods listed. First command?kubectl describe rs(orkubectl get events) forFailedCreate. - A LimitRange is added with defaults. Do running pods change? No. Admission only.
- A LimitRange sets only
max: {cpu: 2}. What request does a bare container get?2, throughdefaultthendefaultRequest. - Quota lists
requests.cpuonly. Pod setslimits.cpu: 500mand no request. Admitted? Yes. The request defaults to the limit, sorequests.cpuis stated.
§VIII. Close
Two plugins, two jobs. LimitRanger fills and bounds each container. ResourceQuota meters the namespace and refuses the create that breaks it. Read the Verb: must specify points at the container, exceeded points at the sum. On a Deployment, the ReplicaSet events hold the answer.
Paired Ops declares an AKS managed namespace and censuses the gaps. Paired Dev computes used + candidate <= hard with a typed Quantity and matches the big2 refusal above.
Related
- Tome: Poulton, The Kubernetes Book ch5 p.55 (
kubectl describe nsquota and LimitRange lines) (grounded-in) - Bootcamp: CKA-PREP-2025-v2 Question 4 resource allocation (referenced)
- Prior Cert: CKS attestation 10-03 · CKA HPA 09-30 · CKA storage 09-24
- Web: kubernetes.io Resource Quotas · Limit Ranges · Configure Memory and CPU Quotas for a Namespace