Kubernetes resource requests and limits: CPU, memory and scheduling explained

Learn how Kubernetes resource requests and limits work with practical examples. Covers CPU throttling, OOMKilled, FailedScheduling, millicores, and memory units.

9 lessons · 27 min · Intermediate

3 minutes reading time

Written by

Civo Team
Civo Team

Marketing Team at Civo

Resource requests and limits tell Kubernetes how much CPU and memory a container needs and how much it is allowed to use.

Requests are the minimum guaranteed resources. Kubernetes uses them when deciding which node to schedule a pod on. A pod will not be placed on a node that cannot satisfy its requests.

Limits are the maximum a container can use. If a container tries to use more CPU than its limit, Kubernetes throttles it. If it tries to use more memory than its limit, the Linux kernel kills the process and Kubernetes reports it as OOMKilled.

resource-requests-limits

Units reference

This is the most commonly confused aspect of resource specifications.

ResourceUnitExampleMeaning

CPU

millicores

500m

Half a CPU core

CPU

cores

1

One full CPU core

Memory

mebibytes

128Mi

128 x 1,048,576 bytes (binary)

Memory

megabytes

128M

128 x 1,000,000 bytes (SI)

Use Mi for memory in almost all cases. The i suffix denotes binary units, which is what the Linux kernel and Kubernetes runtime actually measure. 100M and 100Mi are close but not equal — 100Mi is approximately 4.9% larger than 100M. When in doubt, use Mi.

CPU is always specified in cores or millicores. 1000m equals 1 CPU core. 500m is half a core.

Resource spec example

apiVersion: v1
kind: Pod
metadata:
name: cpu-mem-demo
spec:
containers:
- name: demo
image: busybox
command: ["sh", "-c", "while true; do :; done"]
resources:
requests:
cpu: "500m"
memory: "100Mi"
limits:
cpu: "1"
memory: "200Mi"
kubectl apply -f cpumem.yaml
kubectl get pods

Inspect the resource configuration:

kubectl describe pod cpu-mem-demo

The output includes a Resources section showing the requests and limits you defined.

Scenario 1: CPU throttling

When a container tries to use more CPU than its limit, Kubernetes throttles it. The container keeps running but its CPU usage is capped.

In the example above, the container runs an infinite loop trying to use as much CPU as possible. The limit is 1 core. Even if the application requests more, it will be throttled to stay within the limit.

Check actual CPU usage with the metrics server:

kubectl top pod

Expected output — usage is capped near the limit:

NAME CPU(cores) MEMORY(bytes)
cpu-mem-demo 999m 2Mi

CPU throttling is invisible to the application. The process does not crash or receive a signal. It simply runs slower than it would without a limit.

Scenario 2: insufficient CPU: pod stuck in Pending

If a pod requests more CPU than any node in the cluster can provide, Kubernetes cannot schedule it and it stays in Pending state indefinitely.

Edit the YAML to request 3 CPU cores on a 2-core node and apply it:

kubectl apply -f cpumem.yaml
kubectl get pods

Expected output:

NAME READY STATUS RESTARTS AGE
cpu-mem-demo2 0/1 Pending 0 10s

Describe the pod to see the reason:

kubectl describe pod cpu-mem-demo2

The Events section shows:

Warning FailedScheduling default-scheduler 0/2 nodes are available: 2 Insufficient cpu.

The pod will stay in Pending until either a node with sufficient CPU is added or the request is reduced. Delete the stuck pod:

kubectl delete pod cpu-mem-demo2 --force --grace-period=0

Scenario 3: memory limit exceeded: OOMKilled

When a container tries to allocate more memory than its limit, the Linux kernel's out-of-memory killer terminates the process. Kubernetes reports this as OOMKilled in the pod status.

Edit the YAML so the container tries to allocate 250Mi but the limit is only 200Mi, then apply it:

kubectl apply -f cpumem.yaml
kubectl get pods

Expected output:

NAME READY STATUS RESTARTS AGE
cpu-mem-demo 0/1 OOMKilled 0 5s

After a few restarts it moves to CrashLoopBackOff:

kubectl get pods

Expected output:

NAME READY STATUS RESTARTS AGE
cpu-mem-demo 0/1 CrashLoopBackOff 3 45s

What OOMKilled means and what to do

The container exceeded its memory limit and the Linux kernel terminated it. To fix it, either increase the memory limit in the YAML, reduce the application's memory usage, or investigate a memory leak if usage was not expected to be this high.

Clean up:

kubectl delete pod cpu-mem-demo2 --force --grace-period=0
Civo Team
Civo Team

Marketing Team at Civo

Civo is the Sovereign Cloud and AI platform designed to help developers and enterprises build without limits. We bridge the gap between the openness of the public cloud and the rigorous security of private environments, delivering full cloud parity across every deployment. As a team, we are dedicated to providing scalable compute, lightning-fast Kubernetes, and managed services that are ready in minutes. Through CivoStack Enterprise and our FlexCore appliance, we empower organizations to maintain total data sovereignty on their own hardware.

Our mission is to make the cloud faster, simpler, and fairer. By providing enterprise-grade NVIDIA GPUs and streamlined model management, we ensure that high-performance AI and machine learning are accessible to everyone. Built for transparency and performance, the Civo Team is here to give you total control over your infrastructure, your data, and your spend.

View author profile