Kubernetes OOMKilled: 먼저 볼 것들
마지막 업데이트

Kubernetes OOMKilled: 먼저 볼 것들


Pod 가 OOMKilled 라면 Kubernetes 는 컨테이너가 memory limit 에 걸려 커널에 의해 종료됐다고 알려 주는 것입니다. 여기서 중요한 질문은 단순히 “limit 을 올릴까?” 가 아닙니다. 실제로 leak 또는 retention 이 있는지, bursty memory behavior 인지, 아니면 request 와 limit sizing 이 현실 운영에 맞지 않는지 구분해야 합니다.

짧게 말하면 핵심은 이것입니다. usage pattern 과 limit 을 같이 봐야 합니다. limit 하나를 올린다고 leak 이 해결되지는 않고, 너무 낮은 limit 은 멀쩡한 workload 를 비정상처럼 보이게 만들 수 있습니다.


usage pattern 과 limit 을 같이 본다

메모리 incident 는 단순화하기 쉽습니다.

실제로는 아래를 같이 봐야 합니다.

  • 실제 memory usage
  • steady growth 인지 short spike 인지
  • requests 와 limits
  • restart timing

이걸 같이 보지 않으면 undersizing 인지, retention 인지, burst pressure 인지 구분하기 어렵습니다.


OOMKilled 는 보통 무엇을 뜻하나

실전에선 보통 아래 중 하나입니다.

  • memory limit 이 너무 낮다
  • 애플리케이션이 메모리를 너무 오래 붙잡는다
  • classic leak 이 아니어도 짧은 spike 가 limit 을 넘는다
  • request / limit sizing 이 동작을 헷갈리게 만든다

restart reason 은 명확해도, fix path 는 usage shape 에 따라 달라집니다.


흔한 원인

1. memory limit 이 너무 낮다

workload 자체는 정상인데 configured limit 이 현실적인 peak usage 보다 낮을 수 있습니다.

특히 이런 뒤 자주 보입니다.

  • traffic 증가
  • payload 증가
  • 동시 작업 증가

2. 애플리케이션이 메모리를 누수하거나 오래 붙잡는다

memory 가 꾸준히 올라가다가 결국 limit 을 치고 죽을 수 있습니다.

이게 항상 고전적인 forever leak 은 아닙니다. unbounded cache, queue, 큰 retained graph 도 운영상으로는 같은 결과를 만들 수 있습니다.

3. bursty workload 가 짧은 spike 를 만든다

leak 이 아니어도 cache, request, parsing, batch work 가 짧은 spike 로 limit 을 넘길 수 있습니다.

평균 usage 만 보면 이런 incident 는 랜덤해 보이기 쉽습니다.

4. requests 와 limits 가 어긋나 있다

request sizing 이 나쁘면 scheduling 과 runtime behavior 가 함께 해석하기 어려워집니다.

배치될 때의 가정과, 실제 runtime limit 이 너무 다르게 느껴질 수 있습니다.

5. 진짜 문제는 다른 데서 시작됐다

queue backlog, retry, downstream slowdown 이 pod 내부 retention 을 간접적으로 키울 수도 있습니다.

그래서 OOM incident 는 memory setting 만의 문제가 아니라 workload behavior 와도 자주 연결됩니다.


실전 점검 순서

1. pod 가 정말 memory pressure 로 죽었는지 확인한다

pod 가 불안정하다고 해서 모든 restart 가 OOM 인 것은 아닙니다.

restart reason 이 실제로 memory kill 인지 먼저 확인해야 합니다.

2. memory usage trend 와 configured limit 을 비교한다

알고 싶은 것은 이렇습니다.

  • memory 가 꾸준히 오르는가
  • 급격히 spike 하는가
  • restart 직전 limit 에 얼마나 가까워지는가

3. steady growth 와 short spike 를 구분한다

이 구분이 매우 중요합니다.

steady growth 는 retention 또는 leak 성향을 시사합니다.

short spike 는 burst workload 나 너무 빡빡한 limit 을 시사합니다.

4. workload 또는 dependency 변화가 메모리 동작을 바꿨는지 본다

최근 아래 변화가 설명이 되는 경우가 많습니다.

  • request size
  • traffic level
  • concurrency
  • response aggregation
  • retry

5. usage pattern 이 분명해진 뒤에만 requests / limits 를 바꾼다

메모리를 더 주면 시간을 벌 수는 있지만, retention 이 진짜 문제라면 진단을 대신해선 안 됩니다.


빠른 명령

kubectl describe pod <pod> -n <ns>
kubectl top pod <pod> -n <ns>
kubectl get pod <pod> -n <ns> -o yaml

restart reason, 실제 memory usage, requests / limits 를 한 번에 비교하기 좋은 기본 조합입니다.

memory spike 가 limit 근처에서 반복되는지, OOM kill event 가 이어지는지, requests / limits 가 workload 에 비해 어색하지 않은지 보세요.


메모리 패턴을 찾은 뒤 무엇을 바꾸면 좋나

limit 이 그냥 너무 낮다면

관측된 peak 에 맞춰 의도적으로 올려야 합니다.

retention 이 문제라면

더 큰 limit 에 기대기보다 cache, queue, object lifetime 동작을 먼저 고쳐야 합니다.

spike 가 문제라면

workload 를 더 부드럽게 만들거나 burst 에 맞는 limit 을 잡아야 합니다.

requests 가 misleading 하다면

scheduling 과 runtime behavior 가 같이 말이 되도록 workload 에 맞게 조정해야 합니다.

backlog 로 시작한 incident 라면

pod 메모리 ceiling 뿐 아니라 backlog 원인도 함께 고쳐야 합니다.


장애 중에 던져볼 질문

이 질문이 꽤 유용합니다.

memory 가 계속 자라다가 죽은 건가, 아니면 정상 운영에서도 나올 수 있는 burst 가 잠깐 limit 을 넘긴 건가?

이 구분이 fix 방향을 거의 결정해 줍니다.


FAQ

Q. 그냥 limit 을 먼저 올리면 되나

undersizing, burst usage, retention 중 무엇인지 보기 전에는 권하지 않습니다.

Q. 가장 빠른 첫 단계는 무엇인가

OOM kill 여부를 확인하고, 실제 memory usage 와 current limit 을 비교하는 것입니다.

Q. 모든 OOMKilled 가 memory leak 인가

아닙니다. spike, backlog, limit undersizing 도 매우 흔합니다.

Q. requests 도 중요한가, limits 만 중요하지 않나

requests 는 placement 와 cluster behavior 에 영향을 주고, limits 는 kill threshold 를 만든다는 점에서 둘 다 중요합니다.


Sources:

먼저 읽어볼 가이드

검색 유입이 많은 핵심 글부터 이어서 보세요.