如何将具有 4 个磁盘的 mdadm RAID10 迁移到 RAID5?

如何将具有 4 个磁盘的 mdadm RAID10 迁移到 RAID5?

我有一个基于 Debian Buster 下 Linux 的 mdadm 的软件 RAID10。最初我发现 RAID10 具有最佳性能。但我需要更多空间,并接受用一些写入性能换取 +50% 的空间。

# cat /proc/mdstat
Personalities : [raid10] [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4]
md1 : active raid10 sdd1[5] sda1[4] sdb1[1] sdc1[2]
      3899738112 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]
      bitmap: 3/30 pages [12KB], 65536KB chunk

unused devices: <none>

此存储通过 NFS 提供服务,理想情况下,RAID 可以在不停机的情况下进行转换。是的,我有备份,故障不会很严重,但如果可行,为什么不在不中断的情况下进行迁移呢?

答案1

我找到了一篇 2012 年的文章,其中描述了这个过程。这些命令被证明是完全正确的。当时作者遇到了一个问题,即mdadm实用程序(或可能是内核驱动程序)在第一个命令时立即挂起系统。从那时起,这个问题似乎已经得到解决。

https://www.tummy.com/blogs/2012/03/29/changing-a-raid-10-into-a-raid-5/

mdadm 中没有从 RAID10→RAID5 的直接路径。相反,您必须先将其降级为 RAID0:

# mdadm --grow /dev/md1 --level=0 --raid-devices=2
mdadm: /dev/md1: could not set level to raid0

此操作立即生效,导致 2 个设备发生故障并从阵列中移除。不幸的是,RAID 级别未设置为 RAID0。dmesg显示:

md/raid0:md1: All mirrors must be already degraded!
md: md1: raid0 would not accept array

我发现问题是将sysfs数组报告为不是尽管实际上已被降级并且mdadm显示cat /proc/mdstat正确:

# cat /sys/block/md1/md/degraded
0

我发现没有其他方法可以解决这个问题,只能停止 NFS 服务器,卸载文件系统,关闭 LUKS 设备,停止 RAID 阵列,重新组装 RAID 阵列并重新启动所有服务。之后,系统会正确报告其已降级,并且可以转换为 RAID0。

然后我可以使用 RAID5 将其扩展回 4 个设备:

# mdadm --grow /dev/md1 --level=5 --raid-devices=5 --add /dev/sdb1 /dev/sdd1

与以往不同的是,cat /proc/mdstat没有显示“重建”正在进行,而是显示“重塑”。这花了相当长的时间(大约 10 小时),而且系统响应速度比 RAID10 重建时慢得多。重建期间我没有管它。

由于重塑已完成,RAID5 很干净,速度也不错。我可能在测量时犯了错误,但现在的读取速度比我之前记录的要快,写入速度对我来说也是可以接受的。

# cat /proc/mdstat 
Personalities : [raid10] [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] 
md1 : active raid5 sdd1[5] sdb1[3] sda1[4] sdc1[7]
      5849607168 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]

unused devices: <none>

(免责声明:整个故事是在迁移完成时写下的。我试图仔细描述实际的命令和错误消息,但可能会有小错误。整个过程按描述的方式进行。)

答案2

尚未测试(不要相信以下步骤中的重要数据),但这里有一个适用于任何可用空间增加的场景的想法,并mdadm --grow说“RAID10 布局对于增长操作来说太复杂”:

  1. 停止 md
  2. 备份 md 每个分区的前几个 MiB(假设 RAID 超级块位于每个分区的开头附近)
  3. 清除超级区块
  4. --assume-clean使用分区创建 RAID5(或其他 RAID)
  5. 创建 md 各个分区的快照,例如https://gist.github.com/jowagner/b36024636140ddf453c12eaf6e590b5d
  6. 将步骤 2 中的分区备份还原为分区快照
  7. 从快照组装 RAID10
  8. dd将所有数据从 RAID10 复制到 RAID5。使用 2 个条带大小的最小公倍数可能对性能最有利,但任何块大小都可以。前几个读取不会被写入破坏,因为它们来自步骤 5 中写入的写时复制数据。其余读取不会被破坏,因为它们在每个分区上都处于安全的写入距离之外(因此这个想法仅限于可用空间增加的场景)。
  9. 停止 RAID10
  10. 丢弃快照

这假设快照仅将对快照的写入重定向到 COW 设备,并且对原始设备的写入不会触发将旧数据复制到 COW 设备中(否则该解决方案将不切实际,因为需要太多额外的空间)。

此外,如果旧 RAID 的超级块靠近每个分区的末尾,则还需要在步骤 3 之前备份这些数据。计算要查找的合适位置和数据量。我会使用几行 Python,但可能有一个命令行工具可以做到这一点。

相关内容