3.6 Resource Requests, Limits & Namespace ResourceQuotas
Key Takeaways
- Resource Requests represent guaranteed compute capacity used by kube-scheduler for Pod placement; Limits represent hard ceilings enforced by Linux cgroups at runtime.
- CPU is a compressible resource subject to CFS bandwidth throttling when limits are exceeded; Memory is incompressible and triggers OOM Killer (exit code 137) upon breach.
- Kubernetes assigns Guaranteed, Burstable, or BestEffort QoS from requests and limits; node-pressure eviction ranks Pods by usage above requests, Pod Priority, and relative excess usage rather than a fixed QoS ladder.
- LimitRanges define default, minimum, and maximum resource allocations per container/pod within a namespace, automatically injecting defaults if requests are omitted.
- ResourceQuotas enforce aggregate namespace-wide caps on compute resources (CPU/memory), storage requests, and object counts (Pods, Services, Secrets).
Resource Requests, Limits & Namespace ResourceQuotas
In multi-tenant Kubernetes clusters, uncontrolled workloads can monopolize CPU and memory, causing noisy neighbor problems, performance degradation, and node starvation. Kubernetes provides a robust, multi-tiered resource governance model: Requests and Limits at the container level, Quality of Service (QoS) classes at the Pod level, and LimitRanges and ResourceQuotas at the namespace level.
1. Requests vs Limits: Scheduling and Runtime Enforcement
Understanding the precise mechanical distinction between resource requests and resource limits is fundamental to Kubernetes operations and CKA exam success.
+-----------------------------------------------------------------------------------------+
| REQUESTS VS LIMITS MECHANICS |
| |
| +---------------------------------------+ +-------------------------------------+ |
| | RESOURCE REQUESTS | | RESOURCE LIMITS | |
| | - Used by: kube-scheduler | | - Enforced by: Linux cgroups | |
| | - Role: Guaranteed minimum allocation| | - Role: Hard maximum threshold | |
| | - Node selection: Capacity >= Sum(Req| | - Exceeding CPU: Throttling (CFS) | |
| +---------------------------------------+ | - Exceeding Memory: OOMKilled (137)| |
| +-------------------------------------+ |
+-----------------------------------------------------------------------------------------+
CPU Resources (Compressible)
- Units: Measured in millicores (
m) or whole cores (1000m = 1 vCPU / Core / Hyperthread). A request of250mrepresents 25% of a CPU core. - Behavior Under Contention: CPU is a compressible resource. If a container attempts to consume more CPU than its allocated limit, the Linux kernel Completely Fair Scheduler (CFS) throttles the container by restricting its CPU execution time slices (using
cpu.cfs_quota_usandcpu.cfs_period_usin cgroups v1, orcpu.maxin cgroups v2). The container experiences latency and reduced processing throughput, but the process is never killed.
Memory Resources (Incompressible)
- Units: Measured in bytes or power-of-two mebibytes/gibibytes (
Mi,Gi) or decimal megabytes/gigabytes (M,G).1Mi = 1,048,576 bytes, whereas1M = 1,000,000 bytes. - Behavior Under Contention: Memory is an incompressible resource. If a container consumes all its allocated memory and attempts to allocate more beyond its
limits.memory, the Linux kernel triggers the Out Of Memory (OOM) Killer. The kernel immediately sends aSIGKILL(Signal 9) to the container process, terminating it with Exit Code 137 (128 + 9).kubectl describe podwill displayReason: OOMKilled.
Ephemeral Storage Requests and Limits
Kubernetes also supports tracking local node storage (including container writable layers, container logs in /var/log/pods, and emptyDir volumes):
requests.ephemeral-storage: Informs the scheduler of minimum disk capacity needed on the node.limits.ephemeral-storage: Hard cap. If anemptyDirvolume or container writable layer exceeds this limit, thekubeletevicts the Pod from the node.
apiVersion: v1
kind: Pod
metadata:
name: backend-processor
namespace: production
spec:
containers:
- name: app
image: redis:7.0-alpine
resources:
requests:
cpu: "250m"
memory: "512Mi"
ephemeral-storage: "1Gi"
limits:
cpu: "1000m"
memory: "1Gi"
ephemeral-storage: "2Gi"
2. Quality of Service (QoS) Classification
The kube-scheduler and kubelet automatically assign every Pod to one of three Quality of Service (QoS) classes based entirely on how requests and limits are configured across all containers in the Pod:
+-----------------------------------------------------------------------------------------+
| QOS DETERMINATION MATRIX |
| |
| 1. GUARANTEED (Highest Priority | oom_score_adj: -997) |
| - Every container in Pod has CPU & Memory Requests AND Limits defined. |
| - CPU Request == CPU Limit AND Memory Request == Memory Limit for all containers. |
| |
| 2. BURSTABLE (Moderate Priority | oom_score_adj: 100 - 999) |
| - At least one container has a CPU or Memory Request. |
| - Does not meet the strict equality criteria of Guaranteed. |
| |
| 3. BESTEFFORT (Lowest Priority | oom_score_adj: 1000) |
| - No Requests and no Limits set for ANY container in the Pod. |
+-----------------------------------------------------------------------------------------+
| QoS Class | Qualification Requirement | Typical memory OOM adjustment |
|---|---|---|
| Guaranteed | Every container specifies CPU and memory requests and limits, with each request equal to its limit. | Strong protection (commonly -997) |
| Burstable | At least one container has a request or limit, but the Pod does not qualify as Guaranteed. | Calculated from requested memory |
| BestEffort | No container has CPU or memory requests or limits. | Least protection (commonly 1000) |
The OOM adjustment affects the Linux kernel OOM killer. Kubelet node-pressure eviction is a separate ranking process. For a resource such as memory, kubelet first separates Pods whose current usage exceeds their requests from those that do not. Within the relevant group it considers Pod Priority, then how far usage exceeds the request. A BestEffort Pod has a zero request and commonly ranks as exceeding it, but a fixed “BestEffort, then Burstable, then Guaranteed” ordering is not guaranteed. A high-priority BestEffort Pod can outlive a lower-priority Burstable Pod that is also over request.
Pods whose usage is below requests are not immune if kubelet cannot reclaim enough resource. Static Pods and system-critical workloads also have priority considerations. Diagnose actual decisions through node events and kubelet logs rather than inferring solely from the displayed QoS class.
3. LimitRanges---
3. LimitRanges: Namespace Defaulting and Boundaries
A LimitRange is a namespaced resource that automatically injects default requests/limits into incoming Pods and enforces boundary constraints (min/max size).
apiVersion: v1
kind: LimitRange
metadata:
name: core-resource-limits
namespace: staging
spec:
limits:
- type: Container
default: # Default LIMIT if omitted by user
cpu: "500m"
memory: "512Mi"
defaultRequest: # Default REQUEST if omitted by user
cpu: "100m"
memory: "256Mi"
max: # Maximum allowed request/limit per container
cpu: "2000m"
memory: "2Gi"
min: # Minimum allowed request/limit per container
cpu: "50m"
memory: "64Mi"
maxLimitRequestRatio:
cpu: "4" # Limit cannot exceed 4x the Request
- type: Pod
max:
cpu: "4000m"
memory: "4Gi"
[!NOTE] If a developer applies a Pod manifest with no
resourcesblock in a namespace with an active LimitRange, the Admission Controller automatically mutates the Pod manifest, populating it with thedefaultRequestanddefaultlimit values.
4. ResourceQuotas: Namespace Capacity Caps
A ResourceQuota restricts total aggregate resource consumption across an entire namespace, preventing any single team or project from consuming all cluster compute, storage, or object counts.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-compute-quota
namespace: staging
spec:
hard:
requests.cpu: "4" # Max total CPU requests across all Pods in namespace
requests.memory: "8Gi" # Max total Memory requests across all Pods
limits.cpu: "8" # Max total CPU limits
limits.memory: "16Gi" # Max total Memory limits
pods: "10" # Max number of Pods allowed in namespace
services: "5" # Max number of Services
services.loadbalancers: "1" # Max cloud load balancers
persistentvolumeclaims: "4" # Max PVC count
requests.storage: "100Gi" # Max total persistent storage allocation
The ResourceQuota Golden Rule
If a ResourceQuota restricts compute resources (requests.cpu or requests.memory), every single Pod submitted to that namespace MUST explicitly specify resource requests (either in its YAML manifest or automatically through an active LimitRange). If requests are omitted and no LimitRange exists, the API server rejects the Pod creation with a 403 Forbidden error (exceeded quota: ... is missing request for cpu).
Quota Scopes and PriorityClasses
ResourceQuotas can be restricted to specific Pod subsets using spec.scopes:
Terminating: Applies only to Pods withspec.activeDeadlineSeconds >= 0.NotTerminating: Applies only to long-running Pods (activeDeadlineSecondsunset).BestEffort: Applies only to Pods with BestEffort QoS.NotBestEffort: Applies to Guaranteed and Burstable Pods.scopeSelector: Matches Pods based onPriorityClassnames.
5. CKA Exam CLI Commands & Troubleshooting Workflows
# Inspect ResourceQuota status and current utilization in a namespace
kubectl get resourcequota -n staging
kubectl describe resourcequota team-compute-quota -n staging
# Inspect LimitRange rules in a namespace
kubectl describe limitrange core-resource-limits -n staging
# Check live compute utilization of nodes and pods
kubectl top nodes
kubectl top pods -n staging --containers
# Troubleshoot Pod rejection due to quota breach
kubectl get events -n staging --field-selector reason=FailedCreate --sort-by=.metadata.creationTimestamp
A Pod has two containers: Container A specifies requests: {cpu: 200m, memory: 256Mi} and limits: {cpu: 200m, memory: 256Mi}. Container B specifies requests: {cpu: 100m, memory: 128Mi} and limits: {cpu: 500m, memory: 512Mi}. What is the Quality of Service (QoS) class assigned to this Pod?
An administrator creates a ResourceQuota in namespace 'staging' setting 'hard.requests.cpu: "2"'. A developer tries to deploy a Pod with 'kubectl run nginx --image=nginx'. The command fails with an error stating that the quota was violated. Why was the request rejected even if total namespace CPU usage was 0?
What happens at the operating system level when a container's processes attempt to allocate 1200Mi of RAM on a node when the container manifest sets resources.limits.memory: "1Gi"?