VPS CPU steal time:如何判斷鄰居干擾
了解 CPU steal time 的實際含義,讀懂 vmstat 的 st 欄位,並區分 noisy neighbour 造成的等待與 VPS 自身過載。
CPU steal time 實際計算的內容
CPU steal time 是指虛擬 CPU 已準備好執行、沒有任何工作需要等待,但 hypervisor 將實體核心分配給其他 guest 的時間比例。工作已排入佇列,但實體核心正在其他地方執行。Linux 會單獨計算這些週期,並將其回報為 st。因此,您可以區分「我的伺服器很忙」與「我的伺服器正在等待執行時段」。
這正是存在此計數器的原因。您自己的程序實際使用 CPU 的時間會回報為 us (user) 或 sy (system)。工作等待儲存裝置而處於阻塞狀態的時間會回報為 wa (I/O wait)。vCPU (virtual CPU) 若可執行、位於 run queue 中、沒有待處理的 I/O,卻仍未執行,則會回報為 st。伺服器內部沒有任何元件能清除這個狀態,因為排程決策是在更底層的 host 上執行。
這直接對應到 VPS 如何在多個 guest 之間共用一台實體機器。通常原因是鄰近 guest:同一個 node 上的另一個 guest 負載過高,因此 host 必須在各 guest 之間分配核心。還有另一個容易被忽略的原因。許多 provider 會將共用 vCPU 限制在實體核心的一部分,而在某些 hypervisor 上,這項強制套用的上限會在 guest 內計入 steal。因此,高 st 數值表示核心沒有分配給您,但不一定能告訴您是誰佔用了它。
偷占用 CPU 時間數值的來源
核心本身無法測量偷占用 CPU 時間,因為它看不到主機。這項資訊由 hypervisor 提供。在 KVM 中,主機會將每個 vCPU 的計數器寫入與 guest 共用的頁面;guest 會在核心建置時啟用 CONFIG_PARAVIRT_TIME_ACCOUNTING 後累加這些數值,所有發行版核心都已啟用此功能。Xen 也會透過 runstate area 回報相同資訊。這個總數只會透過一個位置傳遞到 userspace:
head -1 /proc/statcpu 這一行包含 10 個計數器,單位是開機後累計的 USER_HZ ticks,順序如下:user、nice、system、idle、iowait、irq、softirq、steal、guest、guest_nice。steal 是標籤後的第 8 個數值。以下所有工具,包括 vmstat、top、mpstat 及任何 Prometheus exporter,都會讀取相同欄位,並將兩次取樣轉換為百分比。
其中一項影響比其他因素更重要。如果 hypervisor 從未匯出這個計數器,該欄位會永遠維持 0,所有依賴它的工具都會回報平靜的 0.0,即使主機已經過載。KVM 和 Xen 會匯出這個數值。VMware 和 Hyper-V 上的 guest 通常會回報固定的 0。在信任 0 之前,先確認平台:
systemd-detect-virt此命令會列印平台名稱,例如 kvm、xen、vmware 或 microsoft;若執行於裸機,則會顯示 none。在容器內,它會改為回報 runtime,例如 lxc、docker 或 podman。這些資訊只能說明容器,無法反映底層機器。在 kvm 上,0 是主機未造成資源爭用的可靠證據。在永遠不填入該欄位的平台上,0 完全沒有參考價值,必須透過計時實際工作來判斷資源爭用。
如何檢查 VPS 的 CPU steal time?
vmstat 來自 procps 套件。幾乎所有 Ubuntu 和 Debian VPS 映像都已包含此工具,但部分精簡容器映像沒有,因此在依賴它之前,請先安裝。
sudo apt-get update
sudo apt-get install -y procps
vmstat --version
vmstat 1 5vmstat --version 會輸出類似 vmstat from procps-ng 4.0.4 的一行內容。若有輸出,表示工具已安裝,且讀取的是核心提供的實際計數器。接著,vmstat 1 5 會每秒取樣一次,共取樣五次。
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
r b swpd free buff cache si so bi bo in cs us sy id wa st gu
1 0 0 3216484 98304 1284360 0 0 4 18 62 110 3 1 96 0 0 0
2 0 0 3216232 98304 1284360 0 0 0 0 248 431 6 2 84 0 8 0在右側的 cpu 區塊中找出 st 欄位。目前的 procps-ng 建置版本會在其後方輸出供 KVM guest 使用的 gu 欄位,因此 st 是從右側數來第二欄,而不是最後一欄。請依欄位標題讀取數值,因為該欄位位置在不同版本間可能變更。
以下兩個習慣有助於避免誤判。第一筆資料列是自開機以來的平均值,因此請忽略該列,改讀後續資料列。單次取樣也不能代表實際狀況,因為 steal time 可能以突發方式出現:執行 vmstat 1 60 並觀察完整一分鐘後,再下結論。
top 會在其 %Cpu(s) 摘要列中回報相同數值,欄位標示為 st:
%Cpu(s): 6.2 us, 2.1 sy, 0.0 ni, 83.9 id, 0.0 wa, 0.0 hi, 0.3 si, 7.5 st如需查看各 CPU 核心的詳細資料,請加入 sysstat:
sudo apt-get install -y sysstat
mpstat -P ALL 1 5mpstat 會為每個 CPU 輸出一列,並包含 %steal 欄位,用來判斷所有 vCPU 是否都受到影響,或只有單一 vCPU 受到影響。若要保留支援工單所需的歷史資料,請儲存取樣結果,不要只在螢幕上查看:
date -u | tee -a ~/steal.log
mpstat -P ALL 1 5 | tee -a ~/steal.log請在你懷疑發生問題的時段,透過 cron 執行這項工作。如此一來,該檔案就能提供確切的十分鐘資料,而不只是告訴供應商「昨晚感覺很慢」。
steal 數值代表什麼?
- 穩定維持在
0.0。 這表示狀況正常,或平台完全不回報 steal。先使用systemd-detect-virt確認,再下結論。 - 持續數秒、幅度為幾個百分點的尖峰。 在任何共享節點上都屬正常。鄰近租戶可能開始建置,或主機正在執行備份。
- 共享方案持續維持 1 到 5 個百分點。 這屬於預期情況。價格反映的就是共享 CPU。
- 持續維持 5 到 10 個百分點。 這代表可量測的效能下降。開始記錄證據,並比較數天內相同時段的數值。
- 一次持續數小時、超過 10 個百分點。 這表示該節點對你的工作負載而言超額配置。達到這個程度時,便有理由提交支援請求或搬遷服務。
請將這些區間視為判讀指南,而非規格,因為沒有供應商會為共享方案發布 steal 保證。應根據你執行的工作負載評估這些數值。夜間批次工作即使承受 15 個百分點的 steal,通常也不會有人察覺。對延遲敏感的服務則會在平均值看起來令人擔憂之前,先反映在 p99 上。因此,交易機器人等延遲敏感的工作負載應部署在專用核心上。
steal time 的成本是多少?
計算很簡單。如果 CPU 時間中有 s 被取走,需要固定 CPU 時間的工作,在實際經過時間上會變成原本的 1 / (1 - s) 倍。以需要 60 秒 CPU 時間的工作為例:
The data behind this chart
[
{
"steal_percent": 0,
"wall_clock_seconds": "60.0"
},
{
"steal_percent": 3,
"wall_clock_seconds": "61.9"
},
{
"steal_percent": 8,
"wall_clock_seconds": "65.2"
},
{
"steal_percent": 15,
"wall_clock_seconds": "70.6"
},
{
"steal_percent": 25,
"wall_clock_seconds": "80.0"
},
{
"steal_percent": 40,
"wall_clock_seconds": "100.0"
}
]在 3 percent(一般共享方案常見的數值)時,該工作需要 61.9 秒,而不是 60.0 秒。這種情況通常不至於需要提交 ticket。在 8 percent 時,則需要 65.2 秒。在 40 percent 時,同一項工作需要 100.0 秒;原本能持續清空的佇列,也會開始累積。
這些是計算值,不是測量結果。此模型假設只有一個可執行執行緒,且 steal time 在整個時間區間內平均分布。實際服務通常比曲線呈現的情況更糟,因為被取走的時間片可能落在請求處理期間,延遲會再次傳遞給所有等待該請求的工作。若要取得自己的數值,而不是只套用公式,請在離峰時段和繁忙時段各自 對 VPS 進行基準測試,並記錄兩個時段的 st。
這是 steal,還是其他問題?
Steal 很容易與其他症狀混淆。請在同一行 vmstat 中一起查看這些計數器。
st偏高,而r和us維持偏低:主機沒有把 CPU core 交給你。這就是 steal。r明顯高於你的 vCPU 數量,且us偏高、st接近 0:你執行的工作量超過自有 CPU 的處理能力。請將r與nproc的輸出比較。這是你自己的 oversubscription,不是鄰近租戶造成的問題。wa偏高,而st接近 0:工作正在等待儲存裝置,這是不同的問題,也需要不同的處理方式。- Load average 偏高,但
st和us都偏低:load 數值也會計入不可中斷的工作,因此通常表示裝置卡住或網路掛載無回應,而不是 CPU 問題。
Burstable 方案需要另外說明。系統閒置時會累積 credit balance,忙碌時則會消耗;credit 用完後,供應商會將你的處理速率限制在 baseline。部分平台會將這種 throttle 回報為 steal;其他平台則不會在內部顯示,你只會得到較少的每秒 CPU cycles。判斷鄰近租戶是否造成問題前,請先閱讀方案說明。
為什麼容器顯示沒有 steal time
Steal 是虛擬機器的屬性,不是其中執行的容器的屬性。自有 VPS 上的 Docker 容器會共用主機的 /proc,因此在容器內讀取的 st 值就是 VPS 的 steal,這正是你需要的結果。以容器為基礎、以 VPS 形式提供的虛擬化環境則不同。在啟用 lxcfs 的情況下,容器內的 /proc/stat 是根據 cgroup accounting 合成的,因此 steal 會固定為 0。只從容器內擷取資料的監控堆疊,可能會顯示平穩且無異常的 0,但底層實體機器其實可能正處於資源不足的狀態。
在容器內,具有相同意義的計數器是 CPU quota throttling。在 cgroup v2 中:
cat /sys/fs/cgroup/cpu.statnr_throttled 計算該群組觸及 CPU quota 的 enforcement period 次數,throttled_usec 則累計程序被凍結的時間。nr_throttled 持續上升表示你的程序處於 runnable 狀態,卻沒有取得 CPU 執行時間;這與 steal 的體驗相同,但原因是你自行設定的限制。責怪主機之前,先檢查自己的限制,尤其是在 VPS 上 使用 Docker 執行服務,且 compose file 設定了 CPU limits 時。分層虛擬化會增加另一個可能損失時間的位置,因為 VPS 內的 VM 必須同時承受 VPS 的 steal,以及自身的排程延遲。如果你 在 VPS 上執行巢狀虛擬化,請將這點納入考量。
如何處理持續性的 steal
guest 內沒有任何設定可以修正 steal,因為做出排程決策的 scheduler 在 guest 外部。實際可採取的措施有 4 項。
先收集證據。 以 UTC 記錄時間戳記、每次事件的持續時間、重複發生的頻率,以及 mpstat 顯示的是單一 vCPU 受影響還是全部 vCPU 受影響。持續記錄一週的取樣資料,比單張螢幕擷取畫面更有價值。
使用這些資料提交 ticket。 直接詢問 2 個問題:這些時段的 node 是否過度配置,以及是否可以遷移我的 instance。貼上 vmstat 的輸出與確切時間。Provider 會根據可重現的時段採取行動;ticket 若只寫著 server 很慢,通常會收到要求提供相關時段的回覆。這項工作有多少能交由 provider 處理,是 受管理與不受管理 VPS 之間的實際差異之一。
要求遷移。 將 guest 移至負載較低的 node,是 provider 的例行工作,通常只需短暫重新開機。這項修正不會增加費用,也能解決常見情況:同一個 node 恰好同時承載多個高負載的鄰近 instance。
購買不受 contention 影響的方案。 Dedicated vCPU 方案會為 instance 保留實體核心,因此計數器會維持在 0。每月費用較高,但對無法承受效能變異的 workload 而言,這是直接且合理的答案。如果這仍然不足,或你也希望獨占 memory bandwidth,下一步就是改用 dedicated server 而非 VPS。
在等待上述處理期間,先降低 steal 造成的影響。執行的 worker thread 數量應少於 vCPU 數量,因為無法取得核心的 thread 只會增加 context switch。將批次工作移至 node 較安靜的時段;現在你自己的 log 已能指出這些時段。接著使用相同的 command,在相同的時段再次測量,這樣才能判斷變更是否有效,而不是猜測。
FAQ
VPS 上正常的 CPU steal time 是多少?
在共用方案中,短暫尖峰以及持續低於約 5 percent 的數值都屬於正常,因為共用 CPU 代表主機會在多個 guest 之間分配實體核心。若數值持續數小時達到兩位數,則不屬於正常情況,值得提交 ticket。在 dedicated vCPU 方案中,預期讀值為 0.0;若出現其他數值,則應回報故障。請根據自身工作負載判斷數值:需要整夜執行的批次工作可以承受 steal,但對延遲敏感的 API 無法承受。
擴大方案能解決高 steal time 嗎?
不能單靠擴大方案解決。同一個共用節點上增加 vCPU,代表更多虛擬 CPU 競爭同一批受爭用的實體核心,百分比可能完全不變。能消除 steal 的方法是取得 dedicated CPU 配置,或遷移到負載較低的節點。從繁忙主機取得更大的資源配額,仍然只是使用繁忙主機的共用資源。
為什麼我的 VPS 明顯很慢,卻顯示 0 steal time?
常見原因有兩個。Hypervisor 可能根本沒有提供這項計數器;在 VMware 和 Hyper-V 平台上通常如此,因此無論主機實際情況如何,該欄位都會維持為零。執行 systemd-detect-virt,確認目前使用的平台。否則,瓶頸可能在其他地方:檢查 wa 以查看儲存裝置等待,將 r 與 nproc 比較以確認自身是否過載,並在容器內讀取 /sys/fs/cgroup/cpu.stat 以檢查配額限制造成的節流。
我可以從伺服器內部降低 steal time 嗎?
你無法從 guest 內部變更主機的排程方式。你只能降低它造成的影響。請使用少於 vCPU 數量的 worker threads,讓較少工作停留在 run queue 中等待尚未可用的核心。將批次工作移到節點較不繁忙的時段執行。快取結果,讓更少請求需要使用 CPU。真正能消除 steal 的措施,例如遷移到其他節點或使用 dedicated cores,屬於 provider 端的處理範圍。