16강 / 20강

메모리가 모자랄 때 — 스왑과 OOM Killer

free 를 제대로 읽고, 워커 메모리를 계산한다

메모리가 모자랄 때 — 스왑과 OOM Killer
메모리가 모자라면 리눅스는 누군가를 죽입니다. 그게 여러분의 앱일 수도 있어요.

새벽 3시에 알림이 옵니다. "쇼핑몰이 죽었어요."

로그를 보니 이렇게 적혀 있습니다.

kernel: Out of memory: Killed process 1046 (gunicorn) total-vm:1214MB, anon-rss:892MB

커널이 여러분의 앱을 죽였습니다. 왜 그랬고, 어떻게 막을까요?

먼저 free를 제대로 읽는 법

초보 관리자가 가장 많이 하는 오해가 여기 있습니다. "free가 300MB밖에 안 남았어요! 큰일이에요!"

이 다섯 칸의 뜻을 정확히 알아야 합니다.
bash 브라우저에서 실행
칸뜻봐야 하나?
total전체 메모리기준값
used프로세스들이 실제로 쓰는 양△
free아무도 안 쓰는 순수 빈 공간✗ 보지 마세요
buff/cache커널이 빌려 쓰고 있는 파일 캐시△
available새 프로그램이 당장 쓸 수 있는 양✓ 이것만 보세요
메모리 계산기 — 워커 수와 워커 메모리를 밀어 보며 언제 스왑에 빠지고 언제 OOM이 나는지 보세요.
불러오는 중…

워커 메모리를 계산합시다

쇼핑몰 서버에서 메모리를 먹는 건 대부분 gunicorn 워커입니다. 워커 하나가 얼마나 쓰는지 재고, 몇 개까지 띄울 수 있는지 계산해 봅시다.

RES 칸이 워커 하나가 실제로 잡은 물리 메모리입니다.
bash 브라우저에서 실행
워커 수의 상한은 CPU가 아니라 메모리가 정할 때가 많습니다.
Python 브라우저에서 실행

메모리가 모자라면 벌어지는 일, 순서대로

  1. 파일 캐시를 버린다 — 조용히 일어남. 디스크 읽기가 조금 늘어난다
  2. 스왑으로 내린다 — 안 쓰는 페이지를 디스크로. 여기서부터 느려진다
  3. 스왑을 계속 들락날락(thrashing) — 응답시간이 무너진다. wa와 sy가 치솟는다
  4. OOM Killer 발동 — 커널이 프로세스 하나를 죽인다
메모리를 14GB 요구하면 지표가 어떻게 되는지 봅니다.
bash 브라우저에서 실행
si/so가 계속 0이 아니면 스왑 중입니다.
bash 브라우저에서 실행
실무에서 새벽 장애를 만나면 가장 먼저 치는 명령입니다.
bash 브라우저에서 실행

대응 방법 — 순서대로

방법비용언제
워커 수를 줄인다무료·즉시지금 당장 살려야 할 때. 처리량은 줄지만 죽지는 않는다
워커에 max-requests 를 건다무료메모리 누수가 의심될 때. 주기적으로 워커를 재시작
gunicorn preload무료워커들이 라이브러리를 공유하게 해 실사용량을 줄인다
메모리 증설돈·재부팅슬롯이 비어 있다면 가장 확실한 해법
코드에서 메모리 줄이기시간한 번에 다 읽지 말고 스트리밍으로
스왑을 늘린다무료근본 해결이 아니다. 죽는 대신 느려질 뿐
기본값 60은 데스크톱 기준입니다. 서버는 보통 10~20으로 낮춥니다.
bash 브라우저에서 실행
🤔 확인 문제
free -h 결과가 total 16Gi, used 9.2Gi, free 0.3Gi, buff/cache 6.5Gi, available 6.8Gi 입니다. 이 서버는 위험한가요?
🤔 확인 문제
워커 하나가 340MiB를 쓰는 16GiB(16,384MiB) 서버에서, 워커를 48개로 늘리면 어떻게 될까요?