리눅스 OOM Killer 동작 로직과 메모리 압박 상황 대응 전략
리눅스 서버를 운영하다 보면 예기치 않게 특정 프로세스가 종료되고, 로그에 “Out of memory” 메시지가 남는 경험을 하게 됩니다. 이는 단순 오류가 아니라, 시스템 전체 멈춤을 막기 위한 리눅스 OOM Killer 동작 로직이 발동한 결과입니다. 오늘은 실제 운영 환경에서 OOM Killer가 어떤 방식으로 동작하는지, 그리고 메모리 압박 상황에서 어떻게 대응하면 되는지 전략적 관점에서 상세히 설명해드리려고 합니다.
목차
- OOM Killer란 무엇인가
- 메모리 부족 발생 시 커널의 판단 구조
- OOM Score 기반 희생 프로세스 선정 방식
- dmesg 로그로 OOM 상황 분석하는 방법
- 메모리 압박을 줄이기 위한 커널/시스템 튜닝 전략
- Docker·Kubernetes 환경에서의 OOM 대응
- 운영 환경 체크리스트 정리
1. OOM Killer란 무엇인가
리눅스에서 OOM Killer는 메모리가 부족해 더 이상 할당할 수 없는 상황이 되었을 때, 시스템 전체가 다운되지 않도록 특정 프로세스를 강제 종료시키는 보호 장치입니다. 메모리가 완전히 고갈되면 커널 패닉이나 서버 응답 불능 상태가 발생하기 때문에, 리눅스는 전체를 살리기 위해 일부 프로세스를 희생시키는 방식으로 안정성을 확보합니다. 이 동작은 자동으로 이루어지며 관리자 개입 없이 즉시 실행됩니다.
2. 메모리 부족 발생 시 커널의 판단 구조
커널은 메모리가 부족해지면 여러 단계를 거쳐 대응합니다.
먼저 페이지 캐시 정리, 스왑 아웃 등 기본적인 메모리 회수 작업을 진행합니다.
다음으로 cgroup의 메모리 제한을 초과한 프로세스가 있는지 확인합니다.
이후에도 부족하다면 커널은 각 프로세스의 메모리 점유량과 중요도를 계산해 종료 대상을 선정합니다.
이 모든 단계에서 실패할 때 마지막으로 OOM Killer가 작동합니다.
이 구조를 이해하면 시스템이 왜 특정 시점에 프로세스를 종료했는지 합리적으로 분석할 수 있습니다.
3. OOM Score 기반 희생 프로세스 선정 방식
OOM Killer가 프로세스를 무작위로 종료하는 것은 아닙니다. 리눅스는 각 프로세스에 OOM Score라는 점수를 부여해 종료할 순서를 결정합니다. 메모리를 많이 사용하는 프로세스일수록 점수가 높습니다. 또한 시스템 중요한 서비스는 oom_score_adj 값을 낮춰 보호할 수 있습니다.
예를 들어 웹 서버, 데이터베이스 등 핵심 프로세스는 낮은 adj 값을 설정해 보호하고, 무거운 배치 프로그램이나 중요도가 낮은 백그라운드 작업은 상대적으로 높은 점수로 종료 대상으로 분류됩니다.
이 정보는 /proc/PID/oom_score 와 oom_score_adj 파일에서 확인할 수 있어 실무적으로 매우 유용합니다.
4. dmesg 로그로 OOM 상황 분석하는 방법
OOM Killer가 발동하면 dmesg 또는 /var/log/messages 에 상세 로그가 기록됩니다. 여기에는 종료된 프로세스, 사용한 메모리 양, OOM Score, 호출 당시 전체 메모리 상태 등이 포함됩니다.
이 로그를 통해 어떤 서비스가 메모리를 과도하게 사용했는지, 특정 프로세스가 누수를 일으켰는지, cgroup 설정이 잘못되었는지 판단할 수 있습니다. 운영 환경에서는 OOM 로그 분석이 문제 조치의 핵심 단계입니다.
5. 메모리 압박을 줄이기 위한 커널/시스템 튜닝 전략
OOM을 예방하기 위해 다음과 같은 튜닝이 실무에서 널리 사용됩니다.
swappiness 조정을 통해 스왑 정책을 변경합니다.
vm.overcommit_memory 설정으로 메모리 예약 정책을 조절합니다.
Transparent Huge Pages(THP) 기능을 비활성화해 불필요한 메모리 사용을 줄일 수 있습니다.
또한 메모리 누수가 있는 프로그램은 시스템 재시작 스케줄(예: systemd timer)로 관리하기도 합니다.
이러한 설정은 단순히 OOM을 막는 수준이 아니라 전체 서버 안정성을 높이는 데도 도움됩니다.
6. Docker·Kubernetes 환경에서의 OOM 대응
컨테이너 환경에서는 OOM이 더욱 빈번하게 생길 수 있습니다. cgroup 메모리 제한을 넘으면 시스템 전체가 아닌 특정 컨테이너만 종료되기 때문입니다.
Kubernetes에서는 OOMKilled 이벤트가 발생하며, Pod가 CrashLoopBackOff로 빠질 수 있습니다.
문제 해결을 위해서는 memory limit과 request 값을 합리적으로 설정해야 하며, OOM 발생 시 kubectl describe나 Pod 로그로 원인을 확인해야 합니다.
컨테이너 기반 환경에서 OOM 분석은 필수적인 운영 지식입니다.
7. 운영 환경 체크리스트 정리
OOM 대비를 위해 다음 내용을 항상 점검하는 것이 좋습니다.
프로세스별 oom_score_adj 설정이 적절한가
스왑 사용 정책(swappiness)이 적절한가
Kubernetes limit/request 값이 실제 워크로드와 맞는가
메모리 누수를 일으키는 애플리케이션이 있는가
로그(dmesg)를 주기적으로 수집하고 있는가
이런 점검 포인트는 서버가 불시에 다운되는 상황을 예방하는 데 큰 역할을 합니다.
마무리 정리
리눅스 OOM Killer는 서버가 완전히 중단되는 것을 막기 위해 존재하는 중요한 보호 장치입니다. 그러나 예고 없이 프로세스를 종료시키기 때문에, 운영자는 OOM의 동작 원리와 로그 분석 방법을 정확히 이해하고 있어야 합니다. 또한 커널 튜닝, cgroup 설정, 컨테이너 메모리 정책 등을 적극적으로 적용하면 OOM 발생을 크게 줄일 수 있습니다.
메모리 압박 상황에 대한 이해와 사전 대비는 서버 안정성을 높이는 가장 확실한 방법입니다.