Why might a pod with `limits.memory: 4G` get OOMKilled when you expected roughly 4 GiB of headroom?
Quick Answer
Because `4G` is decimal: 4,000,000,000 bytes ≈ 3.72 GiB — about 280–295 MB *less* than `4Gi` (4,294,967,296 bytes). The kubelet writes 4,000,000,000 into the cgroup limit, and once the container's memory crosses that, the kernel OOM killer terminates it. An app tuned for 4 GiB routinely trips this smaller-than-expected ceiling.
Detailed Answer
This is the classic 'memory trap.' You think 4G means 4 GiB, but Kubernetes takes it literally as 4 × 10^9 bytes. That is ~93% of a real 4Gi. The kubelet sets the container cgroup's memory limit (memory.limit_in_bytes on cgroup v1, memory.max on cgroup v2) to that exact byte value. The Linux OOM killer enforces it against the container's RSS plus unreclaimable page cache.
So a workload that peaks near 4 GiB — a JVM with -Xmx4g, a Go service with a 4Gi cache, Redis sized to 4Gi — will exceed a 4G limit and be OOMKilled with exit code 137, even though the manifest 'looks like' 4 GB. The fix is to write 4Gi, and to size requests/limits and the app's own memory settings in the same (binary) units.
Code Example
# Symptom
kubectl get pod api-0 -o jsonpath='{.status.containerStatuses[0].lastState.terminated.reason}'
# -> OOMKilled (exit code 137)
# Wrong
limits: { memory: "4G" } # 4,000,000,000 bytes (~3.72Gi)
# Right
limits: { memory: "4Gi" } # 4,294,967,296 bytesInterview Tip
Mention exit code 137 and that the cgroup limit is the exact byte count — interviewers want the mechanism, not just "use Gi".