raid-check

在完成 mdadm构建RAID10 之后,运维过程中发现默认系统配置了每周一次 raid-check ,也就是在 Cron定时运行 配置了一个 /etc/cron.d/raid-check :

默认配置每周日凌晨1点进行 raid-check
# Run system wide raid-check once a week on Sunday at 1am by default
0 1 * * Sun root /usr/sbin/raid-check

在实际生产环境中,由于现代存储容量非常巨大(单块 NVMe存储 容量达到4T,组合 mdadm构建RAID10 达到数十T),这个 mdadm 的检查耗时会非常长:

  • 默认同步速度限制为 200MB/sec (可修改,但是我踩了一个 mdadm 同步速度 调整的坑 ),此时观察 top 输出:

raid-check 是观察 top 输出
%Cpu(s):  0.0 us,  0.9 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 13137145+total, 11335824+free,  4092892 used, 13920332 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used. 11808108+avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  7608 root      20   0       0      0      0 R  42.7  0.0   5230:41 md10_raid10
112353 root      25   5       0      0      0 D  14.9  0.0  30:11.22 md10_resync
 38355 root      20   0  409524  57780   8724 S   1.7  0.0 329:38.63 glusterfsd

可以看到 md10_resync 始终处于 D 状态

  • 检查 md10 可以看到状态正常,且正在 check :

使用 mdadm -D 可以检查RAID状态
mdadm -D /dev/md10

输出显示:

使用 mdadm -D 可以检查RAID状态,当先显示正在 check
/dev/md10:
        Version : 1.2
  Creation Time : Wed Aug 16 15:29:17 2023
     Raid Level : raid10
     Array Size : 22499205120 (21456.91 GiB 23039.19 GB)
  Used Dev Size : 3749867520 (3576.15 GiB 3839.86 GB)
   Raid Devices : 12
  Total Devices : 12
    Persistence : Superblock is persistent

  Intent Bitmap : Internal

    Update Time : Thu Nov  9 17:51:45 2023
          State : clean, checking
 Active Devices : 12
Working Devices : 12
 Failed Devices : 0
  Spare Devices : 0

         Layout : near=2
     Chunk Size : 512K

   Check Status : 56% complete

           Name : u94j03331.alipay.ea134:10  (local to host u94j03331.alipay.ea134)
           UUID : 6f256e54:6534cc6a:be2241a5:f2d61129
         Events : 44863

    Number   Major   Minor   RaidDevice State
       0     259        6        0      active sync set-A   /dev/nvme0n1p1
       1     259       17        1      active sync set-B   /dev/nvme1n1p1
       2     259       16        2      active sync set-A   /dev/nvme2n1p1
       3     259       11        3      active sync set-B   /dev/nvme3n1p1
       4     259       24        4      active sync set-A   /dev/nvme4n1p1
       5     259       18        5      active sync set-B   /dev/nvme5n1p1
       6     259       12        6      active sync set-A   /dev/nvme6n1p1
       7     259       22        7      active sync set-B   /dev/nvme7n1p1
       8     259       23        8      active sync set-A   /dev/nvme8n1p1
       9     259       10        9      active sync set-B   /dev/nvme9n1p1
      10     259       15       10      active sync set-A   /dev/nvme10n1p1
      11     259        8       11      active sync set-B   /dev/nvme11n1p1

排查

在生产环境中,当每周末1点启动 raid-check 之后,业务繁忙期间会出现较高的延迟(大约是正常状态的2倍,也就是 20ms => 40ms)

检查 md 设备 md10sync_speed_max 限速
cat /sys/block/md10/md/sync_speed_max

默认值是 200000 也就是 200MB/s :

md 设备默认 sync_speed_max 限速是 200MB/s
200000 (system)
  • 观察服务器 top 输出,可以看到 md10_resync 持续 D 状态,但是 iowait 始终是 0

默认 mdadm 同步速度 服务器的 md10_resync 始终 D 状态 非常异常
%Cpu(s):  0.0 us,  0.9 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 13137145+total, 11335824+free,  4092892 used, 13920332 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used. 11808108+avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  7608 root      20   0       0      0      0 R  42.7  0.0   5230:41 md10_raid10
112353 root      25   5       0      0      0 D  14.9  0.0  30:11.22 md10_resync
 38355 root      20   0  409524  57780   8724 S   1.7  0.0 329:38.63 glusterfsd
  • 检查 md10_resync 进程堆栈:

通过 /proc 获取 md10_resync 的进程堆栈
#cat /proc/47438/stack
[<0>] msleep+0x2a/0x40
[<0>] md_do_sync+0xd39/0x1000
[<0>] md_thread+0x11f/0x160
[<0>] kthread+0xf5/0x130
[<0>] ret_from_fork+0x1f/0x30
[<0>] 0xffffffffffffffff
dump素有blocked (D)状态的任务
echo w >/proc/sysrq-trigger
  • 不幸的是,陷入 D 状态的 md10_resync 无法杀死,即使使用了 kill -9 47438 也不行

  • 我尝试将同步速度降低到 0 ,结果发现最低实际上是 2MB/s :

限制同步速度到0,实际结果是 2MB/s
#sysctl -w dev.raid.speed_limit_max=0
dev.raid.speed_limit_max = 0

#cat /proc/mdstat
Personalities : [raid10]
md10 : active raid10 nvme11n1p1[11] nvme10n1p1[10] nvme9n1p1[9] nvme8n1p1[8] nvme7n1p1[7] nvme6n1p1[6] nvme5n1p1[5] nvme4n1p1[4] nvme3n1p1[3] nvme2n1p1[2] nvme1n1p1[1] nvme0n1p1[0]
      22499205120 blocks super 1.2 512K chunks 2 near-copies [12/12] [UUUUUUUUUUUU]
      [>....................]  check =  1.8% (422515840/22499205120) finish=173123.3min speed=2124K/sec
      bitmap: 1/168 pages [4KB], 65536KB chunk

unused devices: <none>

而且,即使限速以后, md10_resync 依然是 D 状态,也无法停止

也就是说,一旦启动了 raid-check 就无法停止了? 不是的

控制 mdadm 的操作是通过 md_sync_action 来实现的,通过向 sync_action 发出 idle 指令,就能停止:

参考