OOM Killer — 메모리 부족 시 프로세스 종료 전략
서버에서 갑자기 프로세스가 죽었다면, OOM Killer가 범인일 수 있습니다. 리눅스 커널이 메모리 부족 상황에서 어떤 프로세스를 죽이는지, 어떻게 방어할 수 있는지 알아봅니다.
OOM Killer란
OOM(Out of Memory) Killer 는 시스템 메모리가 부족할 때 커널이 프로세스를 강제 종료 하여 메모리를 확보하는 메커니즘입니다.
메모리 부족 → 커널 메모리 할당 실패
→ 페이지 캐시 회수 시도
→ 스왑 활용 시도
→ 그래도 부족하면
→ OOM Killer 발동 → 프로세스 선택 → SIGKILL 전송
OOM Score
커널은 각 프로세스에 OOM Score (0~1000)를 부여하고, 가장 높은 점수의 프로세스를 종료 합니다.
점수 계산 기준:
- 메모리 사용량이 많을수록 높은 점수
- 자식 프로세스의 메모리도 합산
- root 프로세스는 약간 감점
oom_score_adj(-1000 ~ 1000)으로 조정 가능
# 프로세스별 OOM Score 확인
cat /proc/$PID/oom_score
# OOM Score 조정값 확인
cat /proc/$PID/oom_score_adj
# OOM 면제 설정 (-1000 = 절대 죽이지 않음)
echo -1000 > /proc/$PID/oom_score_adj
# OOM 우선 대상 설정 (1000 = 최우선 종료)
echo 1000 > /proc/$PID/oom_score_adj
OOM Killer 발동 확인
# 커널 로그에서 OOM 확인
dmesg | grep -i "oom\|out of memory\|killed process"
# 전형적인 OOM 로그:
# Out of memory: Killed process 1234 (java) total-vm:8192000kB,
# anon-rss:4096000kB, file-rss:1000kB, shmem-rss:0kB
# journald에서 확인
journalctl -k | grep -i oom
메모리 Overcommit
리눅스는 기본적으로 메모리 오버커밋(overcommit) 을 허용합니다.
cat /proc/sys/vm/overcommit_memory
# 0: 적당히 오버커밋 허용 (기본값, 휴리스틱)
# 1: 항상 오버커밋 허용 (malloc 절대 실패 안 함)
# 2: 오버커밋 금지 (물리 메모리 + 스왑 이내만 허용)
오버커밋이 문제를 일으키는 시나리오:
물리 메모리: 8GB
프로세스 A: malloc(4GB) → 성공 (아직 실제 사용 안 함)
프로세스 B: malloc(4GB) → 성공
프로세스 C: malloc(4GB) → 성공 (12GB 약속, 8GB만 있음)
세 프로세스가 모두 실제로 메모리를 쓰기 시작하면...
→ OOM Killer 발동!
OOM 방어 전략
1. 중요 프로세스 보호
# DB 프로세스를 OOM에서 보호
echo -1000 > /proc/$(pidof mysqld)/oom_score_adj
2. cgroup으로 메모리 제한
# 특정 서비스의 메모리를 제한
# systemd unit에서:
# [Service]
# MemoryMax=2G
# MemoryHigh=1.5G # 이 이상이면 스왑 사용 유도
3. 오버커밋 비활성화
# 오버커밋 금지 (Redis 서버 등에서 권장)
echo 2 > /proc/sys/vm/overcommit_memory
echo 80 > /proc/sys/vm/overcommit_ratio # 물리메모리의 80%까지만
4. 애플리케이션 레벨
# JVM 힙 크기 명시적 설정
java -Xmx2g -Xms2g -jar app.jar
# 물리 메모리의 70% 이하로 설정하는 것이 안전
핵심 포인트
- OOM Killer가 발동하는 조건: 물리 메모리 + 스왑 모두 부족, 페이지 캐시 회수도 불가
- 어떤 프로세스를 죽이는가: OOM Score가 가장 높은 것 (메모리 사용량 기반)
- 오버커밋과 OOM의 관계: malloc은 성공했지만 실제 물리 메모리가 부족하면 OOM
- 실제 대응: 중요 프로세스는
oom_score_adj=-1000, cgroup으로 메모리 제한
정리
OOM Killer는 시스템 전체가 멈추는 것을 방지하기 위한 최후의 수단입니다. 서버 운영에서 OOM은 사전에 방지하는 것이 가장 좋고, 발생했을 때 로그를 빠르게 확인하여 원인을 파악하는 것이 중요합니다.