Kubernetes CPU Resource Management
Kubernetes CPU Resource Management ensures efficient resource allocation by setting limits and requests, optimizing cluster performance and workload reliability.
Kubernetes CPU Resource Management is the set of concerns specific to how CPU, as a compressible resource, is requested, allocated, and enforced within Kubernetes — encompassing the millicore unit system used to express fractional CPU, the CFS-based throttling mechanism enforcing limits, and the distinct operational behaviors that follow from CPU being a resource containers can be throttled on rather than killed for exceeding. CPU's defining characteristic in Kubernetes' resource model is that it is compressible: a container that needs more CPU than it currently has can simply be slowed down without losing any state, in sharp contrast to memory, whose enforcement is a hard, unrecoverable kill rather than a graceful slowdown.
This compressibility is what shapes nearly every CPU-specific practice in Kubernetes, from how limits are set to how throttling is diagnosed, and understanding it explains why CPU management conventions differ meaningfully from the more conservative, headroom-heavy conventions typically applied to memory.
The Millicore Unit
Expressing Fractional CPU
CPU quantities are expressed either as whole numbers (1 meaning one full CPU core's worth of time) or in millicores (500m meaning half a core), where one core equals 1000 millicores — this fine-grained unit allows precise, sub-core resource declarations appropriate for the many lightweight containers that do not need a full core's worth of continuous compute.
resources:
requests:
cpu: "250m"
limits:
cpu: "1"
What a "Core" Means in a Virtualized or Shared Environment
A CPU unit in Kubernetes corresponds to one virtual CPU (vCPU) as exposed by the underlying node — on cloud instances, this is typically a hyperthread rather than a full physical core, a detail worth keeping in mind when reasoning about the absolute compute capacity a given CPU request or limit actually represents.
CFS Quota and Period Enforcement
How Limits Become Throttling
A CPU limit is translated by the container runtime into a CFS (Completely Fair Scheduler) quota, measured against a fixed period (commonly 100ms) — a container with a 500m limit is allowed to consume 50ms of CPU time within each 100ms period; once it exhausts that quota, it is throttled (paused) until the next period begins.
Throttling Is Reversible, Not Terminal
Unlike a memory limit violation, exceeding a CPU limit never terminates the container — it simply pauses execution until quota resets, which is why CPU limits can be set more aggressively (closer to actual need) than memory limits without the same catastrophic downside of a hard kill on every overage.
The Throttling Latency Problem
Bursty Workloads and Short Periods
A container whose workload is bursty within short timeframes can be throttled even when its average CPU usage over a longer window appears comfortably within its limit — because CFS periods are typically only 100ms, a request that needs a brief, intense burst of CPU can exhaust its quota for that period well before the next period's allowance becomes available, producing latency spikes that correlate with request bursts rather than with any sustained overuse.
kubectl exec codartium-app -- cat /sys/fs/cgroup/cpu.stat
Checking nr_throttled and throttled_time in the cgroup's CPU statistics directly reveals whether a service experiencing intermittent latency is actually being throttled, which is often a faster diagnostic path than profiling the application code itself.
Mitigating Throttling Latency
Raising the CPU limit (giving more quota per period), or in some cases removing the CPU limit entirely and relying only on the request plus namespace-level ResourceQuota controls, are the two most direct mitigations for throttling-induced latency — the tradeoff being reduced protection for co-located workloads if the limit is removed entirely.
CPU Requests and Scheduling Fairness
Guaranteed Minimum Share
A CPU request, unlike memory, does not represent a hard-reserved chunk of a physical resource in quite the same way — instead, it establishes the container's relative CPU shares under the underlying scheduler's fair-sharing mechanism, guaranteeing it receives at least its requested proportion of CPU time when the node is under contention, while still allowing it to use more when the node has spare capacity and no limit prevents it.
CPU Manager Policies for Exclusive Allocation
For latency-sensitive workloads needing dedicated, exclusive CPU cores rather than shared time-sliced access, the kubelet's CPU Manager, configured with the static policy, can pin Guaranteed QoS Pods with integer CPU requests to specific physical cores, avoiding the scheduling overhead and cache-locality loss that comes from time-sliced sharing.
resources:
requests:
cpu: "2"
memory: "2Gi"
limits:
cpu: "2"
memory: "2Gi"
Example
apiVersion: v1
kind: Pod
metadata:
name: codartium-cpu-example
spec:
containers:
- name: app
image: codartium/app:latest
resources:
requests:
cpu: "500m"
limits:
cpu: "1500m"