Linux 下使用 RAID10 软陈列的一些事儿

我在前面一则日记中在 VirtualBox Deepin Linux 虚拟机里演示一下用 mdadm 创建 RAID10 软陈列。今天补充一些我觉得在使用 RAID10 软阵列时值得注意的事项。包括:磁盘分区、阵列成员大小、添加阵列成员命令 --add 和 --re-add 区别及添加阵列成员顺序。测试的环境是 VirtualBox 里面的 Deepin 20.5 Linux,内核版本 5.10.101,mdadm – V4.1 – 2018-10-01。视频演示地址: https://www.bilibili.com/video/BV1rB4y127KT?share_source=copy_web

一、磁盘分区
尽管一块磁盘可以不分区直接作为阵列成员,但强烈推荐使用分区并使用GPT分区类型。并且,在分区时,在磁盘末尾留下约100MiB的未分配空间。这是因为在 RAID10 中,当需要替换损坏的磁盘时,新换上的阵列成员容量必须大于或等于原来的,不分区且未留未分配空间的话,如果新换上的磁盘恰好比原来的磁盘小一点点,替换就会失败。
使用 GPT 分区是因为大多数阵列用户使用的磁盘会大于 2TiB,而老式的 MBR 分区表不支持大于 2TiB 的分区。
这里使用4块8GiB大小的虚拟磁盘。都使用 fdisk 分区,分区表选择 GPT,分区大小选择 8092M(MiB),分区类型选 ID 为 29 的 Linux RAID,末尾留 100MiB 不分配。
示例如下:

littlebat@learndiary:~$ sudo fdisk /dev/sdb

Welcome to fdisk (util-linux 2.33.1).                                                                         
Changes will remain in memory only, until you decide to write them.                                           
Be careful before using the write command.

Command (m for help): g
Created a new GPT disklabel (GUID: DD83BD1C-0C54-D749-9449-CE6720FD93F5).
The old dos signature will be removed by a write command.

Command (m for help): n
Partition number (1-128, default 1): 
First sector (2048-16777182, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-16777182, default 16777182): +8092M

Created a new partition 1 of type 'Linux filesystem' and of size 7.9 GiB.

Command (m for help): t
Selected partition 1
Partition type (type L to list all types): 29
Changed type of partition 'Linux filesystem' to 'Linux RAID'.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

littlebat@learndiary:~$

然后,我们如上篇日记一样用 mdadm 创建一个 RAID10 软阵列。主要命令如下:

sudo mdadm --create --verbose --level=10 --raid-devices=4 /dev/md/r10a1 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
sudo update-initramfs -u
sudo mkfs.ext4 -L R10P /dev/md/r10a1
sudo mkdir /mnt/tmp -v
sudo mount /dev/md/r10a1 /mnt/tmp -v
sudo cp /usr/src /mnt/tmp/ -a # 复制一些测试数据到阵列上面的文件系统中
ls /mnt/tmp
sudo du -sh /mnt/tmp

二、阵列大小及阵列成员使用大小
首先查看阵列信息如下:

littlebat@learndiary:~$ sudo mdadm --detail /dev/md/r10a1
/dev/md/r10a1:
           Version : 1.2
     Creation Time : Sun Apr 17 18:21:11 2022
        Raid Level : raid10
        Array Size : 16562176 (15.79 GiB 16.96 GB)
     Used Dev Size : 8281088 (7.90 GiB 8.48 GB)
      Raid Devices : 4
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Sun Apr 17 18:27:39 2022
             State : clean 
    Active Devices : 4
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 0

            Layout : near=2
        Chunk Size : 512K

Consistency Policy : resync

              Name : learndiary:r10a1  (local to host learndiary)
              UUID : 48fb1616:db1a15f8:9ca99ea4:1b32a56d
            Events : 17

    Number   Major   Minor   RaidDevice State
       0       8       17        0      active sync set-A   /dev/sdb1
       1       8       33        1      active sync set-B   /dev/sdc1
       2       8       49        2      active sync set-A   /dev/sdd1
       3       8       65        3      active sync set-B   /dev/sde1

然后,用 fdisk 查看相关设备大小:

littlebat@learndiary:~$ sudo fdisk -l | grep dev | grep -v sda
 Disk /dev/sdb: 8 GiB, 8589934592 bytes, 16777216 sectors
 /dev/sdb1   2048 16574463 16572416  7.9G Linux RAID
 Disk /dev/sdc: 8 GiB, 8589934592 bytes, 16777216 sectors
 /dev/sdc1   2048 16574463 16572416  7.9G Linux RAID
 Disk /dev/sdd: 8 GiB, 8589934592 bytes, 16777216 sectors
 /dev/sdd1   2048 16574463 16572416  7.9G Linux RAID
 Disk /dev/sde: 8 GiB, 8589934592 bytes, 16777216 sectors
 /dev/sde1   2048 16574463 16572416  7.9G Linux RAID
 Disk /dev/md127: 15.8 GiB, 16959668224 bytes, 33124352 sectors

其中,阵列信息里有2个参数是这里要讨论的,如下:
Array Size : 16562176 (15.79 GiB 16.96 GB)
Used Dev Size : 8281088 (7.90 GiB 8.48 GB)

“Array Size”就是阵列大小,这里是16562176*1024=16,959,668,224 bytes,跟 fdisk 报告的 /dev/md127 的一致。 “Used Dev Size”就是阵列成员使用大小,这个大小在 RAID10 中指成员容量最小的那个容量大小,在这里,我们每个阵列成员都是一样的大小,即是 8281088*1024=8,479,834,112 bytes。fdisk 报告的阵列成员分区大小是 16572416*512=8,485,076,992 bytes。前者比后者要小 5MiB,我猜测应该是阵列成员组成阵列的过程中额外的消耗。

下面,我们通过一个测试来再次验证一下 “Used Dev Size” 的含义。我们把阵列删除,重建一个 RAID10 阵列,前3个阵列成员分区大小不变,第4个成员使用前面在磁盘末尾留的那个未分配完空间中的 90MiB 的分区。看看建成的阵列的“Array Size”和“Used Dev Size”如何。

littlebat@learndiary:~$ sudo umount /mnt/tmp -v
umount: /mnt/tmp unmounted
littlebat@learndiary:~$ sudo mdadm --stop /dev/md/r10a1
mdadm: stopped /dev/md/r10a1
littlebat@learndiary:~$ for d in sdb1 sdc1 sdd1 sde1; do sudo mdadm --zero-superblock /dev/${d}; done

然后,执行 fdisk /dev/sde,增加第2个分区,类型仍为 ID 是 29 的“Linux RAID”,大小是90M(MiB)。
然后,以 /dev/sdb1、/dev/sdc1、/dev/sdd1、/dev/sde2 为成员组建 RAID10 软阵列。

littlebat@learndiary:~$ sudo mdadm --create --verbose --level=10 --raid-devices=4 /dev/md/r10a1 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde2
mdadm: layout defaults to n2
mdadm: layout defaults to n2
mdadm: chunk size defaults to 512K
mdadm: size set to 87040K
mdadm: largest drive (/dev/sdb1) exceeds size (87040K) by more than 1%
Continue creating array? y
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md/r10a1 started.

sudo vim /etc/mdadm/mdadm.conf # 删除前面旧的阵列配置行
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
sudo update-initramfs -u
sudo mkfs.ext4 -L R10P /dev/md/r10a1
sudo mount /dev/md/r10a1 /mnt/tmp -v
sudo cp /var/log /mnt/tmp/ -a # 复制一些测试数据到阵列上面的文件系统中
ls /mnt/tmp
sudo du -sh /mnt/tmp

查看阵列信息如下:

littlebat@learndiary:~$ sudo mdadm --detail /dev/md/r10a1
/dev/md/r10a1:
           Version : 1.2
     Creation Time : Sun Apr 17 21:38:04 2022
        Raid Level : raid10
        Array Size : 174080 (170.00 MiB 178.26 MB)
     Used Dev Size : 87040 (85.00 MiB 89.13 MB)
      Raid Devices : 4
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Sun Apr 17 21:38:04 2022
             State : clean 
    Active Devices : 4
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 0

            Layout : near=2
        Chunk Size : 512K

Consistency Policy : resync

              Name : learndiary:r10a1  (local to host learndiary)
              UUID : 0b159393:135ea86f:07d5a6e4:0e6bf696
            Events : 17

    Number   Major   Minor   RaidDevice State
       0       8       17        0      active sync set-A   /dev/sdb1
       1       8       33        1      active sync set-B   /dev/sdc1
       2       8       49        2      active sync set-A   /dev/sdd1
       3       8       66        3      active sync set-B   /dev/sde2

可以看到,“Used Dev Size”(阵列成员使用大小)是比最小的阵列成员分区 /dev/sde2 的 90MiB 小 5MiB 的 85MiB,而“Array Size”(阵列大小)是“Used Dev Size”的2倍,即 170MiB。而阵列成员分区大小为 8092MiB 的 /dev/sdb1、/dev/sdc1、/dev/sdd1 这 3 个成员每一个都浪费了 8092-90=8002MiB 的空间。

三、添加阵列成员命令 --add 和 --re-add 区别及添加阵列成员顺序
从 man mdadm 中可以看到,--add 和 --re-add 都可以在阵列成员失效或者失效和移除后添加成员,这里演示一下它们的一些区别。
--add 用于添加阵列成员,如果阵列成员是之前失效或移除的成员,会使用下面的 --re-add 方式重新加入。
--re-add 用于重新加入之前移除的成员,有可能原封不动的添加进去,甚至可能不需要恢复的过程。
但是据我在虚拟机上的多次测试,只在 --fail 后即执行 --re-add 才能成功。如果 --fail 加 --remove 后执行 --re-add 会失败,只能使用 --add 命令加入移除的成员。注意,上述结论是我在虚拟机中进行有限次测试的结果,官方 man mdadm 并没有这样说。所以不排除在使用中出现跟这个结论不同的结果。测试如下:

1、
littlebat@learndiary:~$ sudo mdadm /dev/md/r10a1 --fail /dev/sdc1 /dev/sdd1
mdadm: set /dev/sdc1 faulty in /dev/md/r10a1
mdadm: set /dev/sdd1 faulty in /dev/md/r10a1

2、
littlebat@learndiary:~$ sudo mdadm /dev/md/r10a1 --add /dev/sdc1 /dev/sdd1
mdadm: Cannot open /dev/sdc1: Device or resource busy
只标记 --fail 用 --add 命令是不能添加成功的。

3、
littlebat@learndiary:~$ sudo mdadm /dev/md/r10a1 --re-add /dev/sdc1 /dev/sdd1
mdadm: re-add /dev/sdc1 to md127 succeed
mdadm: re-add /dev/sdd1 to md127 succeed
用 --re-add 添加成功。
sudo mdadm --detail /dev/md/r10a1 查看可见 /dev/sdc1、/dev/sdd1 按原来的位置重新加进去了。

4、
littlebat@learndiary:~$ sudo mdadm /dev/md/r10a1 --fail /dev/sdc1 /dev/sdd1 && sudo mdadm /dev/md/r10a1 --remove /dev/sdc1 /dev/sdd1
mdadm: set /dev/sdc1 faulty in /dev/md/r10a1
mdadm: set /dev/sdd1 faulty in /dev/md/r10a1
mdadm: hot removed /dev/sdc1 from /dev/md/r10a1
mdadm: hot removed /dev/sdd1 from /dev/md/r10a1

5、
littlebat@learndiary:~$ sudo mdadm /dev/md/r10a1 --re-add /dev/sdc1 /dev/sdd1
mdadm: --re-add for /dev/sdc1 to /dev/md/r10a1 is not possible
用 --re-add 添加失败。

6、
littlebat@learndiary:~$ sudo mdadm /dev/md/r10a1 --add /dev/sdc1 /dev/sdd1
mdadm: added /dev/sdc1
mdadm: added /dev/sdd1
用 --add 添加成功。但是用 sudo mdadm --detail /dev/md/r10a1 查看可见 /dev/sdc1、/dev/sdd1 的位置互换了。

7、
littlebat@learndiary:~$ sudo mdadm /dev/md/r10a1 --fail /dev/sdc1 /dev/sdd1 && sudo mdadm /dev/md/r10a1 --remove /dev/sdc1 /dev/sdd1 && sudo mdadm /dev/md/r10a1 --add /dev/sdc1 && sudo mdadm /dev/md/r10a1 --add /dev/sdd1
然后用 sudo mdadm --detail /dev/md/r10a1 查看可见 /dev/sdc1 在/dev/sdd1 的上面了。

littlebat@learndiary:~$ sudo mdadm /dev/md/r10a1 --fail /dev/sdc1 /dev/sdd1 && sudo mdadm /dev/md/r10a1 --remove /dev/sdc1 /dev/sdd1 && sudo mdadm /dev/md/r10a1 --add /dev/sdd1 && sudo mdadm /dev/md/r10a1 --add /dev/sdc1
用 sudo mdadm --detail /dev/md/r10a1 查看可见 /dev/sdd1 又在 /dev/sdc1 的上面了。
可见,如果依次单独添加阵列成员 /dev/sdc1 和 /dev/sdd1 就会按我们指定的顺序加入阵列中。

四、参考资料:
1、RAID (简体中文) https://wiki.archlinux.org/title/RAID_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)#%E5%AF%B9%E7%A3%81%E7%9B%98%E8%BF%9B%E8%A1%8C%E5%88%86%E5%8C%BA
2、raid10 in mdadm reports incorrect "Used Dev Size" https://serverfault.com/questions/432963/raid10-in-mdadm-reports-incorrect-used-dev-size
3、man mdadm

发表评论

电子邮件地址不会被公开。 必填项已用*标注