降低CentOS7磁盘I/O timeout避免虚拟机掉盘:实战手记

虚拟机跑着跑着就“掉盘”,日志里清一色“task blocked for more than 120 seconds”,这是CentOS7默认磁盘I/O timeout=120s在作怪。把数值压到30s以内,系统能更快识别卡盘并触发重试,而不是傻等两分钟直接踢盘。下面把踩过的坑、验证过的命令、一行行可复制的配置全放出来,照着敲,10分钟搞定。

为什么timeout太长反而掉盘
KVM/VMware/ESXi底层压力一大,虚拟盘偶尔响应慢半拍。CentOS7内核把每个I/O请求的死等时间定成120s,超时后上层文件系统直接标记磁盘“offline”,于是你看到的就是“盘没了”,重启才回来。把timeout砍到10~30s,内核更快报错,多路径或iSCSI层才有机会切链路、重发包,盘反而稳得多。
先查当前值,别盲改
cat /sys/block/sda/device/timeout #默认120
cat /sys/block/vda/device/timeout # virtio盘也常常是120
看到120就继续,已经改过的跳过。

临时生效:echo秒改
echo 10 > /sys/block/sda/device/timeout
echo 10 > /sys/block/vdb/device/timeout
一次只对单盘生效,重启就丢,适合先在测试机验证有没有副作用。
永久生效:udev规则一次写死
新建文件/etc/udev/rules.d/99-io-timeout.rules,内容如下:
# SATA/SAS盘
SUBSYSTEM=="block", SUBSYSTEMS=="scsi", ATTR{device/timeout}=="*", ATTR{device/timeout}="10"
# Virtio半虚拟盘
SUBSYSTEM=="block", KERNEL=="vd*", ATTR{device/timeout}="10"
保存后执行:
udevadm control --reload-rules && udevadm trigger
再cat那个sys文件,确认全部变成10,重启也稳。
多路径环境别只改单层
用了dm-multipath,还得把/dev/dm-*设备的queue_if_no_path关掉,否则单路径卡死一样会拖满120s。
/etc/multipath.conf里加:
defaults {
polling_interval 5
no_path_retry 5
queue_if_no_path no
}
改完systemctl reload multipathd,让配置立即生效。
性能没损失,别被谣言吓住
有人担心timeout改小会“误杀”慢盘。实测SATA 7200转盘正常读写响应在20ms内,SSD更低。10s的超时足够完成上千次重试,根本轮不到误判;相反,120s的冗长等待才让业务线程堆积,系统load飙升。
一条龙验证脚本
把下面脚本扔进去跑,自动对比改前改后:
#!/bin/bash
for d in /sys/block/*/device/timeout; do
printf "%-20s 超时: %s秒\n" "$(basename $(dirname $d))" "$(cat $d)"
done
全变10就及格,谁还是120就回去检查udev规则拼写。
常见翻车点提醒
- 只改sda不改vda,结果系统盘是virtio,白忙活。
- rules文件里写错ATTR大小写,udev直接忽略,不会报错。
- 云主机厂商自定义内核,sys路径多一层host*/target*/,用通配符*号最稳。
收工检查清单
✓ 所有盘timeout≤30s
✓ multipath queue_if_no_path关闭
✓ 重启后依旧生效
✓ 业务压测30分钟无“blocked task”新日志
做完这几步,虚拟机再遇到存储抖动,顶多卡几秒,再也不会整盘消失,半夜起床重启的日子就此翻篇。
