SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor

VPS CPU steal time 與鄰居干擾怎麼看

了解 CPU steal time 的確切意義,讀懂 vmstat 的 st 欄位,並用具體方法判斷問題來自 noisy neighbour,還是 VPS 自身過載。

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, August 7, 2026.

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。伺服器內部的任何元件都無法清除這個狀態,因為排程決策是在更底層的主機上做出的。

這直接源自 VPS 如何在多個 guest 之間共用一台實體機器。最常見的原因是鄰近 guest:同一個 node 上的另一個 guest 負載很高,因此主機必須在各 guest 之間分配核心。另一個容易被忽略的原因是,許多供應商會將共用 vCPU 限制在實體核心的一部分,而在某些 hypervisor 上,這項強制套用的限制會在 guest 內計入 steal。因此,高 st 數值表示核心沒有分配給您,但不一定能指出是誰佔用了核心。

Steal 數值的來源

核心無法自行測量 steal,因為它看不到主機。這項資訊由 hypervisor 提供。在 KVM 上,主機會將每個 vCPU 的計數器寫入與 guest 共用的頁面;當核心建置時包含 CONFIG_PARAVIRT_TIME_ACCOUNTING,guest 核心就會累加這些數值,所有發行版核心都包含此功能。Xen 則透過 runstate 區域回報相同資訊。總計數值只會在一個位置提供給 userspace:

head -1 /proc/stat

這行 cpu 包含 10 個計數器,單位是自開機以來的 USER_HZ tick,順序如下: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,是否看得到 steal,取決於主機匯出的資訊以及 guest 核心支援的功能。因此,看到固定的 0 本身無法證明任何事情。信任 0 之前,先確認平台:

systemd-detect-virt

此命令會輸出平台名稱,例如 kvm、xen、vmware 或 microsoft;在 bare metal 上則會輸出 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 5

vmstat --version 會輸出類似 vmstat from procps-ng 4.0.4 的一行內容。若能輸出該內容,表示工具已安裝,且讀取的是實際的核心計數器。接著,vmstat 1 5 會輸出 5 份報告:第 1 份是自開機以來的平均值,後 4 份是每秒取樣結果。

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 建置版本會在該欄位後方輸出 gu 欄位,用來表示 KVM guest time,因此 st 是從右側數來第 2 欄,而不是最右欄。請依欄位標題讀取數值,因為該位置在不同版本之間曾經變更。

請養成兩個習慣,確保讀值正確。第 1 行資料是自開機以來的平均值,因此請忽略該行,改讀後續各行。其次,單次取樣不能代表實際狀況,因為 steal time 可能以突發方式出現:執行 vmstat 1 61,在自開機以來的那一行後提供 60 次每秒取樣,並觀察完整 1 分鐘後再下結論。

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 5

mpstat 會為每個 CPU 輸出一列,並包含 %steal 欄位,可用來判斷所有 vCPU 都受到影響,還是只有其中一個受到影響。若要保留支援工單所需的歷史資料,請儲存取樣結果,不要只在畫面上查看:

date -u | tee -a ~/steal.log
mpstat -P ALL 1 5 | tee -a ~/steal.log

請在你懷疑發生問題的時段,透過 cron 執行該命令。如此一來,檔案就能讓你向供應商提出確切的 10 分鐘資料,而不是只說「昨晚感覺速度很慢」。

steal 數值代表什麼?

  • 穩定維持在 0.0。 表示狀況良好,或平台根本不回報 steal。先用 systemd-detect-virt 確認,再下結論。
  • 持續數秒、幅度只有幾個百分點的尖峰。 任何共用節點都可能發生。鄰近租戶啟動建置工作,或主機正在執行備份。
  • 在共用方案中持續維持 1 到 5 個百分點。 屬於預期情況。方案價格反映的就是共用 CPU。
  • 持續維持 5 到 10 個百分點。 這已是可測量的效能下降。開始記錄證據,並比較數天內相同時段的數值。
  • 每次持續數小時、超過 10 個百分點。 可能是節點對你的工作負載超額配置,也可能是方案正在套用 CPU 上限;部分供應商會將這項限制回報為 steal。達到這個程度,就有理由提交支援工單或更換方案。

請將這些區間視為判讀指南,而不是規格,因為沒有供應商會對共用方案提供 steal 保證。判斷時也要考量你的工作負載。夜間批次工作即使承受 15 個百分點的 steal,通常也不會有人察覺。對延遲敏感的服務,p99 延遲會遠早於平均值變得令人擔憂,因此 交易機器人等延遲敏感的工作負載應配置在專用核心上。

Steal time 的成本是多少?

計算很簡單。如果 CPU 時間中有 s 被占用,需要固定 CPU 時間的工作,在實際經過時間上會變成原本的 1 / (1 - s) 倍。以需要 60 秒 CPU 時間的工作為例:

圖表Wall clock time for a job needing 60 seconds of CPU
此圖表背後的資料
[
  {
    "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 秒。這通常不至於讓人提出支援請求。在 8 percent 時,需要 65.2 秒。在 40 percent 時,同一項工作需要 100.0 秒,原本能逐漸清空的佇列也會開始累積。

這些是計算值,不是測量值。此模型假設只有一個可執行執行緒,且 steal time 平均分布在整個期間。實際服務通常會比曲線顯示的情況更差,因為被占用的時間片可能落在請求處理期間,而所有等待該請求的工作都必須再次承擔這段延遲。若要取得自己的數值,而不是套用公式,請在低負載時段和高負載時段各執行一次 VPS 效能基準測試,並記錄兩個時段的 st。

這是 steal,還是其他問題?

Steal 很容易與其他症狀混淆。請在同一行 vmstat 中一起查看這些計數器。

  • st 偏高,而 r 與 us 維持偏低:主機沒有把 CPU 核心時間分配給你。這就是 steal。
  • r 明顯高於你的 vCPU 數量,且 us 偏高、st 接近 0:你執行的工作量超過自有 CPU 的處理能力。將 r 與 nproc 的輸出比較。這是你自己的超額配置,不是鄰近租戶造成的。
  • wa 偏高,而 st 接近 0:工作正在等待儲存裝置。這是不同的問題,也需要不同的處理方式。
  • 負載平均值偏高,但 st 與 us 都偏低:負載數值也會計入不可中斷的工作,因此通常表示裝置卡住或網路掛載無回應,而不是 CPU 問題。

Burstable 方案需要另外說明。這類方案會提供 credit balance;閒置時累積,忙碌時消耗。額度用完後,供應商會將你的速率限制在基準值。有些平台會將這項節流回報為 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.stat

nr_throttled 計算該群組觸及 CPU quota 的 enforcement period 次數,throttled_usec 則累計其遭凍結的時間。nr_throttled 持續上升表示你的程序處於 runnable 狀態但未獲得執行時間,體驗上與 steal 相同,但原因是你自行設定的限制。先檢查自己的限制,再判斷是否應歸咎於主機;如果你在 compose 檔案中設定 CPU limits,尤其要確認這點,例如 在 VPS 上使用 Docker 執行服務。分層虛擬化會增加另一個時間耗損點,因為 VPS 內的 VM 必須承受 VPS 的 steal,以及自身的排程延遲。如果你 在 VPS 上執行巢狀虛擬化,請將這點納入考量。

持續發生 steal 時的處理方式

Guest 內沒有任何設定能修正 steal,因為做出排程決策的 scheduler 在 guest 外部執行。升級 kernel 也不會改變這點:Linux kernel 7.2 新增的快取感知排程會在實際分配給你的 core 之間重新安排工作,但無法取回鄰近 guest 已經占用的 CPU 週期。實際可行的做法有4種。

先蒐集證據。 記錄 UTC 時間戳記、每次事件的持續時間、重複發生的頻率,以及 mpstat 顯示的是單一 vCPU 受到影響,還是全部 vCPU 都受到影響。持續記錄一週的樣本,比單張螢幕截圖更有價值。

附上資料建立支援請求。 直接詢問2個問題:這個 node 是否在這些時段超額配置,以及是否能將你的 instance 搬移到其他 node。貼上 vmstat 的輸出和確切時間。Provider 需要可重現的時段才能處理;只寫「server 很慢」的支援請求,通常會收到要求提供時段的回覆。你能將多少這類工作交由他人處理,是受管理與非受管理 VPS之間的實際差異之一。

要求搬移。 Provider 將 guest 搬到負載較低的 node 是例行作業,通常只需短暫重新開機。這種修正不需額外費用,並能解決常見情況:某個 node 恰好同時承載數個高負載的鄰近 guest。

付費消除資源競爭。 Dedicated vCPU 方案會為你的 instance 保留 CPU 容量。依 Provider 而定,可能是完整 core 或完整 hardware thread。如此一來,鄰近 guest 不會再占用你的 CPU 週期,計數器也會維持在0或非常接近0。Hypervisor 自身的 housekeeping 仍可能留下少量殘值。這會增加每月費用,但對無法承受效能波動的工作負載而言,這是誠實的答案。如果這仍然不夠,或你也希望獨享 memory bandwidth,下一步就是選擇dedicated server,而不是 VPS。

在等待上述處理期間,先降低 steal 造成的影響。執行的 worker thread 數量應少於 vCPU 數量,因為無法取得 core 的 thread 只會增加 context switch。將批次工作移到 node 較清閒的時段執行;現在你自己的 log 已經能指出這些時段。接著使用相同的 command,在相同時段重新測量,這樣才能判斷變更是否有效,而不是憑猜測下結論。

FAQ

VPS 上正常的 CPU steal time 是多少?

在共用方案中,短暫的尖峰,以及持續低於約 5 percent 的數值,都屬於正常情況。這是因為共用 CPU 會讓主機在不同 guest 之間分配實體核心。若數值持續數小時維持在兩位數,則不屬於正常情況,建議提交支援工單。在 dedicated vCPU 方案中,預期讀值應為 0.0 或非常接近此值。這是因為 hypervisor 的 housekeeping 仍可能占用少量 CPU。因此,若 steal time 持續高於此值,應回報為故障。請根據自身工作負載判斷數值:需要整夜執行的批次工作可以承受 steal time,但對延遲敏感的 API 則不同。

擴大方案能解決高 steal time 嗎?

不能單靠擴大方案解決。在同一個共用節點上增加 vCPU,代表更多 virtual CPU 競爭相同的高負載實體核心,百分比可能完全不變。能幾乎消除 steal time 的方式,是配置 dedicated CPU,或移轉到負載較低的節點。忙碌主機上較大的資源配額,仍然只是忙碌主機上的共用資源。

為什麼我的 VPS 明顯變慢,卻顯示 0 steal time?

常見原因有兩個。hypervisor 可能根本不提供這個計數器。部分平台會依主機與 guest kernel 的不同而有此情況,因此無論主機實際狀況如何,欄位都會維持為零。執行 systemd-detect-virt,查看目前使用的平台。否則,瓶頸可能在其他地方:檢查 wa 的 storage wait,使用 r 與 nproc 比較自身的 overload,並在容器內查看 /sys/fs/cgroup/cpu.stat,確認是否受到 quota throttling。

我可以從伺服器內部降低 steal time 嗎?

你無法從 guest 內部變更主機的排程方式。你只能降低它造成的影響。執行的 worker thread 數量應少於 vCPU 數量,讓較少工作停留在 run queue 中,等待不會分配到的核心。將批次工作移到節點較不忙碌的時段。快取結果,讓較少請求需要使用 CPU。真正能移除 steal time 的措施,例如移轉到其他節點或使用 dedicated core,必須由 provider 端處理。