Linux OOM Killer Tuning for VPS:實用指南

12 分鐘閱讀 - 2026年6月8日

hero section cover
目錄
  • VPS 的 Linux OOM 殺手調校
  • OOM 殺手如何選擇犧牲品
  • 在系統當機前偵測記憶體壓力
  • 使用 oom_score_adj 保護關鍵程序
  • 使用 cgroups 和 systemd 限制記憶體
  • 在發生 OOM 事件後讀取日誌
  • 總結
分享

調整您 VPS 上的 Linux OOM 殺手,以保護資料庫和 SSH、使用 cgroups 封鎖失控的進程,以及阻止錯誤的服務被殺死。

VPS 的 Linux OOM 殺手調校

當記憶體耗盡時,Linux OOM 殺手是核心的最後手段:它會選取一個程序並終止該程序,以維持系統運作。在 RAM 資源緊繃且無後備方案的 VPS 上,預設的選擇往往是錯誤的。 您的資料庫被終止,而一個長期運行的工作程序卻倖存下來,您只能自己去摸索原因。本指南將說明 OOM 殺手如何對程序進行評分、如何將評分優先權偏向您的關鍵服務,以及如何使用 cgroups,以防止單一失控程序拖垮整個系統。


 

OOM 殺手如何選擇犧牲品

當核心無法透過頁面快取驅逐或交換空間回收足夠的記憶體時,便會啟動 OOM 殺手。每個程序都有一個 oom_score 0 到 1000 之間的分數,該分數主要根據其駐留集大小 (RSS) 和交換空間使用情況計算得出。分數最高的進程將收到 SIGKILL 訊號。

RSS 在計算中佔主導地位,這也是為何終止操作幾乎總是落在記憶體消耗最大的進程上。這通常是您的資料庫、應用伺服器,或是任何正在執行最重要工作的長壽進程。實際觸發分配的進程(即「呼叫者」)極少會被終止。

您需要區分以下兩種 OOM 事件:

  • 全局 OOM:主機(或您的 VPS 整體)已耗盡 RAM 和交換空間。核心會掃描每個進程,並終止得分最高的進程。
  • cgroup OOM:特定 cgroup 已達到其記憶體限制。即使系統其餘部分仍有閒置記憶體,核心也只會在該 cgroup 內部終止進程。

若您已設定 systemd 單元限制,或正在運行容器,多數 OOM 事件將屬於 cgroup OOM。這其實是好事:影響範圍得以控制。

在系統當機前偵測記憶體壓力

OOM 事件幾乎從不會突然發生。通常會先出現一段壓力逐漸加劇的預警期,而監控的目標正是要在該預警期內及時察覺。

free -h 提供系統概覽。關鍵的欄位是 available,而非 free:它代表可回收的頁面快取,反映了在不進行交換的情況下實際可分配的記憶體量。請將 MemAvailable 維持在峰值負載的 10% 至 15% 左右 MemTotal

若要進行按進程歸因分析,請依 RSS 排序:

ps aux --sort=-%mem | head -10

或使用 htop 並依 RES。此處顯示的數值會直接納入核心的評分機制,因此排在前幾名的項目最有可能成為 OOM 的目標。

在 4.20 及更新版本的內核中,「壓力滯留資訊」是值得整合至監控系統的早期預警機制:

cat /proc/pressure/memory

some avg10 圖表顯示過去十秒內,至少有一項任務因等待記憶體而陷入停滯的時間占比。低於 5% 即屬正常。若數值持續高於 10%,表示系統正耗費實時資源卡在記憶體回收上,此時發生 OOM 強制終止程序的可能性很高。

交換空間抖動會顯示在 vmstat 1 中以非零 siso 欄位中持續出現。少量駐留的交換空間無害,但持續不斷的交換進與交換出則不然。

使用 oom_score_adj 保護關鍵程序

核心計算出的分數可透過 oom_score_adj,調整範圍從 -1000(免疫)到 +1000(優先終止)。此調整值將直接加到最終分數上。

若要對正在執行的程序進行一次性變更:

echo -500 | sudo tee /proc/$(pidof sshd)/oom_score_adj

若需讓設定在系統重啟後持續生效,請在 systemd 單元中設定。這正是 sshd、您的資料庫,以及任何您無法承受損失的服務的正確設定位置:

[Service]
OOMScoreAdjust=-900

合理的預設起始值:

  • sshd:-1000。若在記憶體危機期間失去遠端存取能力,後續復原將困難許多。
  • MySQL、PostgreSQL、Redis:-800 至 -900。提供強效保護,同時確保在真正災難性情況下仍可對其進行干預。
  • 應用程式工作執行程序、批次工作、cron 任務:+100 至 +500。這些是您寧可看到它們被終止,也不願讓資料庫受影響的程序。

請勿將所有設定都設為 -1000。若沒有任何進程可被終止,核心最終會陷入恐慌或凍結狀態,情況反而更糟。

使用 cgroups 和 systemd 限制記憶體

調整評分會影響哪些進程被終止。cgroups 則決定是否會觸發全局終止機制。透過為每個服務設定嚴格的上限,可將記憶體異常限制在單一 cgroup 內,而非讓單一進程耗盡整個 VPS 的資源。

在 systemd 單元檔案中:

[Service]
MemoryHigh=400M
MemoryMax=512M
OOMPolicy=stop
Restart=on-failure
RestartSec=5s

MemoryHigh 是軟性限制:當使用量超過此值時,核心會積極從該 cgroup 回收頁面,但不會終止任何進程。 MemoryMax 是硬性上限。若 cgroup 嘗試分配超過此上限,核心會終止該 cgroup 內的某個程序。透過 Restart=on-failure 該服務會立即重新啟動。

在 cgroup v2 環境下(Ubuntu 22.04 及後續版本、近期 Debian、RHEL 9), memory.oom.group 會將 cgroup 中的所有進程一併終止,而非留下孤兒進程。這對於 PHP-FPM 池等多進程服務特別有用,因為若僅終止部分進程,該群組可能會出現異常行為。

以下是幾項值得參考的應用程式特定注意事項:

  • PHP-FPM:設定 pm = ondemand 於小型 VPS 實例上,並將 pm.max_children 時,應參照每個工作執行程式的平均 RSS 值,而非預設值。若在 2 GB 的 VPS 上將池大小設定為保留 4 GB 空間,當記憶體填滿時便會首次觸發 OOM 錯誤。
  • Node.js:使用 --max-old-space-size=512 (單位為 MB)。若未設定,Node 會持續擴張直至核心介入為止。
  • MySQL 與 PostgreSQLinnodb_buffer_pool_size 以及 shared_buffers 應為作業系統的頁面快取、連線記憶體以及伺服器上的其他租戶預留充足的餘裕空間。預設值是基於專用伺服器的假設。

在發生 OOM 事件後讀取日誌

當 OOM 殺手觸發時,核心會將詳細報告寫入環形緩衝區。請使用以下指令讀取:

dmesg -T | grep -iE 'killed process|out of memory'
journalctl -k --grep='Out of memory'

需仔細閱讀的區段以「invoker」開頭,並以「victim」結尾。核心會列印完整的任務清單,包含每個進程的 RSS、交換空間使用量以及最終 oom_score_adj。有三項內容值得檢查:

  • 限制條件CONSTRAINT_NONE 表示全域 OOM, CONSTRAINT_MEMCG 表示 cgroup 觸及其限制。兩種情況的解決方式各不相同。
  • Free swap。若此處顯示 0kB,表示 RAM 和交換空間皆已耗盡。可選擇增加交換空間、提高 MemoryMax 肇事進程的權重,或是降低並發度。
  • 受害進程的評分與其他所有進程的比較。若受害進程的評分僅略高於後幾項進程,則您的 oom_score_adj 設定的數值未能發揮足夠作用。請擴大分差。

針對 cgroup 記憶體不足 (OOM) 情況,kill 計數器位於 memory.events cgroup 內部:

cat /sys/fs/cgroup/system.slice/mysql.service/memory.events

計數器 oom_kill 計數值上升,表示該服務正反覆觸及其限制。這是一個訊號,表示應提高 MemoryMax、分析工作負載,或是將服務移至更大的資源方案,而非不斷循環重啟該服務。

總結

調整 OOM 殺手並非為了讓它消失,而是為了控制在記憶體耗盡時由哪個程序承擔代價,並在發生時縮小影響範圍。在生產環境中,以下模式是行之有效的:

  • 為您無法承受損失的服務設定 Score-protect,尤其是 sshd 和您的資料庫。
  • 將其餘所有服務 MemoryMax ,將其納入 systemd 單元中,如此一來,即使有單一程序失控,也只需重新啟動該服務,而非導致系統中斷。
  • 監控 PSI 並 MemAvailable ,而非等待 dmesg 事後才透過 PSI 得知狀況。
  • 預留 15% 至 20% 的 RAM 作為緩衝空間。即使進行調校,也無法彌補 VPS 容量根本不足以應付工作負載的問題。

若您的記憶體壓力屬於結構性問題而非可透過設定解決,您需要更多 RAM 或更快的交換區儲存裝置。FDC Servers 的 VPS 方案採用 AMD EPYC 處理器搭配 NVMe 儲存裝置,這能確保交換區讀取速度足夠快,使短暫的記憶體爆滿不會演變成系統強制終止。

博客

本周特色

更多文章
Linux OOM Killer Tuning for VPS:實用指南

Linux OOM Killer Tuning for VPS:實用指南

調整您 VPS 上的 Linux OOM 殺手,以保護資料庫和 SSH、使用 cgroups 封鎖失控的進程,以及阻止錯誤的服務被殺死。

12 分鐘閱讀 - 2026年6月8日

Linux 流量控制 (tc):實用指南

12 分鐘閱讀 - 2026年6月5日

更多文章