Requests, limits and quotas
Requests, limits and quotas
resources:
requests: { cpu: "250m", memory: "128Mi" } # guaranteed, used for scheduling
limits: { cpu: "500m", memory: "256Mi" } # hard ceiling, enforced by cgroups
Units: 1 CPU = 1 core = 1000m. Memory Mi/Gi (binary), M/G (decimal).
| Request | Limit | |
|---|---|---|
| Used by | scheduler (node must have it free) | kubelet / kernel at runtime |
| CPU over it | fine, if the node has spare | throttled - slower, not killed |
| Memory over it | fine, until the node is short | OOMKilled - container restarts |
graph LR
N["Node allocatable 4 CPU"] --> A["Pod A request 1"]
N --> B["Pod B request 2"]
N --> F["free for scheduling: 1"]
The scheduler counts requests, not real usage.
QoS classes
| Class | When | Evicted under memory pressure |
|---|---|---|
| Guaranteed | requests = limits for CPU and memory, every container | last |
| Burstable | at least one request or limit set | middle |
| BestEffort | nothing set | first |
kubectl get pod web -o jsonpath='{.status.qosClass}'
Guard rails per namespace
LimitRange - defaults and min/max per container:
apiVersion: v1
kind: LimitRange
metadata: { name: defaults, namespace: team-a }
spec:
limits:
- type: Container
defaultRequest: { cpu: "100m", memory: "64Mi" }
default: { cpu: "500m", memory: "256Mi" } # default limit
max: { memory: "1Gi" }
ResourceQuota - totals for the whole namespace:
apiVersion: v1
kind: ResourceQuota
metadata: { name: team-a, namespace: team-a }
spec:
hard:
pods: "10"
requests.cpu: "2"
requests.memory: 4Gi
limits.memory: 8Gi
With a CPU/memory quota, every Pod must declare those resources (or get
them from a LimitRange) - otherwise it is rejected. The rejection shows on the
ReplicaSet (FailedCreate), not on a Pod.
Seeing usage
kubectl top nodes|pods needs metrics-server (installed in Lab 19).