KubernetesCIX · LimitRangeLimitRange
Container defaults — the foundation of resource accounting
What you'll learn
- Configure container defaults (default, defaultRequest)
- Apply the overcommit strategy via defaults
- Reason about the operational impact
- Apply the operational discipline of setting sensible defaults
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
Container defaults in LimitRange ensure every container is declared. This lesson walks the defaults, the admission behaviour, the overcommit strategy, and the discipline.
The default fields
apiVersion: v1
kind: LimitRange
metadata:
name: container-defaults
namespace: tenant-a-prod
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
The default fields:
- default. Limits applied to containers that
don’t specify them. If a container has no
limits, the admission controller adds the defaults. - defaultRequest. Requests applied to containers
that don’t specify them. If a container has no
requests, the admission controller adds the defaults.
The admission controller’s behaviour:
- The user submits a Pod.
- The LimitRange admission plugin checks each container.
- If a container has no
requests, thedefaultRequestis applied. - If a container has no
limits, thedefaultis applied. - The Pod is stored with the applied defaults.
The overcommit strategy
flowchart LR
A[default] --> B[500m CPU]
C[defaultRequest] --> D[100m CPU]
B --> E["Limit: 500m"]
D --> F["Request: 100m"]
E --> G["Overcommit ratio: 5x"]
F --> G
The overcommit strategy:
- default at 500m CPU. The container can use up to 500m.
- defaultRequest at 100m CPU. The scheduler reserves 100m.
- Overcommit ratio: 5x. 5 containers with default requests can fit on a node that has 1 container’s worth of CPU at full limits.
The trade-off:
- High overcommit. More containers per node; lower density; bursts more likely to throttle.
- Low overcommit. Fewer containers per node; higher density; bursts less likely.
The default ratio
flowchart TD
A["Default ratio"] --> B{"Ratio"}
B -->|"1:1 (default = defaultRequest)"| C["Guaranteed QoS"]
B -->|"2:1 to 5:1"| D["Burstable QoS"]
B -->|"> 5:1"| E["BestEffort QoS if no requests; high overcommit"]
The default-to-request ratio determines the QoS:
- 1:1. Default = defaultRequest. Containers are Guaranteed QoS.
- 2:1 to 5:1. Default > defaultRequest. Containers are Burstable QoS.
- > 5:1. Very high overcommit. Containers may frequently throttle.
Most production deployments use a 2:1 to 5:1 ratio.
Observing defaults
kubectl describe pod myapp-pod -n tenant-a-prod
Containers:
app:
Image: myapp
Limits:
cpu: 500m # from default
memory: 512Mi # from default
Requests:
cpu: 100m # from defaultRequest
memory: 128Mi # from defaultRequest
...
The Pod spec reflects the applied defaults. If the container originally had no resources, the defaults are now visible.
Setting sensible defaults
flowchart LR
A[Setting defaults] --> B[Observe typical workload sizes]
B --> C[Set default at typical]
C --> D[Set defaultRequest at 50% of default]
D --> E[Test with new Pods]
E --> F["Adjust if too tight/loose"]
The discipline:
- Observe typical workload sizes. Use
kubectl topor metrics to determine typical CPU and memory. - Set default at typical. 500m CPU, 512Mi memory is a reasonable starting point for many workloads.
- Set defaultRequest at 50% of default. 100m CPU, 128Mi memory.
- Test with new Pods. Verify the defaults produce the expected QoS.
- Adjust if too tight/loose. Quarterly review.
Quiz
Knowledge check · 4 questions
Q1. When are LimitRange defaults applied to a container?
Q2. Changing a LimitRange updates the defaults on Pods that were already created.
Q3. A Java service starts being OOMKilled the day after a LimitRange is introduced; explain the link and fix it properly.
`billing-worker` in `finance-prod` ran for a year with no `resources` block. A LimitRange with `default.memory: 512Mi` and `defaultRequest.memory: 128Mi` was applied yesterday, and the Deployment was rolled this morning. `kubectl describe pod` now shows `Last State: Terminated, Reason: OOMKilled, Exit Code: 137` with three restarts in twenty minutes, and the container's Limits section reads `memory: 512Mi`. The JVM is started without any heap flag.
Q4. A Container LimitRange sets `default.memory: 512Mi` and `defaultRequest.memory: 128Mi`. A container declares `limits.memory: 1Gi` and no requests. What memory request does it end up with?
Passing score: 75%. Answers are checked in this browser.
The operational discipline
Container defaults in production rest on five non-negotiable elements:
- Set defaults for every namespace. No namespace should be without defaults.
- Match defaults to typical workloads. 500m/512Mi is a starting point; adjust based on observation.
- Set defaultRequest at 50% of default. Allow bursting.
- Verify defaults in practice. Quarterly: create a Pod without resources; verify defaults are applied.
- Document the defaults. The runbook lists each namespace’s defaults.
Defaults are the foundation of resource accounting. Without defaults, the quota is meaningless.