题干与适用场景
一台 Linux 主机的 %iowait 从 3% 升到 38%,业务 p99 延迟翻倍,而整体 CPU 使用率只有 30%。请说明如何区分本地块设备、NFS、内存回收、hypervisor steal,以及采集范围不一致造成的假象。
这道题考察 SRE、DevOps、后端和系统岗位的诊断能力。38%、30% 和 p99 翻倍是虚构练习数据,不是通用阈值。回答应先解释 /proc/stat 的 iowait,再用 vmstat、iostat、pidstat、PSI、cgroup 和内核日志建立证据链。
面试官考察点
记账边界
候选人要知道 iowait 是 CPU 统计字段,不是磁盘利用率,也不等于所有任务等待 I/O 的总时长。多核调度会让归属变得不精确。
证据分层
强回答会从主机平均值深入每核、线程、cgroup、设备和业务尾延迟,说明每个观测如何改变假设。
等待路径
应区分本地块 I/O、NFS/FUSE、数据库 RPC、内存回收和 hypervisor steal。不同路径需要不同工具和处置。
安全闭环
回答要包含留证、低风险止损和恢复验收,避免直接重启、杀进程或提高并发放大故障。
回答前需要澄清的问题
- iowait 来自主机还是容器?主机
/proc/stat与服务 cgroup 可能不是同一范围。 - 是每核都高,还是单核高?平均值会隐藏 affinity、NUMA 或配额造成的局部饱和。
- 请求等待的是文件、块设备还是网络 RPC?NFS、数据库和 HTTP 的证据不同。
- p99 与 I/O 指标是否严格同窗?要对齐采样、发布、备份和流量。
- 是否有 swap、major fault、memory PSI 或 steal time?
- 是否有权限读取线程栈和 cgroup 文件?生产排查应采用最小权限。
30 秒回答框架
“38% iowait 是线索,不是磁盘故障结论。先对齐主机、服务和 p99 的时间窗,再看每核 mpstat、vmstat r/b、CPU/IO/memory PSI、cgroup 配额和 steal time。
若设备队列、延迟、进程读写与内核错误一起异常,查块设备;若线程停在 NFS 或文件系统而本地设备正常,查挂载、网络和服务端;若 memory PSI、swap、major fault 上升,查工作集;若 steal 上升,查宿主机。止损后同时验证业务尾延迟、等待线程、PSI 和底层资源。”
分步骤深入解答
第一步:解释 iowait 的边界
/proc/stat 的 iowait 是等待 I/O 完成时的 CPU 时间记账。CPU 可以在一个任务等待时运行其他任务;多核下等待任务也不一定归属于同一个 CPU。因此低 iowait 不能排除远程存储或内核等待,高 iowait 也不能单独证明磁盘故障。
第二步:看每核和实时队列
mpstat -P ALL 1 10
vmstat 1 10
cat /proc/loadavgr 持续高且 CPU busy 高,支持 CPU 排队;b 持续高,优先调查不可中断等待。每核数据、affinity、cgroup quota 和 throttling 能揭示“总体 30%、局部已饱和”。
第三步:用 PSI 量化停顿
for r in cpu io memory; do echo "[$r]"; cat /proc/pressure/$r; donePSI 的 some 表示至少部分任务因资源停顿,full 表示所有非 idle 任务同时停顿;avg10/60/300 表示趋势。读取目标 cgroup 的 pressure 文件,才能区分服务自身压力与同机噪声。
第四步:定位线程和等待点
ps -eLo state,pid,tid,wchan:32,comm --sort=state
pidstat -d -p ALL 1 10按 R/D 状态、命令、cgroup 和 wchan 聚合。权限允许时读取代表性线程的 /proc/PID/stack。wchan 只是当前睡眠位置,必须和时间相关性、PSI、业务延迟互相印证。
第五步:进入对应子系统
iostat -xz 1 10
dmesg -T | tail -200
cat /proc/meminfo | egrep 'Swap|Dirty|Major'块设备看 await、队列、吞吐和错误;NFS/FUSE 看挂载、重传、网络和服务端;内存看 memory PSI、swap 和 major fault;数据库或 HTTP RPC 要补应用追踪和连接池指标。
第六步:止损并验证
先保存线程、PSI、设备和日志快照,再按证据限流、暂停批任务、切换健康副本或修复挂载。不要反复 kill -9 D 状态任务,信号通常要等等待返回后才能处理。修复后同时验证 p99、错误率、R/D 数、PSI、资源延迟和积压。
高质量示范回答
“我不会把 38% iowait 直接等同于磁盘故障。它是受多核调度影响的 CPU 记账字段。我先对齐范围和时间窗,再看每核 mpstat、vmstat r/b、CPU/IO/memory PSI、cgroup quota 和 steal time。
若 D 线程和 I/O PSI 增加,wchan 指向块 I/O,iostat 的延迟和队列也上升,就检查设备、文件系统和内核错误。若本地设备正常而线程集中在 NFS,则查挂载、重传、网络和服务端。若 memory PSI、swap 或 major fault 上升,则控制工作集;若 steal 上升,则查宿主机。
我会先暂停放大 I/O 的批任务、限流或切换健康副本并保留现场。恢复验收看业务 p99/错误率、R/D 数、PSI、底层延迟和积压,而不是只等 iowait 回落。”
常见错误
- 把 iowait 当磁盘利用率;应结合
iostat和设备基线。 - 看到 iowait 高就扩 CPU;应先查每核、R/D 和 PSI。
- 看到 iowait 低就排除 I/O;应检查 D 状态、远程存储和 I/O PSI。
- 把所有 D 状态归因于本地磁盘;NFS、驱动和文件系统也会等待。
- 只看主机指标;服务 cgroup 可能有不同配额与压力。
- 只取一次样本;应连续采样并和业务曲线对齐。
- 立即重启或杀进程;先保存现场并评估数据完整性。
- 只等 iowait 降低;应验证用户延迟和资源队列。
追问及应对
追问一:为什么 iowait 高但磁盘 util 不高?
等待可能在 NFS、FUSE、数据库或网络 RPC,也可能是设备映射和时间窗不一致。沿线程等待点、应用追踪、I/O PSI、挂载和网络指标继续定位。
追问二:为什么 iowait 低但请求仍卡住?
任务可能等待锁、连接池、CPU 配额、内存回收或远程 RPC。比较 R/D、线程栈、CPU/memory PSI 和依赖延迟;CPU 记账不会分类所有等待。
追问三:容器如何判断自身 I/O 压力?
读取目标 cgroup 的 io.pressure、I/O 统计和 throttling 事件,再与主机 /proc/pressure/io 和服务 p99 比较。主机高、容器低时扩容服务未必有效。
追问四:D 状态线程可以直接 kill 吗?
可以发信号,但通常要等不可中断等待返回后才处理。先保存堆栈和等待点,修复设备、挂载或驱动;重启要先确认冗余和数据安全。
追问五:如何设置 iowait 告警?
不要使用跨机器通用的固定百分比。把 iowait 与 I/O PSI、设备或远端存储延迟、D 状态、业务 SLO 和持续时间组合,并按基线校准。