Active Nerds
Module #15 · intermediate Article

OOMKilled Prevention: Container Memory Limits, Cgroups, and Linux OOM Killer

OOMKilled means the container exceeded its memory limit and was killed by the Linux OOM killer — fix by increasing the memory limit, finding and fixing the m...

4 min read+15 XPPublished 2026-05-31

Quick Answer: OOMKilled means the container exceeded its memory limit and was killed by the Linux OOM killer — fix by increasing the memory limit, finding and fixing the memory leak, or using VPA to right-size requests.

Detailed Answer:

# Detect OOMKilled
kubectl describe pod my-pod | grep -i oom
# Last State: Terminated
#   Reason:    OOMKilled
#   Exit Code: 137

# Check current memory limits
kubectl get pod my-pod \
  -o jsonpath='{.spec.containers[0].resources}'
# {"limits":{"memory":"256Mi"},"requests":{"memory":"128Mi"}}

# Monitor actual memory usage (requires metrics-server)
kubectl top pod my-pod --containers

# Check historical memory usage in Prometheus
# container_memory_working_set_bytes{pod="my-pod"} — actual usage
# container_spec_memory_limit_bytes{pod="my-pod"} — the limit

Memory Limit Strategy:

resources:
  requests:
    memory: "256Mi"               # What scheduler uses for placement
  limits:
    memory: "512Mi"               # 2x request — gives burst headroom
                                  # OOMKill happens when usage hits THIS value

# For Java apps (JVM doesn't respect cgroup limits by default):
# Use JVM flags to stay within container limits:
env:
- name: JAVA_OPTS
  value: "-XX:MaxRAMPercentage=75.0 -XX:+UseContainerSupport"
# This tells JVM to use max 75% of the container's memory limit

Right-sizing with VPA (Vertical Pod Autoscaler):

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  updatePolicy:
    updateMode: "Off"             # Recommendation only — don't auto-change
  resourcePolicy:
    containerPolicies:
    - containerName: app
      minAllowed:
        memory: "128Mi"
      maxAllowed:
        memory: "2Gi"

# Check VPA recommendations after running for a while:
kubectl describe vpa my-app-vpa
# Recommendation:
#   Container Recommendations:
#     Container Name: app
#     Target: Memory: 384Mi      ← Use this as your new request/limit

Common Mistake:

Setting memory limit equal to memory request. This creates a Guaranteed QoS pod (which is good for priority) but leaves zero headroom for traffic spikes — a single burst OOMKills the pod. Set limits at 1.5–2x requests for most apps.

Key Takeaway: OOMKilled means your memory limit is too low for actual usage — either increase the limit, fix the leak, or use VPA recommendations to right-size based on real usage data.


Finished reading?

Mark as complete to claim your +15 XP and track progress.