Kubernetes Memory Resource Management
Kubernetes Memory Resource Management ensures efficient memory allocation and prevents out-of-memory errors in containerized applications.
Kubernetes Memory Resource Management is the set of concerns specific to how memory, as an incompressible resource, is requested, allocated, and enforced within Kubernetes — a fundamentally different enforcement model from CPU, since memory cannot be "throttled" the way CPU time can; a container exceeding its memory limit is terminated outright by the kernel's OOM killer, with no graceful degradation path. This incompressibility is the defining fact that shapes every memory-specific practice in Kubernetes, from why memory limits require more conservative headroom than CPU limits, to why memory-related eviction and OOM events are treated as more urgent operational signals than CPU throttling typically is.
Because there is no equivalent to CPU's period-based quota system for memory, once a container's memory usage reaches its limit, the outcome is immediate and terminal rather than a temporary slowdown.
Byte Units and Quantities
Binary vs. Decimal Suffixes
Memory quantities use either binary suffixes (Ki, Mi, Gi, based on powers of 1024) or decimal suffixes (K, M, G, based on powers of 1000) — 256Mi (268,435,456 bytes) is meaningfully larger than 256M (256,000,000 bytes), and using the wrong suffix by habit or typo is a common, easy-to-miss sizing mistake.
resources:
requests:
memory: "256Mi"
limits:
memory: "512Mi"
OOM Termination
The Kernel's OOM Killer
When a container's memory usage exceeds its cgroup limit, the kernel's out-of-memory killer terminates the offending process immediately — this is a hard, unrecoverable event from the container's perspective; there is no warning period, throttling phase, or graceful degradation, only immediate termination followed by the kubelet restarting the container according to the Pod's restartPolicy.
kubectl describe pod codartium-app | grep -A 5 "Last State"
A Reason: OOMKilled entry in the container's last termination state is the definitive signal that the memory limit, not an application crash, was the direct cause.
Distinguishing Container-Limit OOM from Node-Level OOM
A container OOM-killed for exceeding its own cgroup limit is a distinct event from a node experiencing system-wide memory pressure severe enough to trigger the kubelet's eviction manager — the former is a per-container enforcement outcome tied directly to that container's declared limit; the latter is a node-wide condition that can affect multiple Pods simultaneously, prioritized by QoS class rather than by any single container's limit.
Sizing Memory Requests and Limits
Conservative Headroom Above Observed Peak
Because exceeding a memory limit is terminal rather than gracefully degraded, memory limits are conventionally set with more headroom above observed peak usage than CPU limits typically require — a common practice is sizing the limit to comfortably exceed the highest peak observed under realistic load testing, rather than the average or median usage.
The Cost of Overly Generous Requests
While limits benefit from headroom, requests should still track actual steady-state usage reasonably closely, since an inflated request (set far above real usage "just to be safe") reserves capacity on the node that goes unused, directly increasing the node count needed to run a given fleet of workloads.
Memory and QoS Class Eviction Priority
BestEffort Pods Are Evicted First
Under node memory pressure, BestEffort Pods (no memory request or limit set at all) are the first candidates for eviction, since they made no resource guarantee and thus receive the least protection.
Burstable Pods Are Ranked by Usage-to-Request Ratio
Among Burstable Pods, the kubelet prioritizes evicting those whose current memory usage most exceeds their request proportionally — a Pod using far more memory than it requested is evicted before one using memory closer to (or below) its requested baseline, even if the latter's absolute usage is higher.
Guaranteed Pods Are Evicted Last
Guaranteed QoS Pods (requests equal to limits for every resource) receive the strongest protection against node-pressure eviction, reflecting that they made the strictest resource commitment and are assumed to be the most operationally critical.
Memory Overcommitment Risk
Requests Enable Overcommitment on Limits
Because scheduling only accounts for requests, a node can host Pods whose combined limits exceed physical memory capacity — relying on the assumption that not every Pod will simultaneously reach its full limit. Under a correlated spike (many Pods hitting high memory usage at once, perhaps due to a shared traffic surge), this overcommitment can produce node-wide memory pressure and eviction cascades even though each individual Pod's scheduling passed fit checks cleanly.
Example
apiVersion: v1
kind: Pod
metadata:
name: codartium-memory-example
spec:
containers:
- name: app
image: codartium/app:latest
resources:
requests:
memory: "512Mi"
limits:
memory: "768Mi"
kubectl top pod codartium-memory-example --containers