Skip to main content

Pod Resource Requests and Limits in Kubernetes

Two numbers per container decide where a pod lands, what it can burst to, and who gets evicted first.

Every container in a Kubernetes pod can declare a request and a limit for CPU and memory. The request is what the container is guaranteed and what the scheduler reserves for it. The limit is the ceiling the node enforces at runtime. Those two numbers drive placement, throttling, eviction order, and, because node count follows reservations, a large share of the cluster bill.

Requests: what the scheduler reserves

When you create a pod, kube-scheduler picks a node where, for each resource type, the sum of the requests of the containers already scheduled plus the new pod stays below the node’s capacity. Actual usage does not enter that calculation. A pod requesting 2 CPUs and using 0.2 still blocks 2 CPUs of capacity. Node autoscalers such as Cluster Autoscaler and Karpenter also size nodes from requests, so inflated requests translate directly into extra nodes.

Requests matter for autoscaling too. The Horizontal Pod Autoscaler expresses utilization as a percentage of the request; if a container has no request, CPU utilization is undefined and the HPA takes no action on that metric.

Limits: how CPU and memory differ

The two resources are enforced differently:

  • CPU limits are enforced by throttling. As the container approaches its limit the kernel restricts its CPU time; Kubernetes describes this as a hard limit. The symptom of a tight CPU limit is latency, not crashes.
  • Memory limits are enforced by the kernel with out-of-memory (OOM) kills. Enforcement is reactive: a container may briefly use more memory than its limit, but if it does, it may be killed.

If you set a limit but no request, and no admission-time default applies, Kubernetes copies the limit into the request.

Units that trip people up

One Kubernetes CPU unit equals one physical or virtual core. 0.1 and 100m (100 millicpu) mean the same thing, and the docs recommend the millicpu form below one CPU to avoid invalid quantities. Memory suffixes are case sensitive: 400m of memory is 0.4 bytes, while 400Mi is 400 mebibytes.

QoS classes and eviction order

Kubernetes assigns each pod a Quality of Service class from its requests and limits:

  • Guaranteed: every container has CPU and memory requests and limits, and each limit equals its request.
  • Burstable: at least one container has a CPU or memory request or limit, but the pod is not Guaranteed.
  • BestEffort: no container has any request or limit.

Under node resource pressure, the kubelet ranks pods by whether their usage exceeds their requests, then by pod priority, then by how far usage exceeds the request. BestEffort and Burstable pods using more than they requested go first; Guaranteed pods and Burstable pods using less than their requests go last. The kubelet does not use the QoS class itself to order evictions, but the class is a good estimate of who goes first, because a BestEffort pod has no request to stay under. Setting requests is therefore a reliability decision as much as a cost one.

Enforcing defaults per namespace

A LimitRange sets default requests and limits for containers that omit them, and can enforce minimums, maximums, and a request-to-limit ratio per pod or container in a namespace. Violations are rejected with HTTP 403 at admission. Two caveats from the docs: LimitRange checks happen only at admission, so existing pods are unchanged when you add one, and if two LimitRanges exist in a namespace it is not deterministic which default applies.

A ResourceQuota caps aggregate consumption per namespace, such as the sum of requests.cpu or limits.memory across non-terminal pods. Once a quota covers CPU or memory, every new pod must specify requests or limits for them, otherwise the quota system may reject it; a LimitRange default is the usual way to avoid that.

Sizing requests in practice

Base requests on observed usage over a representative period, set memory limits with enough headroom to avoid OOM kills during peaks, and revisit after load changes. ZopNight’s Kubernetes workload rules flag containers with missing requests or limits and workloads whose CPU or memory is over-provisioned. The broader picture is in Kubernetes cost optimization, and the namespace-level objects are listed on the LimitRange and ResourceQuota integration pages.

faq

Questions we get a lot.

If yours isn't here, email us and we'll answer directly.

Should I set CPU limits at all?

It is a trade-off. A CPU limit caps a container through throttling, which protects neighbours but can add latency when the container needs to burst. It is not required for scheduling; the request is what the scheduler uses. Note that a pod only gets the Guaranteed QoS class if every container has CPU and memory limits equal to its requests.

What happens if a pod has no requests at all?

If no container sets any request or limit, the pod is BestEffort; any usage exceeds its zero request, so it ranks among the first candidates for eviction under node pressure. The scheduler reserves nothing for it, and an HPA cannot compute CPU utilization for it.

Stop watching the waste.
Start cutting it.

See. Find. Fix. Automatic.

Connect your first cloud account in under 5 minutes. See your first remediation in under 7. No credit card required.

CDCR connect detect classify remediate
full audit every action traceable
read-only default access
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·