Ubuntu Server 22.04 HWE内核下NVME0磁盘I/O超时引发系统冻结的问题排查求助
问题背景
我在Ubuntu Server 22.04上使用HWE内核6.2.0-35-generic搭建了一个2TB的RAID1 mdadm阵列,使用的磁盘是nvme0n1和nvme1n1。
服务器偶尔会出现无响应的情况——当时有多个实时流和聊天程序在运行,所以这个问题非常明显。通常几分钟后会恢复,但这个现象有时在高负载下出现,有时负载不高也会触发。
相关内核日志
冻结前后的内核日志如下(注意时间戳,前几行是冻结前,后面是恢复后):
Oct 28 20:33:50 tombstone kernel: [731601.828091] nvme nvme0: I/O 1 (I/O Cmd) QID 3 timeout, aborting Oct 28 20:33:50 tombstone kernel: [731601.828099] nvme nvme0: I/O 2 (I/O Cmd) QID 3 timeout, aborting Oct 28 20:33:50 tombstone kernel: [731601.828106] nvme nvme0: I/O 3 (I/O Cmd) QID 3 timeout, aborting Oct 28 20:33:50 tombstone kernel: [731601.828113] nvme nvme0: I/O 4 (I/O Cmd) QID 3 timeout, aborting Oct 28 20:34:21 tombstone kernel: [731632.551513] nvme nvme0: I/O 0 QID 3 timeout, reset controller Oct 28 20:34:51 tombstone kernel: [731663.266956] nvme nvme0: I/O 24 QID 0 timeout, reset controller Oct 28 20:35:22 tombstone kernel: [731693.971274] nvme nvme0: Abort status: 0x371 Oct 28 20:35:22 tombstone kernel: [731693.971281] nvme nvme0: Abort status: 0x371 Oct 28 20:35:22 tombstone kernel: [731693.971284] nvme nvme0: Abort status: 0x371 Oct 28 20:35:22 tombstone kernel: [731693.971287] nvme nvme0: Abort status: 0x371 Oct 28 20:35:22 tombstone kernel: [731693.971290] nvme nvme0: Abort status: 0x371 Oct 28 20:35:22 tombstone kernel: [731694.019253] nvme nvme0: 15/0/0 default/read/poll queues
值得注意的是,总是nvme0出现问题,nvme1从未出现过类似日志。
已尝试的调整
- 调整过IO调度器,有一定改善但没能彻底解决问题
- 修改了脏内存参数:目前后台脏页设置为300MB,硬限制约60GB——因为要避免写入数据时出现硬停顿,之前设置更低的限制时问题依然存在
当前疑问与考虑
我查到的资料显示这可能是磁盘故障,但也有建议将IO超时设置为极高的值。我愿意尝试,但担心如果超时设得太高,服务器会永远挂起而不是默认的30秒左右,这反而更糟。有没有人能给点建议?
由于停机影响非常大,我的想法是如果确实是磁盘故障,就把nvme0从mdadm阵列中移除,让阵列降级运行,直到我们能安排停机维护。
具体问题:
- 这个问题是什么原因导致的?一定是硬件故障吗?还是可能有配置错误?
- 为什么mdadm不在后台处理这个问题,反而导致系统冻结?
- 如果确实是磁盘故障,将其标记为故障并从RAID1阵列中移除,除了mdadm会发出警告信息和失去冗余之外,还有什么其他弊端吗?
问题解答与建议
1. 问题根源分析
首先,大概率是nvme0硬件层面的问题——因为只有这一块盘反复出现I/O超时、控制器重置的日志,另一块盘完全正常。不过也不能完全排除几种非硬件的可能性:
- NVMe驱动兼容性问题:6.2内核虽然是HWE版本,但某些特定型号的NVMe盘可能存在小的驱动bug,导致高负载或特定IO模式下触发超时。你可以尝试升级到更新的HWE内核(比如6.5系列,Ubuntu 22.04的HWE内核后续版本)看看是否能解决。
- 磁盘固件版本过旧:很多NVMe盘的早期固件存在稳定性问题,建议你查看
nvme0的固件版本,去厂商官网看看有没有更新包,更新固件后再观察。 - PCIe插槽/链路问题:如果
nvme0是插在某个PCIe插槽上,可能插槽接触不良或者链路稳定性差,导致IO传输中断。可以尝试把两块NVMe盘交换插槽,看看问题是否转移到原来的nvme1上——如果转移了,那就是插槽或链路的问题,而不是磁盘本身。
2. 为什么mdadm会导致系统冻结?
RAID1的工作机制是写操作需要同步写入两块盘,读操作可以从任意一块读取。当nvme0出现IO超时后,内核会尝试中止IO、重置控制器,这个过程中,所有依赖nvme0的IO请求都会被阻塞——包括mdadm的同步写请求。
默认情况下,Linux内核的块设备IO是阻塞式的,当某个磁盘的IO卡住时,上层的应用(包括mdadm)会一直等待IO完成,直到超时或重置完成。如果这个过程持续时间较长,就会导致整个系统的IO队列堵塞,进而引发系统无响应。
mdadm本身没有能力“跳过”故障盘的IO等待,因为它依赖内核的块设备层处理IO,而内核在处理NVMe超时重置时会占用相关资源,导致整个IO路径被阻塞。
3. 降级运行RAID1的弊端
把故障盘从RAID1中移除后,除了你提到的失去冗余、mdadm告警之外,还有几个需要注意的点:
- 单盘压力增大:原来由两块盘分担的读写负载会全部落到
nvme1上,如果你的服务器有高负载的IO需求,可能会导致nvme1的负载过高,甚至触发新的问题。 - 数据一致性风险:虽然降级运行时数据依然可读可写,但如果剩下的
nvme1也出现问题,就会直接导致数据丢失——所以一定要做好备份,并且尽快安排时间更换故障盘。 - mdadm的自动同步问题:之后添加新盘重建RAID时,会进行全量同步,这个过程会占用大量IO资源,可能影响服务器的正常业务,所以需要在低峰期操作。
临时缓解方案建议
- 不建议盲目调高IO超时:正如你担心的,调高超时时间只会让系统冻结的时间更长,而不会解决根本问题,反而可能错过故障盘的早期预警。
- 优先排查硬件/固件:先交换NVMe插槽验证是否是插槽问题,然后更新磁盘固件,再升级内核试试。
- 临时隔离故障盘:如果暂时无法停机更换,可以先把
nvme0标记为故障并移除:
执行后可以用# 标记nvme0n1为故障 mdadm /dev/mdX --fail /dev/nvme0n1 # 从阵列中移除故障盘 mdadm /dev/mdX --remove /dev/nvme0n1mdadm --detail /dev/mdX确认阵列状态,之后记得监控nvme1的状态,确保它稳定运行。
备注:内容来源于stack exchange,提问作者Garrett B

