Out of Memory 개념 정리

Linux OOM 개념과 분석 절차입니다. OOM killer 로그, MemAvailable, swap, RSS, cgroup/systemd 제한, Docker OOMKilled, swap 추가와 재발 방지 기준을 정리했습니다.

Out of Memory(OOM)는 Linux 커널이 더 이상 안전하게 메모리를 할당하기 어렵다고 판단해 프로세스를 강제로 종료하는 상황입니다. 단순히 “메모리가 부족했다”로 끝내면 안 되고, 어떤 cgroup 또는 프로세스가 압박을 만들었는지, swap은 있었는지, OOM killer가 무엇을 죽였는지까지 확인해야 합니다.

OOM 로그 읽기

대표 로그는 다음과 같습니다.

kernel: Out of memory: Killed process 1234 (httpd) total-vm:123456kB, anon-rss:12345kB, file-rss:0kB, shmem-rss:0kB
kernel: oom_reaper: reaped process 1234 (httpd), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

anon-rss는 프로세스가 실제로 잡고 있던 익명 메모리, file-rss는 파일 매핑 메모리, shmem-rss는 shared memory 성격의 메모리입니다. DB, JVM, 웹서버, 컨테이너 런타임은 각자 다른 패턴으로 보입니다.

로그 검색

journalctl -k --no-pager | egrep -i 'out of memory|oom-killer|killed process|oom_reaper' | tail -n 120
dmesg -T | egrep -i 'out of memory|oom-killer|killed process|oom_reaper' | tail -n 120

# RHEL 계열 레거시 로그
sudo egrep -i 'out of memory|oom-killer|killed process' /var/log/messages*

# Ubuntu/Debian 계열
sudo egrep -i 'out of memory|oom-killer|killed process' /var/log/syslog*

현재 메모리 상태

free -h
swapon --show
vmstat 1 5
cat /proc/meminfo | egrep 'MemTotal|MemAvailable|SwapTotal|SwapFree|Dirty|Writeback|Slab|SReclaimable|SUnreclaim'

MemAvailable이 낮고 swap이 가득 차 있으면 전형적인 메모리 압박입니다. Slab이나 SUnreclaim이 비정상적으로 크면 커널 slab 증가도 봐야 합니다.

프로세스별 메모리 확인

ps -eo pid,ppid,stat,rss,vsz,pmem,comm,args --sort=-rss | head -n 20
top -o %MEM
pidstat -r 1 5

특정 프로세스 하나가 꾸준히 증가하면 누수 가능성을 보고, 여러 프로세스가 동시에 증가하면 트래픽 증가, worker 수 과다, 캐시 설정, 배치 작업을 봅니다.

systemd/cgroup 환경 확인

컨테이너나 systemd 서비스 단위에서 OOM이 난 경우 전체 서버 메모리는 남아 있어도 해당 cgroup 제한 때문에 죽을 수 있습니다.

systemctl status your-service --no-pager
systemctl show your-service -p MemoryCurrent -p MemoryMax -p OOMPolicy
cat /sys/fs/cgroup/memory.current 2>/dev/null || true
cat /sys/fs/cgroup/memory.max 2>/dev/null || true

Docker/컨테이너 환경이면 컨테이너 제한과 OOMKilled 여부를 같이 봅니다.

docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}'
docker inspect --format '{{.Name}} OOMKilled={{.State.OOMKilled}} ExitCode={{.State.ExitCode}}' <container>
docker stats --no-stream

swap 추가 예시

swap은 근본 해결책은 아니지만 급한 OOM 재발을 줄이는 완충 장치가 될 수 있습니다. 디스크 여유와 성능 영향을 보고 적용합니다.

sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
swapon --show
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

재발 방지 기준

  • 서비스별 메모리 상한을 명확히 둡니다. JVM, DB buffer pool, 웹 worker 수를 확인합니다.
  • OOM 로그를 알림으로 연결합니다. journalctl -k 검색만 수동으로 하면 늦습니다.
  • 컨테이너는 host 메모리와 container limit을 함께 봅니다.
  • swap 추가는 임시 완충이고, 누수나 과도한 worker 설정은 별도로 고쳐야 합니다.
  • OOM이 DB를 죽였으면 데이터 정합성 확인과 재기동 로그 점검이 필요합니다.

OOM 분석의 핵심은 “누가 죽었는지”보다 “왜 그 프로세스가 선택될 정도로 메모리 압박이 생겼는지”입니다. 로그, 현재 메모리, 프로세스 RSS, cgroup 제한, swap 상태를 같이 봐야 원인을 놓치지 않습니다.

BGM EVER