리눅스 장애 대응 · 메모리와 OOM · 실습
메모리와 OOM 진단
목표
메모리 지표를 정확히 읽고, 프로세스가 실제로 붙잡은 메모리와 예약만 한 주소 공간을 구분하고, OOM Killer 가 무엇을 보고 고르는지 확인합니다.
왜 중요한가
메모리 문제의 오진 대부분은 잘못된 열을 보는 것에서 시작합니다. free 의 free 열이 아니라 available 열을 봐야 하고, top 의 VIRT 가 아니라 RES(RSS)를 봐야 합니다. OOM Killer 의 점수도 RSS 기준입니다 - 64GB 를 mmap 으로 예약만 한 프로세스는 후보조차 아닙니다. 그리고 컨테이너 안에서 free 는 호스트 전체를 보여 주므로, 진짜 상한은 cgroup 파일에서 읽어야 합니다. 이 실습의 7번이 "없으면 없다고 적어라"까지 채점하는 이유는, 현장에서도 그 파일이 있는지부터 확인하는 것이 첫 동작이기 때문입니다.
단계
/root/mem 디렉터리에서 작업합니다.
1. /proc/meminfo 의 MemTotal 값을 kB 숫자만 /root/mem/total_kb.txt 에 적으세요.
2. MemAvailable 값을 kB 숫자만 /root/mem/available_kb.txt 에 적으세요.
3. 실제 상주 메모리(VmRSS)가 100MB 이상인 프로세스를 백그라운드로 띄우고 PID 를 /root/mem/hog_pid.txt 에 적으세요. 이후 단계 내내 살아 있어야 합니다.
4. 그 프로세스의 VmSize 와 VmRSS 를 /root/mem/vm.txt 에 다음 두 줄로 적으세요.
vsize_kb=<값>rss_kb=<값>
5. 그 프로세스의 oom_score_adj 를 500 으로 설정하고, 그 뒤에 읽은 oom_score 값을 /root/mem/oom_score.txt 에 적으세요.
6. /root/mem/topmem.sh <N> 을 만드세요. RSS 상위 N개 프로세스를 <rss_kb> <comm> 형식으로 내림차순 출력합니다. 정확히 N줄이어야 합니다.
7. 이 컨테이너의 cgroup 메모리 한도를 /root/mem/limit.txt 에 그대로 적으세요. 해당 파일을 읽을 수 없는 환경이면 unavailable 이라고 적으세요.
8. /root/mem/memguard.sh <임계값kB> 를 만드세요. RSS 가 임계값을 넘는 프로세스가 있으면 over=<PID> 를 한 줄씩 출력하고 종료 코드 1, 없으면 ok 한 줄과 종료 코드 0. 인자가 없으면 0이 아닌 코드입니다.
참고
python3 -c "import time; b=bytearray(150*1024*1024); time.sleep(9999)" &로 메모리를 실제로 붙잡을 수 있습니다./proc/<PID>/status에VmSize,VmRSS,/proc/<PID>/oom_score와oom_score_adj가 각각 있습니다.- 커널 스레드는
VmRSS항목이 없으므로 6번과 8번에서 걸러야 합니다. - 흔한 실수 1: 3번에서 메모리를 할당만 하고 쓰지 않으면 VmSize 만 늘고 VmRSS 는 그대로입니다.
- 흔한 실수 2: 5번에서
oom_score를 먼저 읽고 adj 를 나중에 바꾸면 값이 맞지 않습니다.
단계 8개
- 전체 메모리 읽기
- MemAvailable 과 MemFree 구분하기
- 메모리를 실제로 붙잡기
- VmSize 와 VmRSS 비교
- OOM 점수 조정하기
- RSS 상위 프로세스 뽑기
- 컨테이너의 진짜 한도 찾기
- 메모리 감시 스크립트