K8S 节点 dm-2 磁盘 IO 操作耗时率过高排查文档

AI摘要
【知识分享】这是一份K8S节点磁盘IO告警排查技术文档,系统介绍了dm-2设备IO耗时率过高问题的排查流程。文档从问题背景出发,明确了排查原则(不直接归因、判断持续性、多维度排查),并详细列出了从设备映射确认、告警趋势分析、实时IO监控、进程定位、容器反查、日志检查到业务任务对齐的十二个排查步骤,同时提供了现场抓取命令、一键排查脚本、问题归因参考及客户沟通口径,是一份结构完整、实操性强的运维排障指南。

K8S 节点 dm-2 磁盘 IO 操作耗时率过高排查文档

一、问题背景

生产环境监控告警提示某 K8S 节点磁盘 IO 操作耗时率过高。

告警示例:

告警名称:node-io-operation-time
告警状态:已恢复
告警级别:warning
告警标题:节点磁盘IO操作耗时率过高
告警描述:服务器 192.166.11.102:9100 磁盘 dm-2 IO 操作耗时率为 91.44%,超过 70%
告警修复建议:请检查服务器 IO 操作

当前涉及节点:

节点 IP192.166.11.102
K8S Namespace:ape
告警磁盘设备:dm-2

从节点当前 iostat 结果看,CPU iowait 较低,vda/vdb 磁盘 %util 也较低,暂未观察到持续性磁盘 IO 压力。因此需要进一步确认:

  1. dm-2 实际对应哪块磁盘、哪个挂载目录;

  2. 告警是持续性异常,还是瞬时峰值;

  3. 是否由某个 Pod、进程、日志文件、定时任务或批量任务导致;

  4. 是否存在云盘规格、IOPS、吞吐、宿主机抖动等基础设施侧因素。


二、排查原则

1. 不直接归因

在未确认 dm-2 对应关系前,不能直接判断是某个服务导致,也不能直接排除基础设施侧问题。

需要先明确:

dm-2 -> 底层磁盘 -> 挂载目录 -> 承载数据 -> 相关 Pod/进程

2. 先判断是否持续

磁盘 IO 高通常分为两类:

类型 特征 常见原因
瞬时峰值 某个时间点突然升高,随后恢复 定时任务、批处理、日志集中写入、文件清理、备份、容器重启
持续异常 长时间维持高 IO 等待 日志刷屏、数据库持续写入、磁盘性能瓶颈、应用异常循环、存储设备问题

3. 多维度排查

本问题需要从以下几个维度排查:

设备映射维度
时间维度
进程维度
容器维度
日志维度
业务任务维度
基础设施维度

三、当前初步判断

根据当前 iostat 输出:

%idle     97% ~ 98%
%iowait   0% ~ 0.11%
vda %util 0% ~ 0.40%
vdb %util 0% ~ 0.07%

当前节点磁盘压力较低,暂未观察到持续性 IO 异常。

因此当前更偏向以下几种可能:

  1. 告警时间点存在瞬时 IO 峰值;

  2. 某个服务执行定时任务或批处理任务;

  3. 某个 Pod 日志短时间大量写入;

  4. 监控采集的 dm-2 与当前 iostat 展示的设备名称存在映射差异;

  5. 云盘或宿主机侧存在瞬时抖动。


四、第一步:确认 dm-2 对应的磁盘和挂载目录

1. 查看块设备映射

lsblk -o NAME,MAJ:MIN,SIZE,TYPE,MOUNTPOINT,FSTYPE

重点查看:

dm-2 对应的 mapper 名称
dm-2 对应的挂载点
dm-2 底层依赖的是 vda 还是 vdb

示例关注字段:

NAME        MAJ:MIN   SIZE TYPE MOUNTPOINT FSTYPE
vda         253:0      40G disk
└─vda1      253:1      40G part /
vdb         253:16    100G disk
└─dm-2      252:2     100G lvm  /data1   xfs

2. 查看文件系统挂载情况

df -hT

重点确认:

/ 
/data
/data1
/var/lib/containerd
/var/lib/docker
/var/log

3. 查看 dm-2 实际路径

readlink -f /dev/dm-2

4. 查看 device mapper 信息

dmsetup ls
dmsetup info /dev/dm-2

5. 查看 LVM 信息

如果节点使用 LVM,可以执行:

pvs
vgs
lvs

或者:

lvdisplay

重点确认:

dm-2 属于哪个 VG/LV
LV 挂载在哪个目录
该目录是否承载容器数据、业务数据、日志数据或数据库数据

五、第二步:确认告警是否持续

1. 查看告警平台趋势

需要确认以下信息:

告警开始时间
告警恢复时间
持续时长
是否连续多次触发
是否集中在固定时间点
是否每天定时出现

重点判断:

如果只出现一次,可能是瞬时任务导致;
如果每天固定时间出现,优先怀疑定时任务、批处理、备份、日志归档;
如果持续不恢复,需要现场抓进程级 IO

2. 建议客户提供信息

1\. dm-2 IO 操作耗时率 90% 以上持续了多久?
2. 告警是否多次连续触发?
3. 告警发生时是否有业务批处理、血缘解析、上线任务、数据同步任务?
4. 告警时间点是否与 lake 服务定时任务时间吻合?
5. 告警时间点是否有 Pod 重启、服务发布、日志异常输出?

六、第三步:实时查看磁盘 IO

1. 查看所有磁盘设备 IO

iostat -x -p ALL 1 10

重点关注字段:

字段 含义 关注点
r/s 每秒读次数 是否读请求异常增多
w/s 每秒写次数 是否写请求异常增多
rkB/s 每秒读取 KB 是否大量读取
wkB/s 每秒写入 KB 是否大量写入
r_await 读等待时间 是否读延迟高
w_await 写等待时间 是否写延迟高
aqu-sz 平均队列长度 是否存在 IO 排队
%util 设备利用率 是否接近 100%

2. 单独观察 dm 设备

iostat -x -p ALL 1 10 | grep -E "Device|dm-2|vda|vdb"

3. 判断标准

一般关注:

%iowait 持续升高
dm-2 %util 持续接近 100%
await 明显升高
aqu-sz 持续升高
wkB/s 或 w/s 明显升高

如果当前 iostat 显示:

%iowait 很低
%util 很低
await 很低

说明当前未复现 IO 异常,需结合告警时间点继续观察。


七、第四步:查看高 IO 进程

1. 使用 pidstat 查看进程 IO

pidstat -d -p ALL 1 10

重点关注:

字段 含义
kB_rd/s 每秒读取 KB
kB_wr/s 每秒写入 KB
kB_ccwr/s 被取消的写入 KB
Command 进程名称

2. 按写入量排序

pidstat -d -p ALL 1 10 | sort -k6 -nr | head -30

3. 使用 iotop 查看实时 IO

如果系统已安装 iotop

iotop -oPa

参数说明:

-o  只显示正在产生 IO 的进程
-P  按进程显示
-a  显示累计 IO

持续观察:

iotop -oP

4. 如果没有 iotop

安装:

yum install -y iotop

或:

apt install -y iotop

如果不能安装,优先使用:

pidstat -d -p ALL 1 10

八、第五步:根据 PID 反查进程和容器

假设发现高 IO 进程 PID 为 12345

1. 查看进程基本信息

PID=12345

ps -fp $PID

2. 查看进程启动命令

cat /proc/$PID/cmdline | tr '\0' ' '

3. 查看进程 cgroup

cat /proc/$PID/cgroup

可能看到类似:

kubepods-burstable-podxxxx/cri-containerd-abcdef...

或者:

docker/abcdef123456...

这里可以提取容器 ID。

4. 查看进程打开的文件

lsof -p $PID | head -50

重点过滤:

lsof -p $PID | grep -E "log|tmp|data|containerd|docker|java|jar|mysql|mariadb|redis"

如果看到进程正在频繁写某个日志文件、临时文件或数据文件,就可以进一步定位。


九、第六步:反查容器和 Pod

1. 如果容器运行时是 containerd

查看容器:

crictl ps | grep <容器ID前几位>

查看容器详情:

crictl inspect <容器ID>

快速过滤 Pod 信息:

crictl inspect <容器ID> | grep -E '"name"|"namespace"|"pod"|"labels"'

2. 如果容器运行时是 Docker

查看容器:

docker ps --no-trunc | grep <容器ID前几位>

查看容器标签:

docker inspect <容器ID> | grep -E "io.kubernetes.pod.name|io.kubernetes.pod.namespace|io.kubernetes.container.name"

3. 直接查看 102 节点上的 Pod

kubectl get pod -n ape -o wide | grep 192.166.11.102

也可以先查节点名称:

kubectl get node -o wide | grep 192.166.11.102

然后按节点过滤:

kubectl get pod -n ape -o wide --field-selector spec.nodeName=<节点名称>

十、第七步:排查容器日志是否过大

1. 查看 ape 命名空间 Pod 日志目录大小

du -sh /var/log/pods/ape_* 2>/dev/null | sort -hr | head -30

2. 查看实际日志文件大小

find /var/log/pods -type f -name "*.log" -exec du -h {} \; | sort -hr | head -30

3. 查看容器日志软链接

ls -lh /var/log/containers | grep ape | head -50

4. 查看日志增长情况

watch -n 5 'du -sh /var/log/pods/ape_* 2>/dev/null | sort -hr | head -20'

如果某个 Pod 日志持续增长,说明可能存在日志刷屏。

5. 查看具体 Pod 日志

kubectl logs -n ape --tail=200 <pod-name>

实时观察:

kubectl logs -f -n ape <pod-name>

如果有多个容器:

kubectl logs -f -n ape <pod-name> -c <container-name>

十一、第八步:重点排查 lake / feature / web 服务

根据 Pod 分布,102 节点可能存在以下服务:

ape-feature
ape-frontend
ape-lake
ape-web

重点关注:

1. ape-lake

可能原因:

血缘解析任务
定时任务脚本
批量查询
批量解析
临时文件生成
大批量日志输出

排查方向:

kubectl logs -n ape --tail=300 <ape-lake-pod>

关注日志中是否存在:

lineage
血缘
定时任务
batch
解析
全量
任务开始
任务结束
异常堆栈
循环报错
SQL 查询

2. ape-feature

可能原因:

特征计算
批量数据读取
指标加工
缓存刷新
外部数据调用

排查方向:

kubectl logs -n ape --tail=300 <ape-feature-pod>

3. ape-web / ape-frontend

可能原因:

Nginx access.log 访问日志过大
前端服务日志刷屏
大量静态资源访问
健康检查频繁访问

排查方向:

kubectl logs -n ape --tail=300 <ape-web-pod>
kubectl logs -n ape --tail=300 <ape-frontend-pod>

十二、第九步:排查业务任务时间点

如果告警是固定时间出现,需要对齐业务任务。

重点核查:

1\. lake 服务是否有定时任务;
2. 血缘解析是否在告警时间点执行;
3. 是否有全量数据解析;
4. 是否有定时 SQL 查询;
5. 是否有报表统计、数据同步、缓存刷新任务;
6. 是否有上线、重启、发布动作;
7. 是否有备份、日志切割、压缩动作。

可通过以下方式辅助确认:

kubectl get cronjob -A
kubectl get job -A

查看 ape 命名空间:

kubectl get cronjob -n ape
kubectl get job -n ape

查看最近事件:

kubectl get events -n ape --sort-by=.lastTimestamp | tail -50

十三、第十步:排查大文件和目录增长

1. 查看根目录大目录

du -xh --max-depth=1 / 2>/dev/null | sort -hr | head -30

2. 查看 /var 大目录

du -xh --max-depth=1 /var 2>/dev/null | sort -hr | head -30

3. 查看 /var/log

du -xh --max-depth=1 /var/log 2>/dev/null | sort -hr | head -30

4. 查看 containerd 目录

du -xh --max-depth=1 /var/lib/containerd 2>/dev/null | sort -hr | head -30

5. 查看 docker 目录

如果使用 Docker:

du -xh --max-depth=1 /var/lib/docker 2>/dev/null | sort -hr | head -30

6. 查找大文件

find / -xdev -type f -size +500M -exec ls -lh {} \; 2>/dev/null | sort -k5 -hr | head -50

如果 dm-2 挂载在 /data1,则改为:

find /data1 -type f -size +500M -exec ls -lh {} \; 2>/dev/null | sort -k5 -hr | head -50

十四、第十一步:Java 服务线程级辅助排查

如果高 IO 进程是 Java 服务,可继续排查线程。

1. 查看 Java 进程

ps -ef | grep java | grep -v grep

2. 查看线程级 IO

pidstat -d -t -p <java_pid> 1 10

3. 查看线程 CPU

top -Hp <java_pid>

4. TID 转十六进制

printf "%x\n" <TID>

5. 导出线程栈

jstack <java_pid> > /tmp/jstack.log

6. 根据十六进制线程 ID 查询

grep -i "<十六进制TID>" /tmp/jstack.log -A 30

说明:

线程级排查主要用于判断是否存在异常循环、日志刷屏、批处理任务卡住等问题。

十五、第十二步:基础设施侧排查

即使业务侧存在可能,也不能完全排除基础设施侧问题。

需要关注:

云盘类型
云盘 IOPS 上限
云盘吞吐上限
是否为突发型云盘
是否存在突发积分耗尽
宿主机是否有 IO 抖动
是否存在快照、备份、迁移任务
是否存在磁盘队列异常

建议客户侧配合确认:

1\. 102 节点云盘类型和规格;
2. dm-2 所在云盘的 IOPS/吞吐监控;
3. 告警时间点云平台侧是否有磁盘性能告警;
4. 是否存在云盘快照、备份、迁移、扩容等操作;
5. 是否其他节点同一时间也有类似 IO 告警。

十六、告警发生时现场抓取命令

如果后续再次触发告警,建议第一时间执行以下命令保存现场。

1. 基础时间信息

date
hostname
uptime

2. 磁盘 IO

iostat -x -p ALL 1 10

3. 进程 IO

pidstat -d -p ALL 1 10

4. 高 IO 进程

iotop -oPa -n 5

如果没有 iotop

pidstat -d -p ALL 1 10 | sort -k6 -nr | head -30

5. 节点 Pod 分布

kubectl get pod -n ape -o wide | grep 192.166.11.102

6. 日志大小

du -sh /var/log/pods/ape_* 2>/dev/null | sort -hr | head -30
find /var/log/pods -type f -name "*.log" -exec du -h {} \; | sort -hr | head -30

7. 大文件

find / -xdev -type f -size +500M -exec ls -lh {} \; 2>/dev/null | sort -k5 -hr | head -50

十七、一键排查脚本

可以临时创建脚本:

cat > /tmp/check_node_io.sh <<'EOF'
#!/bin/bash

echo "=============================="
echo "1. 基础信息"
echo "=============================="
date
hostname
uptime

echo
echo "=============================="
echo "2. 块设备信息"
echo "=============================="
lsblk -o NAME,MAJ:MIN,SIZE,TYPE,MOUNTPOINT,FSTYPE

echo
echo "=============================="
echo "3. 文件系统信息"
echo "=============================="
df -hT

echo
echo "=============================="
echo "4. dm-2 信息"
echo "=============================="
readlink -f /dev/dm-2 2>/dev/null
dmsetup ls 2>/dev/null
dmsetup info /dev/dm-2 2>/dev/null

echo
echo "=============================="
echo "5. 磁盘 IO"
echo "=============================="
iostat -x -p ALL 1 5

echo
echo "=============================="
echo "6. 进程 IO"
echo "=============================="
pidstat -d -p ALL 1 5

echo
echo "=============================="
echo "7. ape Pod 日志目录大小"
echo "=============================="
du -sh /var/log/pods/ape_* 2>/dev/null | sort -hr | head -30

echo
echo "=============================="
echo "8. 容器日志文件大小"
echo "=============================="
find /var/log/pods -type f -name "*.log" -exec du -h {} \; 2>/dev/null | sort -hr | head -30

echo
echo "=============================="
echo "9. 大文件检查"
echo "=============================="
find / -xdev -type f -size +500M -exec ls -lh {} \; 2>/dev/null | sort -k5 -hr | head -50

EOF

chmod +x /tmp/check_node_io.sh

执行:

/tmp/check_node_io.sh | tee /tmp/check_node_io_$(date +%F_%H%M%S).log

十八、问题归因参考

场景一:dm-2 %util 高,wkB/s 高

可能原因:

大量日志写入
批量任务写文件
数据库刷盘
容器日志持续写入

重点排查:

/var/log/pods
/var/log/containers
应用日志目录
业务数据目录

场景二:dm-2 %util 高,rkB/s 高

可能原因:

批量查询
全量扫描
血缘解析读取大量文件
缓存预热
报表任务

重点排查:

lake 服务
feature 服务
数据库查询
定时任务

场景三:await 高,但读写量不大

可能原因:

云盘性能抖动
磁盘队列异常
宿主机 IO 抖动
底层存储性能不足

重点排查:

云盘监控
IOPS/吞吐上限
宿主机侧指标
是否其他节点同时告警

场景四:只有某个时间点高

可能原因:

定时任务
日志切割
备份
批处理
Pod 重启
服务发布

重点排查:

告警时间点
cronjob/job
应用定时任务日志
K8S events
发布记录

场景五:日志文件快速增长

可能原因:

应用异常循环
日志级别过低
大量 SQL 打印
请求异常刷屏
健康检查访问日志过多

处理建议:

调整日志级别
限制 access log
增加日志滚动策略
修复异常循环
清理历史大日志

十九、客户沟通口径

1. 当前阶段说明

目前告警对象为 dm-2 磁盘设备,该设备属于 Linux 设备映射层。当前需要先确认 dm-2 实际对应的底层磁盘、挂载目录以及承载的数据内容。在未确认设备映射关系前,暂不能直接判断是具体某个服务、日志写入还是基础设施侧问题。

2. 当前检查结果说明

目前在 192.166.11.102 节点执行 iostat 检查,当前 CPU iowait 和磁盘 util 均较低,暂未观察到持续性磁盘 IO 压力。本次告警可能是某个时间点的瞬时 IO 峰值,也可能与业务任务、日志写入或底层云盘抖动有关,需要结合告警时间点继续分析。

3. 后续排查方向

后续会从设备映射、告警持续时间、进程 IO、Pod 分布、容器日志增长、业务定时任务以及云盘性能等多个维度继续排查。重点关注 lake 服务血缘解析、定时任务脚本、批量查询以及血缘日志是否存在集中写入情况。

二十、结论模板

1. 未复现时

当前节点未复现持续性 IO 异常,iostat 显示 CPU iowait 和磁盘 util 均处于较低水平。建议继续观察告警趋势,并在下次告警发生时同步抓取 iostat、pidstat、iotop、Pod 日志大小和 dm-2 设备映射信息,以便定位具体来源。

2. 定位到日志写入时

经排查,dm-2 对应目录下容器日志存在快速增长,初步判断本次 IO 升高与 Pod 日志持续写入有关。建议进一步确认应用是否存在异常循环、日志级别过低或大量 SQL/异常堆栈输出,并进行日志级别调整、日志滚动配置和异常修复。

3. 定位到 lake 定时任务时

经排查,告警时间点与 lake 服务血缘解析/定时任务执行时间吻合,且该时间段存在批量读取或解析操作,初步判断本次 IO 升高与批处理任务集中执行有关。建议优化任务执行频率、分批处理、降低单次任务数据量,并观察后续 IO 指标。

4. 怀疑基础设施侧时

当前业务侧未发现明显持续写入或异常日志增长,但 dm-2 在告警时间点存在较高 await/%util,建议客户侧进一步结合云盘 IOPS、吞吐、队列长度、宿主机状态及云平台监控排查是否存在底层存储性能抖动。

二十一、持续跟踪建议

后续建议持续跟踪以下指标:

1\. dm-2 IO 操作耗时率趋势;
2. dm-2 await%util、aqu-sz;
3. 102 节点 CPU iowait;
4. /var/log/pods 下日志增长情况;
5. ape-lake、ape-feature、ape-web、ape-frontend 日志输出情况;
6. lake 血缘解析任务执行时间;
7. 定时任务、批处理、上线发布记录;
8. 云盘 IOPS、吞吐、队列长度。

建议形成固定观察记录:

时间 dm-2 IO 耗时率 是否持续 102 节点 iowait 高 IO 进程 涉及 Pod 是否有任务 是否有日志增长 初步判断
2026-04-27 13:27 91.44% 待确认 待确认 待确认 待确认 待确认 待确认 待进一步排查

二十二、排查优先级

建议优先级如下:

P1:确认 dm-2 对应挂载点
P2:确认告警持续时间和时间规律
P3:告警发生时抓取 iostat / pidstat / iotop
P4:检查 /var/log/pods 日志增长
P5:对齐 lake 血缘解析和定时任务执行时间
P6:反查高 IO PID 对应 Pod
P7:排除云盘和基础设施侧问题

二十三、总结

本次问题属于 K8S 节点层磁盘 IO 耗时率告警,当前告警设备为 dm-2,需要先完成设备映射确认,再结合告警时间点、进程级 IO、Pod 分布、日志增长和业务任务执行情况进行综合判断。

当前阶段不建议直接归因为某个服务或磁盘硬件问题。较合理的排查路径是:

dm-2 设备映射确认
    ↓
告警时间段确认
    ↓
iostat 判断是否持续 IO 异常
    ↓
pidstat / iotop 定位高 IO 进程
    ↓
cgroup / crictl / docker 反查 Pod
    ↓
检查日志、任务、临时文件、业务数据目录
    ↓
结合云盘性能监控判断是否存在基础设施侧问题

重点关注方向:

ape-lake 血缘解析任务
定时任务脚本
批量查询或批量解析
血缘日志大量写入
容器日志快速增长
云盘性能瞬时抖动
本作品采用《CC 协议》,转载必须注明作者和本文链接
每天一点小知识,到那都是大佬,哈哈
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
php @ 远程
文章
101
粉丝
16
喜欢
77
收藏
88
排名:522
访问:1.6 万
私信
所有博文
社区赞助商