## TL;DR
Exit code 137 with reason `OOMKilled` means the container blew past its own memory limit: raise the limit or fix the leak. Status `Evicted` with reason `Evicted` means the node ran out of memory and the kubelet killed the pod: add node capacity or fix the noisy neighbor. The pod description tells you which one in seconds; do not raise limits for an eviction, it will not help.

## Error / query
```text
how to tell OOMKilled from node-pressure eviction
```

## Use this skill when
- A pod died with exit code 137 and you are not sure why
- Pods show `Evicted` and you need to know if it is node pressure
- Memory limit increases are not stopping the kills
- You need to decide between raising limits vs adding nodes

## Not for this skill when
- The pod is CPU-throttled but alive (different problem)
- The container exits 0 or 1 (app logic, not memory)
- Pods are Pending (scheduling, not killing)

## Steps

### Step 1: Read the pod's last termination state
```bash
kubectl get pod [pod-name] -n [namespace] -o jsonpath='{.status.containerStatuses[0].lastState.terminated}{"\n"}'
```
Expected: JSON with `reason` and `exitCode`. `reason: OOMKilled, exitCode: 137` is the container limit. `reason: Error` with a different code is an app crash, not memory.

### Step 2: Check for eviction on the pod
```bash
kubectl get pod [pod-name] -n [namespace] -o jsonpath='{.status.phase}{"\n"}{.status.reason}{"\n"}'
```
Expected: `Failed` with `reason: Evicted` means the kubelet killed it for node pressure. OOMKilled pods show `Failed` with no eviction reason and keep their container statuses; evicted pods are replaced by the controller.

### Step 3: Check the node's memory pressure at the time
```bash
kubectl describe node [node-name] | grep -B2 -A5 MemoryPressure
kubectl top node [node-name]
```
Expected: `MemoryPressure: True` (or recent pressure events in node events) alongside evictions confirms the node ran dry. OOMKilled with a healthy node points squarely at the pod's limit.

### Step 4: Compare usage against the limit
```bash
kubectl top pod [pod-name] -n [namespace] --containers
kubectl get pod [pod-name] -n [namespace] -o jsonpath='{.spec.containers[0].resources.limits.memory}{"\n"}'
```
Expected: for OOMKilled, usage was at or above the limit right before death. If usage was far below the limit, suspect a sudden spike (check with a memory graph) rather than a too-low limit.

## Variant phrasings

### "exit 137 oomkilled vs evicted"
Step 1 settles it: `reason: OOMKilled` vs `status.reason: Evicted`.

### "pod evicted but memory limit not reached"
That is node pressure by definition. Look at the node's other pods; one of them is the memory hog, not yours.

## Why it happens
Two different killers share exit code 137. The container runtime's OOM killer fires when a single container exceeds its cgroup memory limit. The kubelet eviction manager fires when the whole node runs out of memory (or disk, or PIDs) and kills pods by QoS class to protect the node. Same symptom, opposite fixes.

## Edge cases and pitfalls
- Burstable pods get evicted before Guaranteed ones; if your pod is always the victim, its QoS class is the reason, not its usage.
- Java apps often die at the limit because heap plus off-heap exceeds it; set `-Xmx` below the container limit.
- Node pressure from disk or PID exhaustion also evicts with similar messages; check all pressure conditions, not just memory.
- Metrics-server has a delay; `kubectl top` right after a kill may show nothing. Use your monitoring history for the minutes before the kill.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_Y-GRk59WhYM2L3jZTdCkLQ
