AI Infra 训练营
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub

iotop —— 进程级 I/O 实时监控

一句话定义

iotop 类似 top 但是显示哪个进程在做磁盘 I/O——按读写量排序。当 iostat 告诉你"磁盘忙"、用 iotop 找"是谁的"。

典型场景

  • top 看到 %iowait 高、找哪个进程在烧 I/O
  • 节点磁盘满了、找谁在猛写
  • 数据库慢、看是不是另一个进程在抢盘
  • K8s 节点排错"是 etcd 还是 containerd 还是用户 pod"

装

apt install -y iotop                        # Ubuntu / Debian
yum install -y iotop                        # CentOS / RHEL

需要 root 才能完整跑

$ iotop
Could not run iotop as some of the requirements are not met:
- Linux >= 2.6.20 ... [OK]
- ... [OK]
- Running as root [FAIL]

普通用户跑 iotop 报错 / 看不到别人进程的 I/O。必须 root:

sudo iotop

或者给 binary 加 capability(不推荐):

setcap 'cap_net_admin,cap_sys_ptrace=eip' $(which iotop)

1. 基本界面

$ sudo iotop
Total DISK READ:    1.5 M/s | Total DISK WRITE:   8.2 M/s
Current DISK READ:  1.2 M/s | Current DISK WRITE: 5.8 M/s
   TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>     COMMAND
  1234 be/4  mysql       500 K/s    5.0 M/s   0.00 %  45.00 %  mysqld
  5678 be/4  postgres    300 K/s    2.0 M/s   0.00 %  15.00 %  postgres
  9012 be/4  root         50 K/s    100 K/s   0.00 %   2.00 %  containerd

逐字段:

字段含义
Total DISK READ/WRITE节点总 I/O 吞吐
Current当前刷新周期的 I/O
TID线程 ID(不是 PID——iotop 显示线程级)
PRIOI/O 调度优先级
USER进程所属用户
DISK READ/WRITE该线程的 I/O 吞吐
SWAPIN该线程因 swap 引起的 I/O 比例
IO>I/O wait 时间百分比(关键指标)
COMMAND命令

IO> 列 —— 关键指标

IO> = 该线程在 iowait 状态的时间百分比。

  • IO> 0 —— 没等过 I/O
  • IO> 50 —— 一半时间在等 I/O
  • IO> 99 —— 几乎全在等 I/O = 严重 I/O 瓶颈

比 DISK READ/WRITE 更能反映"这个进程被 I/O 拖累"——量大但 IO> 低 = I/O 很快、不卡;量小但 IO> 高 = I/O 慢、卡得这进程做不了事。


2. 核心 flag

sudo iotop -o                               # only 只显示有 I/O 的进程
sudo iotop -P                                # process(线程合并成进程)
sudo iotop -b                                # batch 模式(脚本用)
sudo iotop -n 5                              # 跑 5 次就退
sudo iotop -d 5                              # 5 秒刷新(默认 1 秒)
sudo iotop -a                                # accumulated 累计模式
sudo iotop -k                                # KB 单位
sudo iotop -u <user>                         # 只看某用户
sudo iotop -p <PID>                          # 只看某 PID

-o —— 必加

不加 -o 看到一堆没 I/O 的进程、找有 I/O 的费劲。

sudo iotop -o                                # 干净的输出

-P —— 进程级(vs 线程级)

sudo iotop                                   # 默认线程级(**TID**)
sudo iotop -P                                # 进程级(PID)

线程级有时太细——Java 应用上百线程都在做 I/O 看不过来。-P 合并成进程视角。

-a —— 累计

默认 iotop 显示当前采样周期的 I/O。-a 改成"程序启动以来的累计"。

sudo iotop -ao
# 找"总共 I/O 最多的进程"

适合长期观察"谁是 I/O 大户"。


3. 交互按键

iotop 跑着时:

键作用
q退出
o切换 -o(只显示有 I/O)
p切换 -P(进程级)
a切换累计 / 当前
r反转排序
← / →改排序列
? / h帮助

4. Batch 模式(脚本 / 监控)

sudo iotop -bo -n 1                          # 跑一次、跳过 0 I/O、退出

适合脚本周期采样:

#!/bin/bash
# 每 30 秒采样一次 top 10 I/O 进程
while true; do
  date >> /var/log/iotop.log
  sudo iotop -bo -n 1 -P | head -15 >> /var/log/iotop.log
  sleep 30
done

或者用更现代的 eBPF 工具(biotop from bcc)。


5. 实战场景

场景 1:top 看 wa 高、找元凶

$ top
%Cpu(s):  3.0 us, 1.0 sy, 0.0 ni, 50.0 id, 45.0 wa, ...
                                              ^^^^
                                              I/O wait 45%

$ sudo iotop -o
   TID  PRIO  USER  DISK READ  DISK WRITE  SWAPIN   IO>   COMMAND
  1234 be/4  mysql    0 B/s     50 M/s     0%      80%   mysqld -- ...
                                                         ^^^^^^^^^
                                                         元凶

→ MySQL 在猛写。看应用为什么:是慢查询、批量 insert、还是 fsync 风暴。

场景 2:K8s 节点 I/O 飙

$ ssh m4 'sudo iotop -bo -n 3 -P | head -20'
   PID  PRIO  USER       DISK READ  DISK WRITE  IO>   COMMAND
  5678  be/4  root         20 M/s     500 M/s   30%   containerd-shim ...
  9012  be/4  root          5 M/s     100 M/s   10%   etcd

containerd-shim 500 MB/s 写 → 某 pod 在猛写。

找具体 pod:

$ ssh m4 'cat /proc/5678/cgroup | head -3'
0::/kubepods/burstable/pod-xxx-yyy/abc...
              ^^^^^^^^^^^^^^^^^^^^
              pod uid → 反查 K8s pod

$ kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.uid} {.metadata.namespace}/{.metadata.name}{"\n"}{end}' | grep "^xxx"
default/noisy-app

→ 找到了:default/noisy-app 这个 pod 在猛写。

场景 3:找 deleted 文件还在写

$ sudo iotop -o
   TID  USER  DISK READ  DISK WRITE  IO>  COMMAND
  1234 root   0 B/s      30 M/s     50%  rsyslogd

$ lsof -p 1234 | grep deleted
rsyslogd 1234 root  8w   REG  ... /var/log/syslog (deleted)
                                                 ^^^^^^^^^^^
                                                 还在写已删的文件!

rsyslogd 还在写已删的 /var/log/syslog → 重启 rsyslog 释放空间。

场景 4:监控某用户的 I/O

# 看 mysql 用户的 I/O 总量
sudo iotop -ouP -u mysql

或者按 cgroup(K8s 场景):

# 在某个 pod 的 cgroup 下监控
sudo iotop -bo -n 1 | awk '{ ... 按 cgroup 过滤 ... }'

iotop 不直接支持 cgroup 过滤、要手动处理。新版 bcc-tools 的 biotop 更适合容器场景。


6. 替代 / 更现代工具

biotop (bcc / eBPF)

apt install -y bpfcc-tools                  # Ubuntu
yum install -y bcc-tools                    # CentOS

biotop 5                                     # 5 秒刷新

输出和 iotop 类似但基于 eBPF、没 setuid 安全风险、容器感知。

pidstat -d

$ pidstat -d 1
Linux ... (m4)  2026-05-27  _x86_64_  (4 CPU)

14:30:01      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
14:30:02      0        1234       0.00   5000.00     0.00      10  mysqld
14:30:02     27        5678     500.00   2000.00     0.00       5  postgres

pidstat -d 来自 sysstat 包(和 iostat 同包)。iodelay 列类似 IO>。

更轻量、更稳定、适合脚本。

atop

apt install -y atop
atop -d                                      # disk 视图

atop 显示更全(CPU + 内存 + 磁盘 + 网络 + 进程)、按 d 切到磁盘视图。

iotop-c

iotop-c 是 iotop 的 C 重写版(社区)—— 不需要 root capability、更现代。但不普及、用 iotop 原版即可。


7. 反面教材

反面 1:iotop 默认看到的不是进程是线程

$ sudo iotop
   TID  ...   COMMAND
  1234       java
  1235       java        ← 同 java 不同线程
  1236       java
  1237       java

每个线程一行 → Java 应用上百行看不过来。加 -P 进程级。

反面 2:以为 IO> 100% 一定瓶颈

IO> 100% 单进程意味着"这个进程在用全部 CPU 等 I/O"——可能是单进程吞吐瓶颈。

但节点级可能没问题(其它进程跑得正常)。看 top 的全局 %iowait:

%iowait 5%                               ← 节点级不忙
但某个 java 进程 IO> 95%                  ← 单进程在等

= 这个进程对它要做的事来说 I/O 慢、但节点磁盘有富余。可能:

  • 这个进程的 I/O 模式不友好(同步小写 / fsync 多)
  • 还可以并发更多进程榨干磁盘性能

反面 3:iotop 看不到 buffer cache I/O

$ kubectl exec my-pod -- dd if=/dev/zero of=/data/test bs=1M count=1000

$ sudo iotop -o
# 看不到这个进程!

dd 通过 page cache 写、还没真落盘。iotop 只看到实际块设备 I/O。

要看应用层的 I/O 加 oflag=direct:

dd if=/dev/zero of=/data/test bs=1M count=1000 oflag=direct
# 跳过 page cache、直接写盘

反面 4:用 iotop 监控不要持续跑

iotop 自身有 CPU 开销(轮询 /proc)。生产环境别 24x7 跑——用 sar / Prometheus 长期监控、iotop 只是排错时临时跑。

反面 5:iotop 在容器里完全不工作

$ kubectl exec my-pod -- iotop
# Could not run iotop ...

K8s pod 默认没 CAP_SYS_PTRACE / 看不到节点全局 I/O。

节点上跑而不是 pod 里。要看 pod 视角的 I/O:

  • pod cgroup io.stat:cat /sys/fs/cgroup/io.stat
  • Prometheus container_fs_*

8. 关联命令

  • iostat —— 节点磁盘综合 → 用 iotop 找具体进程
  • top —— %iowait 判断是不是 I/O 瓶颈
  • lsof —— iotop 找到 PID 后看它开了什么文件
  • pidstat -d —— 类似 iotop、轻量级
  • biotop (bcc) —— eBPF 现代版
  • atop —— 综合监控
在 GitHub 上编辑此页