VPS có cần swap không? Cách chọn dung lượng
Cloud image thường không có swap. Tìm hiểu khi nào VPS nhỏ cần swap file, nên cấp bao nhiêu, vm.swappiness đánh đổi gì và khi nào zram phù hợp hơn.
VPS của bạn có cần swap không?
Hầu hết cloud image không có swap, và với VPS nhỏ thì câu trả lời thường là có: hãy thêm một swap file. Swap không biến server 1 GB thành server 2 GB. Nó cung cấp cho kernel một nơi để đưa các anonymous page ít được sử dụng vào đó. Nhờ vậy, page cache vẫn có thể được sử dụng hiệu quả, còn OOM killer (out of memory killer, routine của kernel dùng để chọn và kill một process nhằm giải phóng bộ nhớ) chỉ được dùng khi không còn lựa chọn khác, thay vì là biện pháp đầu tiên.
Tóm lại: trên một máy chạy vài service lâu dài, một swap file nhỏ đáng với dung lượng disk phải bỏ ra. Trên một máy mà một process thường xuyên cố allocate nhiều hơn toàn bộ bộ nhớ hiện có, swap sẽ không cứu được bạn. Nó còn khiến lỗi xảy ra chậm hơn và khó nhận biết hơn. Phần còn lại của guide này sẽ giúp bạn phân biệt hai trường hợp đó, đồng thời giải thích 2 chi phí chỉ xuất hiện trên VPS.
Mọi command bên dưới đều cần root trên chính server của bạn. Vì vậy, hãy chạy chúng trên server đó thay vì sao chép output từ máy của người khác.
Swap thực sự làm gì và không làm gì
Bộ nhớ Linux có 2 loại. Page được hỗ trợ bởi file là bản sao của những thứ đã tồn tại trên disk: các chương trình và mọi file bạn vừa đọc. Tập hợp đó là page cache. Page ẩn danh là vùng bộ nhớ không có file đứng sau: heap và stack, cùng với phần lớn vùng mà database cấp phát trong runtime.
Khi bộ nhớ sắp cạn, kernel phải thu hồi page. Một page được hỗ trợ bởi file và chưa bị thay đổi thì dễ thu hồi, vì bản sao trên disk vẫn còn và page có thể được đọc lại sau đó. Page ẩn danh thì không như vậy, vì bản sao duy nhất của nó nằm trong RAM. Không có swap, kernel chỉ có 2 lựa chọn với bộ nhớ ẩn danh: giữ lại hoặc kill process sở hữu nó.
Server không có swap vẫn paging. Chỉ là nó paging nhầm loại bộ nhớ. Khi chịu áp lực bộ nhớ, kernel thu nhỏ page cache và loại bỏ những page của file mà nó sắp cần lại, bao gồm cả phần mã executable của các chương trình đang chạy. Những page đó quay lại dưới dạng major page fault. Bạn sẽ thấy disk read trong cột bi của vmstat và counter pgmajfault tăng trong /proc/vmstat, trong khi si và so luôn ở mức 0. Máy chủ đang thrashing nhưng các counter swap không báo gì.
Swap không làm tăng capacity. Nếu working set, tức các page thực sự đang được truy cập, lớn hơn RAM, swap sẽ biến lỗi kill do hết bộ nhớ thành một server rất chậm. Đôi khi đó là đánh đổi bạn muốn, vì có thể SSH vào một server chậm để sửa lỗi, còn database đã bị kill thì không thể. Đôi khi tình hình còn tệ hơn, vì server chậm tiếp tục fail health check trong khi vẫn giữ mọi connection mở. Hãy quyết định trước khi thêm swap.
Vì sao cloud image được phát hành mà không có swap?
Đây là lựa chọn có chủ đích. Một image phải khởi động được trên mọi plan mà nhà cung cấp bán, nên partition swap cố định sẽ lãng phí disk trên các plan nhỏ và không có nhiều tác dụng trên các plan lớn. Tốc độ swap cũng phụ thuộc vào storage bên dưới guest, trong khi image không thể biết trước thông tin này. Ngoài ra, bên tạo image tối ưu cho hành vi có thể dự đoán được, vì một process chết ngay sẽ dễ chẩn đoán hơn trên toàn bộ fleet so với một máy vẫn hoạt động nhưng trả lời mọi request chậm vài giây.
Những lý do này phù hợp với các máy dùng tạm. VPS bạn duy trì lâu dài lại khác. Bạn sửa nó thay vì thay máy, nên việc paging kéo dài vài giây thường vẫn tốt hơn một service bị kill. Hãy xem việc thiếu swap là một default được thiết kế cho use case của người khác.
Tệp swap hay phân vùng swap trên VPS?
Hãy dùng tệp. Phân vùng swap đòi hỏi thay đổi kích thước filesystem root đang hoạt động trên một disk đã được phân vùng sẵn. Đây là rủi ro thực sự mà không mang lại lợi ích. Tệp được tạo và xóa bằng các lệnh thông thường. Bạn cũng có thể thay đổi kích thước sau này mà không cần sửa partition table.
Tốc độ không phải yếu tố quyết định. Tại swapon thời điểm, kernel đọc extent map của tệp một lần rồi gửi I/O thẳng đến block device. Filesystem không nằm trên đường đi của từng thao tác page in và page out. Trên cùng một disk, tệp swap và phân vùng swap có hiệu năng như nhau.
Có 2 giới hạn cần biết. Không đặt swap trên network filesystem như NFS (network file system). Trên btrfs, tệp phải tắt copy on write và tắt compression. Vì vậy, btrfs cung cấp helper riêng để tạo tệp swap.
Cách thêm swap file trên Ubuntu hoặc Debian
Kiểm tra trạng thái hiện tại trước khi thay đổi.
swapon --show
free -h
findmnt -no FSTYPE /Kết quả trống từ swapon --show nghĩa là hệ thống chưa có swap nào. Đây là trạng thái bình thường của một cloud image mới. findmnt in ra loại filesystem của root, và loại này quyết định cách tạo file. Trên ext4, là loại filesystem được hầu hết cloud image sử dụng, fallocate an toàn.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfilechmod phải chạy trước mkswap. Nếu bỏ qua, mkswap sẽ báo lỗi: mkswap: /swapfile: insecure permissions 0644, fix with: chmod 0600 /swapfile. Một swap file cho phép mọi user trên máy đọc được sẽ để lộ dữ liệu bộ nhớ mà các process khác đã paged out. Sau đó, mkswap xác nhận kích thước bằng một dòng như Setting up swapspace version 1, size = 2 GiB (2147479552 bytes).
Trên xfs hoặc btrfs, lệnh cuối có thể fail với swapon: /swapfile: swapon failed: Invalid argument. Trên XFS, nguyên nhân là fallocate tạo ra các extent chưa được ghi, vì vậy hãy ghi trực tiếp các byte.
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progressTrên btrfs, nguyên nhân là copy on write, và btrfs-progs hiện tự thiết lập đúng các flag.
sudo btrfs filesystem mkswapfile --size 2g /swapfileDù dùng cách nào, hãy kết thúc bằng chmod 600, dùng mkswap khi cần, rồi chạy swapon để xác nhận kết quả.
swapon --show
free -hswapon --show phải liệt kê /swapfile với type là file và kích thước đúng như yêu cầu. free -h phải hiển thị một dòng Swap gần như không dùng dung lượng. Swap được dùng 0 trên một hệ thống mới là đúng. Kernel chỉ chuyển page sang đó khi có lý do.
Để swap tồn tại sau reboot, hãy thêm entry rồi kiểm tra ngay.
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
sudo swapoff /swapfile
sudo swapon -a
swapon --showswapon -a đọc /etc/fstab, vì vậy một dòng sai sẽ fail ngay trước mắt bạn. Một lỗi chính tả chưa được kiểm tra sẽ xuất hiện trong lần reboot ngoài kế hoạch, khi máy khởi động lại mà không có swap bạn tưởng là đã cấu hình.
Để xóa swap sau này, chạy sudo swapoff /swapfile, xóa dòng tương ứng trong fstab, rồi chạy sudo rm /swapfile. swapoff trước hết phải đưa mọi page đã paged out trở lại RAM, nên trên một máy đang bận, lệnh này có thể fail với swapoff: /swapfile: swapoff failed: Cannot allocate memory. Hãy giải phóng bớt memory rồi thử lại.
Kích thước swap file nên là bao nhiêu?
Tác vụ này giữ các anonymous page ít được truy cập, vì vậy yếu tố cần quan tâm là bao nhiêu phần memory được cấp phát thực sự đang idle, không phải plan có bao nhiêu RAM. Memory idle không tăng theo cùng tỷ lệ với kích thước plan, nên multiplier sẽ giảm khi plan lớn hơn. Đây là quy tắc được dùng trong guide này.
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
}
]Ở plan nhỏ nhất, swap có kích thước 2 GB, tương đương 2 lần RAM, vì máy 1 GB có rất ít headroom và chỉ một spike cũng có thể kích hoạt OOM killer. Ở mức cao nhất trong biểu đồ, file dừng ở 4 GB, tương đương 0.25 lần RAM, vì việc paging từng đó dữ liệu trên shared storage mất đủ lâu để server gần như ngừng hoạt động trong thời gian này. Hãy giảm các con số này nếu disk allowance của bạn hạn chế, vì file sẽ sử dụng dung lượng disk thực tế.
Lý do kinh điển duy nhất để đặt swap bằng hoặc lớn hơn RAM là hibernation, vì hibernation ghi toàn bộ memory image vào swap. VPS không hibernate, nên quy tắc đó không áp dụng cho bạn.
vm.swappiness thực sự thay đổi điều gì?
vm.swappiness không phải là tỷ lệ phần trăm RAM và cũng không phải là một ngưỡng. Đây là chi phí tương đối mà kernel gán cho việc thu hồi anonymous page so với file page. Giá trị mặc định là 60. Giảm giá trị này khiến kernel ưu tiên loại bỏ page cache. Tăng giá trị này khiến kernel ưu tiên đưa anonymous memory ra swap.
Đây là một sự đánh đổi theo cả hai hướng. Ở vm.swappiness = 10, database giữ lại nhiều allocation hơn trong RAM và đổi lại phải đọc lại các file vừa bị loại khỏi cache. Trên máy chủ chủ yếu dùng để phục vụ file, đó là hướng không phù hợp, vì page cache mới là thành phần thực hiện công việc hữu ích ở đó.
Đặt giá trị này thành 0 không tắt swap. Nó chỉ dẫn kernel tránh thu hồi anonymous memory cho đến khi bộ nhớ gần cạn, khiến OOM killer được kích hoạt sớm hơn thay vì trì hoãn. Nếu không muốn dùng swap, hãy xóa swap file.
sysctl vm.swappiness
printf 'vm.swappiness = 10\n' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --system
sysctl vm.swappinessLệnh sysctl -w không có tham số chỉ có hiệu lực đến lần reboot tiếp theo rồi âm thầm ngừng áp dụng, vì vậy hãy ghi giá trị vào file trong /etc/sysctl.d/. Các kernel từ phiên bản 5.8 chấp nhận giá trị từ 0 đến 200. Giá trị trên 100 chỉ hợp lý khi swap nhanh gần bằng RAM, tức là trong trường hợp dùng zram.
zram: swap tiêu tốn CPU thay vì disk
zram là một block device được nén và lưu trong RAM. Dùng nó làm swap thì page lẽ ra phải ghi xuống disk sẽ được nén và giữ trong memory. Không có disk I/O và không tiêu tốn disk quota. Cái giá phải trả là CPU time cho mỗi lần page in và page out, cùng với lượng RAM chứa các page đã nén mà ứng dụng không còn sử dụng được.
Tỷ lệ nén từ 2:1 đến 3:1 thường được công bố cho anonymous page. Số liệu thực tế của bạn được zramctl in trong các cột DATA và COMPR. Hãy đo thay vì lập kế hoạch dựa trên con số điển hình, vì một số workload chứa dữ liệu gần như không nén được.
sudo apt install zram-toolsĐặt ALGO=zstd và PERCENT=25 trong /etc/default/zramswap, sau đó restart service và kiểm tra kết quả.
sudo systemctl restart zramswap
zramctl
swapon --showPERCENT là tỷ lệ trên tổng RAM. Vì vậy, giá trị 25 trên máy 4 GB sẽ dành tối đa 1 GB cho các page đã nén. Hãy bắt đầu với giá trị thấp và chỉ tăng khi zramctl cho thấy device đang đầy dần. Thiết lập PRIORITY trong cùng file quyết định kernel sẽ lấp đầy swap nào trước: giá trị cao hơn được ưu tiên, còn swap file trên disk được thêm bằng swapon thông thường sẽ nhận priority âm. Vì vậy, zram được dùng trước và file sẽ nhận phần overflow. swapon --show in cả hai giá trị trong cột PRIO. Trên các distribution dùng systemd-zram-generator thay cho zram-tools, các thiết lập tương tự nằm trong /etc/systemd/zram-generator.conf.
zram phù hợp với máy còn dư CPU nhưng ít disk trống. Đây là lựa chọn không phù hợp khi CPU allowance đã là tài nguyên thiếu hụt, vì công việc nén sẽ cạnh tranh cùng application để sử dụng phần tài nguyên đó.
Hai bẫy về swap chỉ gặp trên VPS
Bẫy đầu tiên là dung lượng đĩa. Một swap file 2 GB chiếm 2 GB trong gói dịch vụ ngay khi bạn tạo, vì dung lượng phải được cấp phát trước. df -h / giảm ngay đủ số lượng đó và không tăng lại cho đến khi bạn xóa file. Với gói nhỏ, đây là một phần dung lượng đáng kể. Filesystem root đầy sẽ gây hỏng nhiều thứ hơn những gì swap có thể khắc phục. File này cũng được tính trong output của du. Hãy nhớ điều đó khi bạn tìm dung lượng và df và du không thống nhất về nơi dung lượng đĩa đã được sử dụng.
Bẫy thứ hai là độ trễ. I/O của swap đi đến storage mà host chia sẻ với các guest khác, và bạn không thể xem tải của chúng từ bên trong guest. Bạn chỉ thấy tác động: thao tác đưa một page vào memory, vốn thường nhanh, đôi khi mất nhiều thời gian hơn, và process chờ thao tác đó sẽ dừng cho đến khi page xuất hiện. Đây là cùng một cách suy luận như CPU steal time trên host dùng chung, nhưng áp dụng cho disk queue thay vì run queue. Hãy đo trên chính máy của bạn, vì mọi con số độ trễ được công bố chỉ mô tả các guest lân cận của người khác.
Làm sao biết swap đang gây hại?
Swap đã sử dụng không phải là vấn đề. Lưu lượng swap mới là vấn đề. Một server có vài trăm megabyte nằm trong swap nhưng không có hoạt động paging chỉ đơn giản là đã chuyển các vùng memory mà không có tiến trình nào truy cập trong nhiều giờ. Đó chính là kết quả bạn muốn.
Hãy theo dõi tốc độ thay vì tổng dung lượng.
vmstat 1 5si và so là số kibibyte mỗi giây được swap in và swap out. Trên một máy bình thường, hai giá trị này luôn ở mức gần zero, bất kể cột swpd hiển thị gì. so duy trì ở mức cao cùng lúc với si tăng nghĩa là các page đang bị ghi ra rồi lập tức được đọc trở lại. Đây là hiện tượng 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 0Mẫu trên cho thấy máy đang gặp vấn đề. Tín hiệu rõ nhất không nằm ở các cột swap. Đó là wa ở mức 72, nghĩa là CPU dành phần lớn thời gian để chờ I/O, và b ở mức 3, nghĩa là có 3 process đang bị block.
PSI (pressure stall information) trả lời trực tiếp hơn.
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 nghĩa là trong 10 giây gần nhất, có ít nhất một task bị stall vì chờ memory trong 8.42 phần trăm thời gian. full tính thời gian mà mọi task không ở trạng thái idle đều bị stall, vì vậy full duy trì ở mức cao là thiệt hại có thể đo được, không chỉ là dấu hiệu cảnh báo. Nếu file này không tồn tại, kernel của bạn đã tắt PSI theo mặc định và cần có psi=1 trên kernel command line.
Để xem process nào đang giữ các page trong swap:
sudo awk '/^Name:/{n=$2} /^VmSwap:/ && $2+0 > 0 {printf "%10d kB %s\n", $2, n}' /proc/[0-9]*/status | sort -rn | headĐể kiểm tra OOM killer đã hoạt động hay chưa:
sudo journalctl -k --grep "Out of memory"Một lần OOM killer hoạt động sẽ có dạng 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, và log của service trong cùng giây đó sẽ ghi Main process exited, code=killed, status=9/KILL. Nếu bạn đã thấy các dòng này trên một máy không có swap, thêm một swap file là việc rẻ nhất nên thử tiếp theo.
Khi swap không phải là cách xử lý đúng
Swap giúp có thêm thời gian khi áp lực bộ nhớ chỉ là tạm thời hoặc có dữ liệu ít được truy cập. Swap không giúp ích cho tiến trình cứ tăng bộ nhớ cho đến khi bị dừng, và còn khiến việc theo dõi lỗi khó hơn vì máy chủ phải mất thêm thời gian để paging thay vì fail nhanh rồi khởi động lại.
Thay vào đó, hãy giới hạn tiến trình. Một systemd service chấp nhận MemoryMax= và MemorySwapMax= trong file drop-in. Đây là cách giới hạn memory và CPU cho service bằng systemd mà không cần thay đổi ứng dụng. Container có các control tương tự ở cấp cao hơn. Thiết lập các giới hạn này là cách ngăn một Compose service chiếm toàn bộ máy chủ. Cả hai cách đều tạo ra một lần kill có tên tiến trình trong log để bạn tìm được, thay vì để kernel chọn tiến trình bị kill dựa trên score.
Hãy làm việc này khi server còn mới và ít tải. Tạo swap file và đặt một memory limit chỉ mất vài phút. Việc này nên được thực hiện cùng với các bước khác trong 10 phút đầu tiên trên một VPS mới.
FAQ
Việc thêm swap có khiến VPS 1 GB hoạt động như VPS 2 GB không?
Không. Swap chậm hơn RAM rất nhiều, và kernel chỉ chuyển những page mà nó đánh giá là ít được sử dụng sang đó. Swap tạo thêm khoảng đệm khi tải tăng đột biến và là nơi lưu tạm bộ nhớ đã được cấp phát nhưng sau đó không còn được truy cập. Nếu workload chủ động đọc và ghi nhiều bộ nhớ hơn dung lượng máy có, swap sẽ biến lỗi hết bộ nhớ thành việc paging liên tục. Server vẫn hoạt động nhưng phản hồi chậm đến mức không thể sử dụng. Trong trường hợp đó, hãy thêm RAM hoặc giới hạn process đang tăng bộ nhớ.
VPS 1 GB hoặc 2 GB cần bao nhiêu swap?
2 GB là đủ cho cả hai, và sau đó không cần tiếp tục tăng swap theo dung lượng RAM. Swap chứa các anonymous page ít được sử dụng. Lượng bộ nhớ thực sự ít được sử dụng trên server không tăng theo cách tổng dung lượng RAM tăng. Quy tắc cũ là cấp swap bằng 2 lần RAM bắt nguồn từ hibernation, vì hibernation ghi toàn bộ memory image xuống disk. VPS không bao giờ hibernation. Cấp quá 4 GB chủ yếu chỉ khiến lỗi xảy ra lâu hơn và chậm hơn trên storage dùng chung với các guest khác.
Đặt vm.swappiness bằng 0 có phải là cách đúng để ngăn swapping không?
Không, và thiết lập này không hoạt động như tên gọi gợi ý. vm.swappiness = 0 không vô hiệu hóa swap. Nó yêu cầu kernel tránh reclaim anonymous page cho đến khi gần hết bộ nhớ. Điều này làm OOM kill dễ xảy ra hơn, không phải khó xảy ra hơn. Nó cũng dồn toàn bộ hoạt động reclaim sang page cache, nên các lần đọc file thường phải quay lại disk hơn. Nếu muốn tắt hoàn toàn swap, hãy chạy sudo swapoff -a và xóa dòng tương ứng khỏi fstab. Nếu muốn giảm swapping, hãy thử vm.swappiness = 10 rồi so sánh các cột si và so trong vmstat trước và sau khi thay đổi.
Có nên dùng zram thay cho swap file không?
Dùng zram khi CPU còn dư nhưng disk còn ít chỗ trống. Dùng swap file khi tình hình ngược lại. zram nén các page và giữ chúng trong RAM, nên loại bỏ hoàn toàn disk I/O nhưng phải trả chi phí CPU cho mỗi lần page in và page out. Phần RAM mà zram sử dụng cũng không còn dành cho application. Trên VPS có giới hạn CPU thấp, chi phí này chiếm chính tài nguyên mà bạn đang thiếu. Chạy cả hai là cách làm bình thường: đặt priority cao hơn cho zram bằng PRIORITY trong /etc/default/zramswap và giữ một disk swap file bên dưới để xử lý phần tràn.
Vì sao OOM killer chạy khi free cho biết vẫn còn bộ nhớ khả dụng?
free chỉ báo cáo trạng thái tại một thời điểm, còn việc cấp phát xảy ra tức thời. Process yêu cầu một block lớn nhanh hơn khả năng reclaim giải phóng bộ nhớ sẽ bị kill, dù mức trung bình vẫn có vẻ an toàn. Đọc kernel log bằng sudo journalctl -k --grep "Out of memory". Log này cho biết process bị kill và resident size của nó tại thời điểm đó. Sau đó kiểm tra xem kill có xuất phát từ giới hạn cgroup thay vì toàn bộ máy hay không. Container hoặc systemd unit có đặt MemoryMax= sẽ bị kill khi đạt giới hạn riêng, trong khi host vẫn còn bộ nhớ trống.