swappiness는 "스왑 사용량 %"가 아니다
가장 흔한 오해가 vm.swappiness=10이면 "메모리의 10%만 스왑을 쓴다"는 해석이다. 실제로는 커널이 메모리를 회수(reclaim)할 때 익명 페이지(anonymous, 프로세스 힙/스택)를 스왑으로 내보낼지, 파일 캐시(page cache)를 버릴지를 정하는 상대적 성향값이다. 0~200 범위이며 값이 클수록 익명 페이지를 더 적극적으로 스왑한다. 즉 "스왑 총량"이 아니라 "회수 대상 선택 편향"을 조절하는 파라미터다.
왜 문제가 되는가: 지연시간 스파이크
DB나 저지연 API 서버에서 익명 페이지가 스왑으로 밀려나면, 다시 접근하는 순간 디스크(또는 SSD) I/O가 발생해 수 마이크로초 작업이 수 밀리초로 튄다. p99 지연시간이 갑자기 나빠지는 원인 중 상당수가 이 major fault다. 현재 상태는 아래로 확인한다.
cat /proc/sys/vm/swappiness
free -h
# 프로세스별 스왑 사용량 상위 확인
grep -H VmSwap /proc/[0-9]*/status 2>/dev/null | sort -t: -k2 -h | tail
# major fault 및 스왑 in/out 추이
vmstat 1 5 # si(swap-in), so(swap-out) 컬럼을 본다
0으로 끄면 안전하다는 오해
swappiness=0은 스왑을 완전히 금지하지 않는다. 커널 3.5 이후로는 "메모리 압박이 심할 때까지 익명 페이지 스왑을 최대한 미루는" 의미로 바뀌었다. 완전 비활성화는 swapoff -a다. 그러나 스왑을 아예 없애면, OOM 상황에서 커널이 완충지대 없이 곧바로 OOM Killer를 호출해 프로세스를 강제 종료한다. 스왑은 "느린 메모리"가 아니라 "OOM 전 안전판" 역할도 한다는 점을 기억해야 한다.
워크로드별 권장값
| 워크로드 | 권장 swappiness | 이유 |
|---|---|---|
| OLTP DB(PostgreSQL/MySQL) | 1~10 | 버퍼풀/캐시 상주 유지, 지연 스파이크 억제 |
| 일반 웹/API 서버 | 10~30 | 여유 메모리는 파일 캐시 우선 |
| 배치/분석 노드 | 30~60 | 처리량 우선, 순간 지연 허용 |
| 데스크톱/개발기 | 60(기본) | 범용 균형 |
영구 적용 설정
런타임 변경은 재부팅 시 사라지므로 sysctl.d에 파일로 남긴다. 컨테이너 호스트라면 이 값이 노드 전체에 적용된다는 점에 유의한다.
# 런타임 즉시 적용
sudo sysctl -w vm.swappiness=10
# 영구 적용
cat <<'EOF' | sudo tee /etc/sysctl.d/99-swap.conf
vm.swappiness = 10
vm.vfs_cache_pressure = 100
EOF
sudo sysctl --system
cgroup v2와 컨테이너 환경
Kubernetes 노드에서는 전역 swappiness보다 cgroup 단위 제어가 더 중요할 때가 있다. cgroup v2에서는 memory.swap.max로 컨테이너별 스왑 상한을, memory.swap.high로 완만한 스로틀을 건다. 기본적으로 kubelet은 스왑을 비활성화하지만, NodeSwap 기능을 켜면 파드가 스왑을 쓸 수 있다.
# 특정 서비스 슬라이스의 스왑을 완전 차단
systemctl set-property my-app.service MemorySwapMax=0
# cgroup v2 직접 확인
cat /sys/fs/cgroup/system.slice/my-app.service/memory.swap.current
cat /sys/fs/cgroup/system.slice/my-app.service/memory.swap.max
주의점: 튜닝보다 근본 원인
- swappiness 조정은 대증요법이다. 반복적으로 스왑이 발생한다면 실제 메모리가 부족한 것이니 워킹셋 크기부터 측정한다.
- DB의 경우 버퍼풀/공유버퍼가 물리 메모리를 초과하도록 설정돼 있지 않은지 먼저 점검한다.
- 스왑 자체를 없애기 전에
vm.overcommit_memory와 OOM 동작을 함께 검토한다. 스왑 제거는 OOM Kill 빈도를 높일 수 있다. - NVMe 스왑은 HDD보다 빠르지만 여전히 RAM보다 수십~수백 배 느리다. "SSD니까 스왑 써도 된다"는 판단은 지연 민감 서비스에선 위험하다.
결론적으로 swappiness는 "얼마나 스왑하느냐"가 아니라 "무엇을 먼저 버리느냐"를 정하는 값이다. 지연이 중요하면 낮게, 처리량이 중요하면 높게 두되, 반복 스왑은 튜닝이 아니라 용량 문제의 신호로 읽어야 한다.