VPS 스왑 메모리 설정 필요성과 적정 용량 계산 방법
대부분의 클라우드 VPS는 스왑 없이 제공됩니다. 스왑 파일이 필요한 상황과 적절한 크기 설정법, vm.swappiness 조정 및 zram 활용 전략을 상세히 설명합니다. 메모리 부족으로 인한 OOM killer 작동을 방지하고 시스템 안정성을 높이는 최적의 가이드를 확인하십시오.
VPS에 스왑(swap)이 필요한가?
대부분의 클라우드 이미지는 스왑 없이 제공되며, 소규모 VPS를 운영한다면 일반적으로 스왑 파일을 추가하는 것이 좋습니다. 스왑이 있다고 해서 1 GB 서버가 2 GB 서버처럼 동작하는 것은 아닙니다. 스왑은 커널이 사용 빈도가 낮은 익명 페이지(anonymous pages)를 보관할 공간을 제공합니다. 이를 통해 페이지 캐시를 효율적으로 유지할 수 있으며, OOM killer(메모리 확보를 위해 프로세스를 강제로 종료하는 커널 루틴)가 즉각적으로 작동하는 대신 최후의 수단으로 동작하게 합니다.
요약하자면, 장기 실행 서비스 몇 개를 운영하는 서버라면 약간의 디스크 공간을 할당해 스왑 파일을 만드는 것이 가치가 있습니다. 반면, 특정 프로세스가 주기적으로 서버 전체 메모리보다 많은 양을 할당하려 시도하는 환경이라면 스왑은 해결책이 되지 못하며, 오히려 장애 발생 시점을 늦추고 원인 파악을 어렵게 만들 뿐입니다. 이 가이드의 나머지 부분은 이 두 상황을 구분하는 방법과 VPS 환경에서만 발생하는 두 가지 비용에 대해 설명합니다.
아래의 모든 명령어는 서버의 root 권한이 필요하므로, 다른 사람의 서버 출력 결과를 복사하지 말고 직접 자신의 서버에서 실행하십시오.
스왑의 실제 역할과 그렇지 않은 것
Linux 메모리에는 두 가지 종류가 있습니다. 파일 기반 페이지(File backed pages)는 프로그램이나 최근 읽은 모든 파일처럼 이미 디스크에 존재하는 데이터의 복사본입니다. 이 집합을 페이지 캐시(page cache)라고 합니다. 익명 페이지(Anonymous pages)는 파일이 없는 메모리 영역으로, 힙(heap)과 스택(stack), 그리고 데이터베이스가 런타임에 할당하는 대부분의 메모리가 여기에 해당합니다.
메모리가 부족해지면 커널은 페이지를 회수해야 합니다. 깨끗한 파일 기반 페이지는 디스크에 원본이 남아 있고 나중에 다시 읽어올 수 있으므로 회수 비용이 저렴합니다. 반면 익명 페이지는 RAM에 있는 것이 유일한 복사본이므로 쉽게 회수할 수 없습니다. 스왑이 없다면 커널은 익명 메모리에 대해 해당 메모리를 유지하거나, 아니면 그 메모리를 소유한 프로세스를 강제 종료(kill)하는 두 가지 선택지만 갖게 됩니다.
스왑이 없는 서버도 페이징을 수행합니다. 단지 잘못된 메모리 영역을 페이징할 뿐입니다. 메모리 압박이 가해지면 커널은 페이지 캐시를 축소하며, 실행 중인 프로그램의 실행 코드(executable text)를 포함해 곧 다시 필요해질 파일 페이지까지 쫓아냅니다. 이렇게 쫓겨난 페이지들은 나중에 메이저 페이지 폴트(major page faults)를 유발하며 다시 로드됩니다. 이때 si과 so은 계속 0을 유지하지만, /proc/vmstat의 pgmajfault 카운터는 계속 올라가고 vmstat의 bi 열에서는 디스크 읽기가 발생합니다. 서버는 스래싱(thrashing) 상태에 빠지지만 스왑 카운터는 아무것도 보고하지 않습니다.
스왑이 하지 않는 역할은 용량 확장입니다. 실제로 사용 중인 페이지들의 집합인 워킹 셋(working set)이 RAM보다 크다면, 스왑은 OOM(Out of Memory)으로 인한 프로세스 강제 종료를 매우 느린 서버 상태로 바꿀 뿐입니다. 때로는 느린 서버라도 접속해서 복구할 수 있는 편이 강제 종료된 데이터베이스보다 나을 수 있으므로 이런 선택을 하기도 합니다. 하지만 느린 서버가 모든 연결을 붙잡은 채 헬스 체크에 계속 실패하게 되면 상황이 더 악화될 수도 있습니다. 스왑을 추가하기 전에 어떤 결과가 필요한지 먼저 결정하십시오.
클라우드 이미지는 왜 스왑(swap) 없이 배포됩니까?
이는 의도적인 선택입니다. 하나의 이미지는 제공자가 판매하는 모든 플랜에서 부팅되어야 합니다. 따라서 고정된 스왑 파티션을 설정하면 작은 플랜에서는 디스크 공간이 낭비되고, 큰 플랜에서는 무의미해집니다. 또한 스왑 속도는 게스트 운영체제 하위의 스토리지 성능에 의존하는데, 이미지는 이를 미리 알 수 없습니다. 이미지 제작자는 예측 가능한 동작을 우선시합니다. 프로세스가 즉시 종료되는 것이, 살아남아 모든 요청에 수 초씩 늦게 응답하는 서버보다 전체 인프라 차원에서 진단하기 쉽기 때문입니다.
위의 이유들은 일회용 서버에 해당합니다. 계속 유지하며 사용하는 VPS는 상황이 다릅니다. 서버를 교체하는 대신 수리해서 사용하므로, 일반적으로 서비스가 강제 종료되는 것보다 수 초간 페이징(paging)이 발생하는 편이 낫습니다. 스왑이 없는 상태는 다른 사용자의 환경을 기준으로 설정된 기본값일 뿐이라고 이해하십시오.
VPS에서 스왑 파일과 스왑 파티션 중 무엇을 사용해야 합니까?
스왑 파일을 사용하십시오. 파티션을 사용하려면 이미 파티션이 나누어진 디스크의 루트 파일 시스템 크기를 실시간으로 조정해야 하는데, 이는 아무런 이득 없이 위험만 초래합니다. 스왑 파일은 일반적인 명령어로 생성 및 삭제가 가능하며, 파티션 테이블을 건드리지 않고도 나중에 크기를 변경할 수 있습니다.
속도는 결정적인 요소가 아닙니다. swapon 시점에 커널은 파일의 익스텐트 맵을 한 번 읽은 뒤 블록 장치로 직접 I/O를 전달하므로, 페이지를 읽고 쓸 때마다 파일 시스템을 거치지 않습니다. 동일한 디스크라면 스왑 파일과 스왑 파티션의 성능은 같습니다.
두 가지 제한 사항을 알아두어야 합니다. NFS(network file system)와 같은 네트워크 파일 시스템에는 스왑을 설정하지 마십시오. 또한 btrfs에서는 해당 파일의 copy on write와 압축 기능을 비활성화해야 합니다. 이것이 바로 btrfs가 스왑 파일 생성을 위한 자체 도구를 제공하는 이유입니다.
Ubuntu 또는 Debian에서 스왑 파일 추가하는 방법
변경 사항을 적용하기 전에 현재 상태를 확인합니다.
swapon --show
free -h
findmnt -no FSTYPE /swapon --show의 출력 결과가 비어 있다면 스왑이 전혀 없는 상태이며, 이는 새로 생성된 클라우드 이미지의 일반적인 상태입니다. findmnt는 루트 파일 시스템 유형을 출력하며, 이 정보에 따라 파일을 생성하는 방법이 결정됩니다. 대부분의 클라우드 이미지에서 사용하는 ext4 환경에서는 fallocate을 사용하는 것이 안전합니다.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfilechmod은 mkswap보다 먼저 실행해야 합니다. 이 단계를 건너뛰면 mkswap가 mkswap: /swapfile: insecure permissions 0644, fix with: chmod 0600 /swapfile와 같은 오류를 반환합니다. 모든 사용자가 읽을 수 있는 스왑 파일은 다른 프로세스가 페이징한 메모리 내용을 시스템의 모든 사용자에게 노출합니다. 올바르게 설정된 mkswap은 Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)와 같은 줄을 출력하여 크기를 확인해 줍니다.
xfs 또는 btrfs 환경에서는 마지막 명령이 swapon: /swapfile: swapon failed: Invalid argument 오류와 함께 실패할 수 있습니다. XFS 파일 시스템에서 이러한 현상이 발생하는 이유는 fallocate이 기록되지 않은 익스텐트(extents)를 남기기 때문이므로, 대신 바이트를 직접 기록해야 합니다.
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progressbtrfs 파일 시스템에서는 쓰기 시 복사(copy on write) 기능이 원인이며, 현재의 btrfs-progs 명령은 필요한 플래그를 자동으로 설정해 줍니다.
sudo btrfs filesystem mkswapfile --size 2g /swapfile어떤 경우든 chmod 600을 실행하고, 필요한 경우 mkswap를 수행한 뒤 swapon을 실행하여 결과를 확인합니다.
swapon --show
free -hswapon --show 명령을 실행하면 /swapfile가 유형 file 및 지정한 크기로 표시되어야 하며, free -h 명령은 사용량이 거의 없는 Swap 행을 보여주어야 합니다. 새로 설정한 환경에서 스왑 사용량이 0인 것은 정상입니다. 커널은 필요한 경우에만 메모리 페이지를 스왑으로 이동시킵니다.
재부팅 후에도 설정이 유지되도록 설정한 뒤, 즉시 항목을 테스트합니다.
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
sudo swapoff /swapfile
sudo swapon -a
swapon --showswapon -a은 /etc/fstab을 읽어 들이므로, 잘못된 줄이 있으면 즉시 오류가 발생합니다. 테스트하지 않은 오타는 계획되지 않은 재부팅 시점에 드러나며, 이때 시스템은 예상했던 스왑 없이 부팅됩니다.
나중에 스왑을 제거하려면 sudo swapoff /swapfile을 실행하고 fstab에서 해당 줄을 삭제한 뒤 sudo rm /swapfile를 실행합니다. swapoff은 페이징된 모든 페이지를 먼저 RAM으로 다시 읽어 들여야 하므로, 시스템 부하가 높을 경우 swapoff: /swapfile: swapoff failed: Cannot allocate memory 오류가 발생할 수 있습니다. 메모리를 확보한 후 다시 시도하십시오.
스왑 파일의 크기는 어느 정도가 적당한가?
이 작업은 콜드 익명 페이지를 유지하므로, 중요한 것은 전체 RAM 용량이 아니라 할당된 메모리 중 실제로 유휴 상태인 메모리의 양입니다. 유휴 메모리는 플랜 크기에 비례하여 증가하지 않으므로, 플랜이 커질수록 배율은 낮아집니다. 이 가이드는 이 규칙을 따릅니다.
The data behind this chart
[
{
"label": "1 GB plan",
"swap_gb": 2,
"swap_x_ram": 2
},
{
"label": "2 GB plan",
"swap_gb": 2,
"swap_x_ram": 1
},
{
"label": "4 GB plan",
"swap_gb": 2,
"swap_x_ram": 0.5
},
{
"label": "8 GB plan",
"swap_gb": 4,
"swap_x_ram": 0.5
},
{
"label": "16 GB plan",
"swap_gb": 4,
"swap_x_ram": 0.25
}
]가장 작은 플랜에서는 스왑이 2 GB이며, 이는 RAM의 2배에 해당합니다. 1 GB 서버는 여유 공간이 매우 적어 일시적인 부하만으로도 OOM killer가 작동할 수 있기 때문입니다. 차트 상단에서 파일 크기는 4 GB 또는 RAM의 0.25배에서 멈춥니다. 공유 스토리지에서 그만큼의 데이터를 페이징하는 데는 시간이 오래 걸려, 작업이 진행되는 동안 서버가 사실상 다운된 상태가 되기 때문입니다. 디스크 용량이 부족하다면 이 수치를 줄이십시오. 스왑 파일은 실제 디스크 공간을 차지합니다.
스왑을 RAM과 같거나 그 이상으로 설정하는 고전적인 이유는 최대 절전 모드(hibernation) 때문이며, 이는 전체 메모리 이미지를 스왑에 기록합니다. VPS는 최대 절전 모드를 사용하지 않으므로 해당 규칙은 적용되지 않습니다.
vm.swappiness는 실제로 무엇을 변경하는가?
vm.swappiness는 RAM의 백분율이나 특정 임계값이 아닙니다. 이는 커널이 파일 페이지와 비교하여 익명 페이지(anonymous pages)를 회수할 때 할당하는 상대적인 비용입니다. 기본값은 60입니다. 이 값을 낮추면 커널은 페이지 캐시를 삭제하는 것을 선호합니다. 값을 높이면 커널은 익명 메모리를 스왑으로 내보내는 것을 선호합니다.
이는 양방향으로 작용하는 트레이드오프입니다. vm.swappiness = 10에서는 데이터베이스가 더 많은 할당 메모리를 상주시키지만, 그 대가로 방금 캐시에서 삭제한 파일을 다시 읽어야 합니다. 파일 제공이 주된 작업인 서버에서는 페이지 캐시가 유용한 작업을 수행하고 있으므로, 이는 잘못된 방향입니다.
이 값을 0으로 설정한다고 해서 스왑이 꺼지는 것은 아닙니다. 이는 커널에 메모리가 거의 고갈될 때까지 익명 페이지 회수를 피하라고 지시하는 것이며, 결과적으로 OOM killer가 더 빨리 작동하게 만듭니다. 스왑을 사용하지 않으려면 스왑 파일을 제거하십시오.
sysctl vm.swappiness
printf 'vm.swappiness = 10\n' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --system
sysctl vm.swappiness단순히 sysctl -w를 실행하는 것은 다음 재부팅 전까지만 유효하며 이후에는 적용이 중단되므로, /etc/sysctl.d/ 아래에 파일을 작성하십시오. 5.8 버전 이후의 커널은 0에서 200까지의 값을 허용합니다. 100을 초과하는 설정은 스왑이 RAM만큼 빠를 때, 즉 zram을 사용할 때만 의미가 있습니다.
zram: 디스크 대신 CPU를 사용하는 스왑
zram은 RAM에 상주하는 압축 블록 장치입니다. 이를 스왑으로 사용하면 디스크로 이동했을 페이지가 압축되어 메모리에 남게 됩니다. 디스크 I/O가 발생하지 않으며 디스크 할당량도 소모하지 않습니다. 대신 모든 페이지의 입출력 시 CPU 자원이 소모되며, 압축된 페이지가 차지하는 만큼 애플리케이션이 사용할 수 있는 RAM은 줄어듭니다.
익명 페이지의 경우 일반적으로 2:1에서 3:1 사이의 압축률을 보이며, 실제 수치는 zramctl의 DATA 및 COMPR 열에서 확인할 수 있습니다. 일부 작업 부하는 데이터 압축이 거의 되지 않을 수 있으므로, 일반적인 수치에 의존하기보다 직접 측정하는 것이 좋습니다.
sudo apt install zram-tools/etc/default/zramswap에서 ALGO=zstd와 PERCENT=25을 설정한 뒤, 서비스를 재시작하여 결과를 확인하십시오.
sudo systemctl restart zramswap
zramctl
swapon --showPERCENT는 전체 RAM에 대한 비율이므로, 4 GB 장비에서 25로 설정하면 압축 페이지를 위해 최대 1 GB를 예약합니다. 처음에는 낮게 설정하고 zramctl에서 장치가 가득 차는 것이 확인될 때만 수치를 높이십시오. 같은 파일의 PRIORITY 설정은 커널이 어떤 스왑을 먼저 채울지 결정합니다. 값이 높을수록 우선순위가 높으며, 일반 swapon로 추가된 디스크 스왑 파일은 음수 우선순위를 가지므로 zram이 먼저 사용되고 스왑 파일은 넘치는 데이터를 처리하게 됩니다. swapon --show은 PRIO 열에서 두 값을 모두 출력합니다. zram-tools 대신 systemd-zram-generator을 사용하는 배포판의 경우, 동일한 설정이 /etc/systemd/zram-generator.conf에 위치합니다.
zram은 CPU 여유는 있지만 디스크 공간이 부족한 장비에 적합합니다. CPU 자원이 이미 부족한 상황이라면 압축 작업이 애플리케이션과 자원을 두고 경쟁하게 되므로 적절한 선택이 아닙니다.
VPS에서만 발생하는 두 가지 스왑(swap) 함정
첫 번째 함정은 디스크 공간입니다. 2 GB 스왑 파일을 생성하는 즉시 해당 공간이 미리 할당되어야 하므로, 사용 중인 플랜의 디스크 용량에서 2 GB가 즉시 차감됩니다. df -h /은 즉시 전체 용량만큼 줄어들며, 파일을 삭제하기 전까지는 복구되지 않습니다. 소규모 플랜에서는 이 용량이 상당한 비중을 차지하며, 루트 파일시스템이 꽉 차면 스왑으로 해결하려던 문제보다 훨씬 더 큰 장애가 발생합니다. 이 파일은 du 출력 결과에도 포함되므로, 디스크 공간을 확보하려고 할 때 df와 du의 디스크 사용량 계산 차이를 확인하는 과정에서 이를 기억해야 합니다.
두 번째 함정은 지연 시간(latency)입니다. 스왑 I/O는 호스트가 다른 게스트와 공유하는 스토리지로 전달되는데, 게스트 내부에서는 다른 게스트의 부하를 확인할 수 없습니다. 오직 그 결과만 체감할 수 있습니다. 평소에는 빠르게 처리되던 페이지 인(page in) 작업이 때때로 훨씬 오래 걸리며, 해당 페이지를 기다리는 프로세스는 데이터가 도착할 때까지 멈춥니다. 이는 공유 호스트에서의 CPU 스틸 타임(steal time)과 같은 원리이며, 실행 큐(run queue) 대신 디스크 큐(disk queue)에 적용된 것입니다. 공개된 지연 시간 수치는 모두 다른 사용자의 환경을 기준으로 하므로, 반드시 본인의 서버에서 직접 측정해야 합니다.
스왑 사용이 성능에 악영향을 주는지 확인하는 방법
스왑을 사용하는 것 자체가 문제는 아닙니다. 스왑 트래픽이 발생하는 것이 문제입니다. 수백 메가바이트가 스왑에 머물러 있더라도 페이징 활동이 없다면, 이는 몇 시간 동안 아무도 건드리지 않은 메모리를 단순히 옮겨둔 것이며 이는 의도한 결과입니다.
총량보다는 비율을 확인하십시오.
vmstat 1 5si와 so는 초당 스왑으로 들어오고 나가는 키비바이트(kibibytes)입니다. 정상적인 서버라면 swpd 열의 값과 관계없이 이 수치는 0에 가깝게 유지됩니다. so이 지속되면서 동시에 si이 증가한다면, 페이지가 디스크로 쓰였다가 즉시 다시 읽히는 스래싱(thrashing) 현상이 발생하고 있는 것입니다.
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 3 1048572 38210 4096 61440 912 1180 2210 1290 1402 2890 9 7 12 72 0해당 샘플은 문제가 있는 서버를 보여주며, 가장 명확한 신호는 스왑 열에 있지 않습니다. wa이 72라는 것은 CPU가 대부분의 시간을 I/O 대기에 소비했음을 의미하며, b가 3이라는 것은 3개의 프로세스가 차단되었음을 의미합니다.
PSI(pressure stall information)는 이 질문에 더 직접적인 답을 제공합니다.
cat /proc/pressure/memorysome avg10=8.42 avg60=5.11 avg300=2.03 total=1284729
full avg10=3.10 avg60=1.94 avg300=0.71 total=498210some avg10=8.42은 지난 10초 동안 최소 하나의 작업이 메모리를 기다리느라 전체 시간의 8.42퍼센트 동안 지연되었음을 의미합니다. full은 유휴 상태가 아닌 모든 작업이 지연된 시간을 합산하므로, full 값이 지속적으로 높게 나타난다면 이는 경고 신호를 넘어 실질적인 성능 저하가 발생하고 있다는 뜻입니다. 해당 파일이 존재하지 않는다면 커널에서 PSI가 기본적으로 비활성화된 것이며, 커널 명령줄에 psi=1 옵션을 추가해야 합니다.
어떤 프로세스가 스왑에 페이지를 점유하고 있는지 확인하려면 다음을 실행하십시오.
sudo awk '/^Name:/{n=$2} /^VmSwap:/ && $2+0 > 0 {printf "%10d kB %s\n", $2, n}' /proc/[0-9]*/status | sort -rn | headOOM killer가 이미 작동했는지 확인하려면 다음을 실행하십시오.
sudo journalctl -k --grep "Out of memory"작동 기록이 있다면 Out of memory: Killed process 2199 (mysqld) total-vm:1275860kB, anon-rss:129252kB, file-rss:0kB, shmem-rss:0kB, UID:114 pgtables:504kB oom_score_adj:0와 같이 출력되며, 같은 시간대의 서비스 로그에는 Main process exited, code=killed, status=9/KILL라는 메시지가 남습니다. 스왑이 없는 서버에서 이러한 로그를 확인했다면, 스왑 파일을 추가하는 것이 가장 먼저 시도해 볼 수 있는 저렴한 해결책입니다.
Swap이 잘못된 해결책인 경우
Swap은 일시적이거나 사용 빈도가 낮은 메모리 압박 상황에서 시간을 벌어줄 뿐입니다. 프로세스가 죽을 때까지 메모리 사용량이 계속 증가하는 문제에는 아무런 도움이 되지 않으며, 오히려 시스템이 즉시 실패하고 재시작하는 대신 페이징에 추가 시간을 허비하게 만들어 장애 상황을 파악하기 어렵게 만듭니다.
대신 프로세스에 제한을 설정하십시오. systemd 서비스는 drop-in 파일에서 MemoryMax= 및 MemorySwapMax= 설정을 지원하며, 이를 통해 애플리케이션을 수정하지 않고도 systemd로 서비스의 메모리 및 CPU 제한하기가 가능합니다. 컨테이너 역시 한 단계 상위 수준에서 동일한 제어 기능을 제공하며, 이를 설정하는 것이 Compose 서비스 하나가 전체 서버 자원을 점유하는 것을 방지하는 방법입니다. 두 방식 모두 커널이 점수에 따라 임의로 희생양을 선택하게 두는 대신, 로그에서 확인할 수 있는 명확한 이름과 함께 프로세스를 종료시킵니다.
이 작업은 서버가 새로 설치되어 부하가 없는 상태에서 수행하십시오. swap 파일을 생성하고 메모리 제한을 설정하는 데는 몇 분밖에 걸리지 않으며, 이는 새 VPS 설정 후 첫 10분 동안 수행해야 할 작업의 일부로 포함되어야 합니다.
FAQ
1 GB VPS에 스왑을 추가하면 2 GB VPS처럼 동작합니까?
아닙니다. 스왑은 RAM보다 훨씬 느리며, 커널은 사용 빈도가 낮은 페이지를 스왑으로 옮길 뿐입니다. 스왑은 일시적인 부하 급증을 견딜 여유를 제공하고, 할당된 후 사용되지 않는 메모리를 보관하는 역할을 합니다. 만약 작업 부하가 물리적 RAM 용량보다 많은 메모리를 지속적으로 읽고 쓴다면, 스왑은 OOM(Out of Memory) 종료를 막는 대신 끊임없는 페이징 현상을 유발하여 서버가 응답 불능 상태에 빠지게 만듭니다. 이런 경우에는 RAM을 증설하거나 메모리 점유율이 높은 프로세스를 제한해야 합니다.
1 GB 또는 2 GB VPS에는 어느 정도의 스왑이 필요합니까?
2 GB면 충분하며, 그 이상으로 RAM 용량에 비례해 늘릴 필요는 없습니다. 스왑은 사용되지 않는 익명 페이지를 보관하는 용도이며, 서버에서 실제로 사용되지 않는 메모리 양은 전체 RAM 용량처럼 증가하지 않기 때문입니다. RAM의 2배를 설정하라는 과거의 규칙은 전체 메모리 이미지를 디스크에 기록하는 최대 절전 모드(hibernation)를 위한 것이며, VPS는 최대 절전 모드를 사용하지 않습니다. 4 GB를 초과하여 설정하는 것은 다른 사용자와 공유하는 스토리지에서 더 길고 느린 장애를 유발할 뿐입니다.
vm.swappiness를 0으로 설정하는 것이 스왑을 멈추는 올바른 방법입니까?
아닙니다. 이름과 달리 실제 동작은 그렇지 않습니다. vm.swappiness = 0은 스왑을 비활성화하지 않습니다. 이 설정은 메모리가 거의 고갈될 때까지 익명 페이지 회수를 최대한 미루도록 커널에 지시하며, 결과적으로 OOM 종료가 발생할 확률을 높입니다. 또한 모든 회수 부담을 페이지 캐시로 전가하여 파일 읽기 성능을 저하시키고 디스크 I/O를 증가시킵니다. 스왑을 완전히 제거하려면 sudo swapoff -a를 실행하고 fstab에서 관련 줄을 삭제하십시오. 스왑 사용량을 줄이고 싶다면 vm.swappiness = 10을 시도해 보고, 변경 전후의 si 및 so 열을 vmstat에서 비교해 보십시오.
스왑 파일 대신 zram을 사용해야 합니까?
CPU 여유가 있고 디스크 공간이 부족하다면 zram을 사용하고, 반대의 경우에는 스왑 파일을 사용하십시오. zram은 페이지를 압축하여 RAM에 보관하므로 디스크 I/O를 완전히 피할 수 있지만, 페이지를 입출력할 때마다 CPU 자원을 소모하며 zram이 차지하는 공간만큼 애플리케이션이 사용할 수 있는 RAM은 줄어듭니다. CPU 할당량이 적은 VPS에서는 이 비용이 이미 부족한 자원에 부담을 줍니다. 두 방식을 함께 사용하는 것도 일반적입니다. /etc/default/zramswap에서 PRIORITY를 사용하여 zram에 더 높은 우선순위를 부여하고, 그 아래에 디스크 스왑 파일을 두어 오버플로우를 처리하십시오.
free 명령어로 확인했을 때는 메모리 여유가 있었는데 왜 OOM killer가 작동했습니까?
free은 특정 시점의 상태만 보여주며, 메모리 할당은 순식간에 일어납니다. 프로세스가 메모리 회수 속도보다 빠르게 대량의 메모리를 요청하면, 평균적인 메모리 사용량이 여유로워 보여도 해당 프로세스는 종료됩니다. sudo journalctl -k --grep "Out of memory"을 사용하여 커널 로그를 확인하십시오. 종료된 프로세스 이름과 당시 상주 메모리(resident size) 크기가 기록되어 있습니다. 또한 종료 원인이 시스템 전체가 아닌 cgroup 제한 때문인지 확인하십시오. 컨테이너나 MemoryMax=이 설정된 systemd 유닛은 호스트에 여유 메모리가 있더라도 자체 제한에 도달하면 종료됩니다.