SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-08-23

VPS CPU steal time 与邻居噪声怎么判断

了解 VPS 的 CPU steal time:读取 vmstat 的 st 列,区分自身过载与邻居争用,并注意 VMware、Hyper-V 客户机可能始终显示 0 的版本与平台陷阱。

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

CPU steal time 的实际含义

CPU steal time 表示:虚拟 CPU 已准备好运行且无需等待,但虚拟机管理程序将物理核心分配给了另一个 guest 的那段时间占比。任务已经排队,但物理核心被分配到了其他位置。Linux 会单独统计这些周期,并将其报告为 st。通过该指标,可以区分“我的服务器很忙”和“我的服务器正在等待调度”。

这正是该计数器存在的原因。进程在 CPU 上实际运行的时间会报告为 us(用户态)或 sy(系统态)。任务因存储操作而阻塞的时间会报告为 wa(I/O wait)。如果 vCPU(虚拟 CPU)处于可运行状态,位于运行队列中,没有未完成的 I/O,但仍未执行,则会报告为 st。服务器内部的任何操作都无法清除这种状态,因为调度决策是在下一层的宿主机上完成的。

这直接源于 VPS 如何共享一台物理机。通常原因是邻居 guest:同一节点上的另一个 guest 负载很高,因此宿主机需要在多个 guest 之间分配物理核心。还有一个容易被忽略的原因。许多提供商会将共享 vCPU 限制为物理核心的一部分;在一些虚拟机管理程序中,这个强制执行的限制会在 guest 内部计入 steal time。因此,较高的 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 个值。下面的每个工具,包括 vmstattopmpstat 和任何 Prometheus exporter,都会读取同一字段,并根据两次采样计算百分比。

其中一个后果尤其重要。如果 hypervisor 从不导出该计数器,该字段会永久保持为 0,所有基于该字段的工具都会报告平稳的 0.0,即使宿主机已经过载。KVM 和 Xen 会导出该计数器。VMware 和 Hyper-V 上的 guest 通常会持续报告 0。信任 0 之前,先检查平台:

systemd-detect-virt

该命令会输出平台名称,例如 kvmxenvmwaremicrosoft;在裸机上则输出 none。在容器内,它会改为报告运行时,例如 lxcdockerpodman。这只能说明容器的运行环境,不能说明其下方的机器。在 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 会每秒采集一次样本,共采集五次。

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 是从右侧数第二列,而不是最后一列。请根据列标题读取该列,因为该位置在不同版本中发生过变化。

以下两个习惯有助于确保读数准确。第一行数据表示自启动以来的平均值,因此应忽略该行,读取后面的行。单个样本也不能作为测量结果,因为 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 5

mpstat 会为每个 CPU 输出一行,其中包含 %steal 列,用于显示所有 vCPU 是否都受到影响,还是只有一个 vCPU 受到影响。若要保留支持工单所需的历史记录,请保存样本,而不要只在屏幕上查看:

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

在你怀疑出现问题的时间段内,通过 cron 运行该命令。这样,文件中就会保存精确的十分钟记录,而不只是告诉服务提供商“昨晚感觉很慢”。

偷占用率数值表示什么?

  • 稳定的 0.0 系统运行正常,或者平台完全不报告 steal。庆祝之前,先使用 systemd-detect-virt 确认。
  • 持续数秒的几个百分点峰值。 在任何共享节点上都很正常。邻居可能启动了构建任务,或者主机正在运行备份。
  • 共享方案中持续保持 1 到 5 percent。 这是预期情况。价格反映的就是共享 CPU。
  • 持续保持 5 到 10 percent。 这已经是可以测量的性能下降。开始记录证据,并比较连续几天相同时间段的数据。
  • 一次持续数小时、超过 10 percent。 对你的工作负载而言,该节点超额分配了资源。这种情况足以提交支持工单或迁移服务。

请将这些区间作为参考,而不是规格保证,因为没有任何服务提供商会为共享方案发布 steal 保证。应结合你的实际工作负载进行判断。夜间批处理任务即使承受 15 percent 的 steal,通常也不会被察觉。对延迟敏感的服务,p99 指标会在平均值显得异常之前反映问题,因此 交易机器人等延迟敏感的工作负载 应运行在专用核心上。

偷取时间会造成多少成本?

计算很简单。如果 CPU 时间中有 s 被占用,需要固定 CPU 时间的任务在实际时钟时间上就会变为原来的 1 / (1 - s) 倍。对于需要 60 秒 CPU 时间的任务:

ChartWall clock time for a job needing 60 seconds of 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% 的情况下,这是普通共享型套餐中的常见读数,该任务需要 61.9 秒,而不是 60.0 秒。通常不会有人因此提交工单。在 8% 时,需要 65.2 秒。在 40% 时,同一任务需要 100.0 秒,原本可以持续清空的队列则会开始增长。

这些是计算值,不是测量值。该模型假设只有一个可运行线程,并且偷取时间在整个时间间隔内均匀分布。实际服务通常会感觉比曲线显示的情况更糟,因为被偷取的时间片可能发生在请求处理中间,等待该请求的所有操作随后还要再次承担这段延迟。要获得自己的数据而不是使用公式,请在低峰时段和高峰时段分别对 VPS 进行基准测试,并记录两个时间窗口的 st

这是 steal,还是其他问题?

Steal 很容易与其他症状混淆。请在同一行 vmstat 中结合查看这些计数器。

  • st 较高,而 rus 保持较低:主机没有向你提供 CPU 核心时间。这就是 steal。
  • r 明显高于你的 vCPU 数量,同时 us 较高、st 接近 0:你运行的工作量超过了自有 CPU 的处理能力。将 rnproc 的输出进行比较。这是你自己的超额订阅,不是邻居实例造成的。
  • wa 较高,而 st 接近 0:任务被存储操作阻塞。这是另一类问题,需要采用不同的修复方法。
  • 负载平均值较高,而 stus 都较低:负载值还会统计不可中断任务,因此这通常表示设备卡住或网络挂载无响应,而不是 CPU 问题。

突发型计划需要单独说明。这类计划会在实例空闲时累积信用额度,在实例繁忙时消耗信用额度;额度用尽后,云服务提供商会将实例限制在基准速率。某些平台会将这种限速报告为 steal。其他平台不会在实例内部显示该限速,你只会获得更少的每秒 CPU 周期。在判断是否由邻居实例造成问题之前,请先阅读计划说明。

为什么容器报告没有 steal time

Steal 是虚拟机的属性,不是其中运行的容器的属性。您在自己的 VPS 上运行的 Docker 容器会共享主机的 /proc,因此在容器内读取的 st 值就是 VPS 的 steal,这正是您需要的结果。作为 VPS 销售的基于容器的虚拟化则不同。启用 lxcfs 后,容器内的 /proc/stat 会根据 cgroup 统计信息合成,因此 steal 按设计始终为 0。只从容器内部抓取指标的监控系统,可能显示一个平稳且毫无异常的 0,而底层物理机实际上已经资源不足。

在容器内,具有相同含义的计数器是 CPU 配额限流。在 cgroup v2 中:

cat /sys/fs/cgroup/cpu.stat

nr_throttled 统计该组触发 CPU 配额的强制执行周期数,throttled_usec 统计该组被冻结的总时间。nr_throttled 持续上升表示您的进程处于可运行状态,但没有获得运行机会;这与 steal 的体验相同,但原因是您自行设置了限制。请先检查您自己的限制,再判断是否应归咎于主机。尤其是在 compose 文件中设置了 CPU 限制,并且您 在 VPS 上使用 Docker 运行服务时,更应如此。分层虚拟化会增加一个额外的时间损耗来源,因为 VPS 内的虚拟机既要承担 VPS 的 steal,还要承担自身的调度延迟。如果您 在 VPS 上运行嵌套虚拟化,请注意这一点。

如何处理持续的 steal

来宾系统内的任何设置都无法修复 steal,因为作出调度决定的调度器运行在来宾系统之外。升级内核也不会改变这一点:Linux kernel 7.2 中加入的缓存感知调度会在实际分配给您的核心之间重新安排任务,但无法恢复邻居已经占用的 CPU 周期。真正有效的措施有4项。

先收集证据。 记录 UTC 时间戳、每次事件的持续时间、重复频率,以及 mpstat 是否显示只有一个 vCPU 受影响,还是所有 vCPU 都受影响。连续记录一周的样本,比一张屏幕截图更有价值。

使用这些数据提交工单。 直接询问两个问题:这些时间段内该节点是否超额分配,以及是否可以迁移您的实例。附上 vmstat 输出和准确时间。服务提供商会根据可复现的时间窗口处理问题;只说服务器运行缓慢的工单,通常会收到要求提供时间窗口的回复。您可以将多少工作交给服务提供商处理,是托管 VPS 与非托管 VPS之间的实际差异之一。

请求迁移。 服务提供商通常可以将来宾系统迁移到负载较低的节点,这一般只需要短暂重启。这种修复不产生额外费用,适用于常见情况:某个节点恰好同时承载了多个高负载邻居。

购买独占资源以避免争用。 独占 vCPU 方案会为您的实例预留物理核心,因此该计数器会保持为0。每月费用更高,但对于无法承受性能波动的工作负载,这是合理的选择。如果这仍然不够,或者您还希望独占内存带宽,下一步就是选择独立服务器而不是 VPS

在等待上述处理期间,先降低 steal 带来的影响。将工作线程数设置为少于 vCPU 数量,因为无法获得核心的线程只会增加上下文切换。将批处理工作移到节点较空闲的时间段,您现在的日志可以帮助确定这些时间。然后在相同时间段内使用相同命令重新测量,这样就能判断调整是否有效,而不是凭猜测。

FAQ

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

在共享套餐中,短暂的峰值以及持续低于约 5% 的数值都属于正常情况,因为共享 CPU 意味着主机会在多个虚拟机之间分配物理核心。持续数小时达到两位数则不正常,建议提交工单。在 dedicated vCPU 套餐中,预期读数为 0.0,因此出现其他数值时应报告故障。应结合自身工作负载判断该数值:夜间批处理任务可以承受 steal time,但对延迟敏感的 API 则不能。

更大的套餐能解决高 steal time 吗?

不能单靠升级套餐解决。同一共享节点上的 vCPU 越多,表示有更多虚拟 CPU 争用同一组繁忙的物理核心,因此百分比可能完全不变。只有 dedicated CPU 分配,或迁移到负载更低的节点,才能消除 steal time。更繁忙主机上更大的资源份额,仍然只是繁忙主机上的一份资源。

为什么 VPS 明显变慢,但显示的 steal time 却是 0?

常见原因有两个。虚拟机监控程序可能根本不提供该计数器。VMware 和 Hyper-V 平台通常如此,因此无论主机实际情况如何,该字段都会保持为 0。运行 systemd-detect-virt 查看当前使用的平台。否则,瓶颈可能在其他位置:检查 wa 了解存储等待,比较 rnproc 判断是否是自身负载过高,并在容器中读取 /sys/fs/cgroup/cpu.stat 检查配额限流。

可以在服务器内部降低 steal time 吗?

无法从 guest 内部更改主机的调度方式。只能降低它造成的影响。运行的 worker 线程数应少于 vCPU 数量,避免过多任务进入 run queue,等待无法获得的核心。将批处理任务移到节点负载较低的时段运行。缓存结果,减少实际需要 CPU 处理的请求。真正能够消除 steal time 的措施,例如迁移到其他节点或使用 dedicated cores,需要由服务提供商执行。