쿠버네티스 용어 사전
트러블슈팅Exit Code 137 · 메모리 초과 · MaxRAMPercentage

OOMKilled 진단

커널이 SIGKILL로 죽인 것이라 애플리케이션 로그가 남지 않는다. 런타임이 limit을 인식해야 한다.

kubectl describe pod web | grep -A5 'Last State'
#   Last State:  Terminated
#     Reason:    OOMKilled
#     Exit Code: 137

메모리 limit 을 넘겨 커널이 프로세스를 죽인 상태 137 = 128 + 9 (SIGKILL)

로그가 안 남는다

  • SIGKILL 은 잡을 수 없다

  • 종료 훅 · 셧다운 로그 · 스택 덤프가 전혀 돌지 않는다

  • 애플리케이션 로그의 마지막 줄이 평범한 처리 로그다

  • 확인은 밖에서 한다

    • kubectl describe pod Last State 의 Reason
    • kubectl get events -A | grep -i oom
    • 노드에서: dmesg | grep -i "killed process"

런타임이 limit 을 인식해야 한다

cgroup 은 커널 수준 제한이라, 런타임이 모르면 호스트 전체 메모리를 기준으로 판단한다

JVM 은 Java 10+ 에서 컨테이너 제한을 인식한다 (UseContainerSupport) -XX:MaxRAMPercentage=75 limit 대비 비율로 힙을 잡는다 -Xmx 를 직접 주면 limit 이 바뀌어도 안 따라간다

주의 — 힙 밖에도 메모리가 든다 메타스페이스 · 코드 캐시 · 스레드 스택 · 다이렉트 버퍼 · GC 구조 힙을 limit 의 100% 로 잡으면 반드시 OOMKilled 된다 실무 감각은 limit 의 60~75%

컨테이너 OOM 과 노드 OOM 을 구분한다

  • 컨테이너 OOM — 그 cgroup 의 limit 초과 → 그 컨테이너만 죽는다

    • Reason: OOMKilled 로 명확히 표시된다
  • 노드 압박 — 노드 전체 메모리 부족 → kubelet 이 파드를 '퇴출' 한다

    • Reason: Evicted, 메시지에 MemoryPressure
    • BestEffort → Burstable → Guaranteed 순으로 쫓겨난다
    • limit 을 안 건 파드가 원인인 경우가 많다
  • 둘은 조치가 다르다

    • 전자 — 그 파드의 limit 이나 사용량을 본다
    • 후자 — 노드 전체 배치와 limit 미설정 파드를 본다

제한 부족인지 누수인지

  • 제한 부족 — 사용량이 limit 근처에서 평평하다가 튄다
    • 부하가 오를 때만 발생한다
  • 누수 — 사용량이 시간에 따라 계속 우상향한다
    • 부하와 무관하게 며칠 뒤 발생한다

메모리 그래프를 며칠 단위로 보면 둘이 바로 갈린다 제한만 올리면 누수는 시점만 미뤄진다

메모리 지표를 정확히 읽는다

  • container_memory_working_set_bytes OOM 판정에 쓰이는 값
  • container_memory_usage_bytes — 페이지 캐시를 포함해 더 크게 보인다
  • container_memory_rss — 익명 메모리

kubectl top 은 working set 을 보여 준다

usage 만 보고 "limit 에 가깝다" 고 판단하면 오진한다 캐시는 압박이 오면 회수되므로 그것만으로 OOM 이 나지는 않는다

재현이 안 될 때

OOM 은 피크에만 발생해 평소 그래프에서 안 보인다

  • 스크레이프 주기(보통 15~30초)보다 짧은 스파이크는 안 잡힌다
  • 그래서 "메모리가 여유로운데 OOM 이 난다" 로 보인다

대응

  • memory.peak(cgroup v2) 또는 컨테이너 런타임의 최대치 지표를 본다
  • 힙 덤프를 남기게 한다
    • -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dump
    • (단 컨테이너 OOM 은 JVM OOM 이 아니라 덤프가 안 남을 수 있다)
  • limit 을 일시적으로 크게 올려 실제 피크를 관찰한다

면접 함정

  • "OOM이면 애플리케이션 로그에 남는다" → SIGKILL이라 아무것도 안 남는다.
  • "limit만 올리면 해결" → 누수면 시점만 미뤄진다. 그래프로 먼저 구분한다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 트러블슈팅 — 증상에서 원인으로