筆者近期在操作Synology NAS時,明明物理上的RAM還很多,但在撈mongoDB的時候卻卡卡的,所以有了以下這一篇的排查筆記,這次我們感謝Gemini(但中間還是有修正及補充啦 嗚嗚要失業了QAQ)
已知狀況:GitLab/MongoDB都架在docker container裡面
kswapd0:0 程序大量進行硬碟 I/O 讀寫,導致系統卡頓。因筆者 htop 版本較舊且網路限制,找不到 M_SWAP 或 NSWAP 欄位,因此改在 NAS 的 SSH 終端機(需有 root 權限)執行以下指令。
它不依賴任何軟體版本,會直接去 Linux 底層撈出目前 Swap 佔用量前 10 名的「程序名稱、PID 與完整啟動指令」:
for file in /proc/*/status; do \
if [ -f "$file" ]; then \
pid=$(echo "$file" | cut -d'/' -f3); \
vmswap=$(awk '/VmSwap/{print $2}' "$file"); \
if [ ! -z "$vmswap" ] && [ "$vmswap" -gt 0 ]; then \
name=$(awk '/Name/{print $2}' "$file"); \
cmdline=$(cat /proc/$pid/cmdline 2>/dev/null | tr '\0' ' '); \
echo "$vmswap KB | PID: $pid | Name: $name | Cmd: $cmdline"; \
fi; \
fi; \
done | sort -n -r | head -n 10
經由上述指令,揪出卡在 Swap 區的大魔王皆為正常服務,無資安(挖礦病毒)風險:
mongod (MongoDB 資料庫)**:單一程序佔用約 290 MB Swap。gitlab-puma-worker (GitLab 網頁核心)**:共 8 個 Worker,每個卡了 430 MB ~ 450 MB 不等的 Swap。sidekiq (GitLab 背景非同步任務)**:佔用約 167 MB Swap。syncd (Synology Drive) 等系統常駐工具也卡了少量 Swap。kswapd0 為了釋放 RAM,將當時沒活動的程序踢進了 Swap。Linux 機制規定:一旦進入 Swap,除非程序主動讀取,否則就算 RAM 空出來了,資料也不會自動搬回 RAM。vm.swappiness 值為 **60**。系統為了保留極大空間給檔案快取(Cache),即使實體 RAM 還很空,也會提早把閒置程序移往 Swap。kswapd0 必須瘋狂在硬碟與 RAM 之間進行「資料置換(Thrashing)」,因而導致 I/O 飆高。不用重啟整個容器,直接進入 GitLab Container 內重啟核心服務,速度快且不影響使用者:
# 進入 GitLab 容器(請將 gitlab 替換為你的容器名稱)
docker exec -it gitlab bash
# 在容器內重啟網頁 Worker 與背景任務處理器
gitlab-ctl restart puma
gitlab-ctl restart sidekiq
# 離開容器
exit
既然實體 RAM 還有 25G 空閒,直接在 NAS 的 SSH 終端機(需切換為 sudo -i root 權限)執行以下指令,強迫把剩餘卡在 Swap 的冷資料(如 MongoDB、Synology Drive)安全地搬回實體 RAM:
sudo swapoff -a && sudo swapon -a
(執行時 htop 的 Swp 會歸零,Mem 會稍微上升,硬碟讀寫隨之平息)
將 NAS 宿主機的 swappiness 從 60 調低至 10,強迫系統優先使用大記憶體,非必要絕不用 Swap。
群暉網頁介面(DSM)操作步驟:
Optimize_Swappinessroot開機# 強迫系統優先使用實體 RAM
sysctl -w vm.swappiness=10
# 開機自動清空可能殘留的 Swap
swapoff -a && swapoon -a
雖然宿主機調整了,但某些 Docker 容器或 Container Manager (WebUI) 的機制仍可能引發 Swap。如果想要在 Container 層面永久修正與限制,請依據你的啟動方式選擇:
在你的 docker-compose.yml 檔案中,找到 gitlab 或 mongodb 服務,透過 sysctls 直接限制該容器的 Swap 權重。這樣就算宿主機以後不小心被改回 60,該容器依然會維持 10 的高效率運作。
version: '3.8'
services:
gitlab:
image: 'gitlab/gitlab-ce:latest'
# 針對此容器調低 swappiness(優先使用實體記憶體)
sysctls:
- vm.swappiness=10
如果你是用純指令建立容器,可以在 docker run 中加入 --memory-swappiness=10 參數:
docker run -d --name gitlab \
--memory-swappiness=10 \
gitlab/gitlab-ce:latest
如果你是用群暉內建的套件中心(舊版叫 Docker,新版叫 Container Manager)管理的:
cat /proc/sys/vm/swappiness,確認回傳值已成功變為 **10**。htop,Swp 條狀圖應維持在極低水平或歸零,且 kswapd0 不再因為正常服務喚醒而引發硬碟讀寫風暴。