RAID (mdadm) - 如果驱动器大小不匹配会发生什么?

JaS*_*ers 17 raid mdadm

问题 1 - 在您回答“它只需要较小的磁盘”之前,请快速听我说完。我的 3TB WD Reds 大小为 3001 GB。假设我通过 mdadm 为跨越 100% 驱动器的 sdb1 和 sdc1 设置了一个镜像。但突然间,其中一个驱动器出现故障。替代品是 3TB,重 3000 GB。当我放入一个小于阵列上当前存在的驱动器时会发生什么?我知道使用 3000 与 3001 的新阵列,它会将阵列构建为 3000。但就像我说的,当前阵列 @ 3001 怎么样,我添加一个较小的驱动器?它是否在重建期间重新构建了 3000 GB 的大小?

问题 2 - 如果我无法将 3000 GB 添加到现有 3001 GB 的阵列中,而它只是缩小到 3000 ……我可以将 3001 缩小一点吗?

问题 3 - 或者,一个更好的主意。如果我将 3TB 驱动器缩小到 2999 GB 会怎样。这样,驱动器是否短 1 MB、1 个字节、10 KB 都没有关系,它总是会选择“较小的”驱动器 @ 2999 GB。

Ale*_*ios 32

我错误地遇到了这个答案,但如果有人好奇,这里有一个由实验支持的答案。

简短版本

附加问题:我可以使用md(4)大小不等的块设备创建RAID 阵列吗?是的,但是 RAID 阵列将具有小块设备的大小(加上一些用于其自身管理的开销)。如果设备大小相差不超过 1%,您会收到警告。

问题 1:我可以将一个md(4)小于当前最小成员的设备添加到现有RAID 阵列中吗?不,谢谢。mdadm将断然拒绝这样做以保护您的数据。

问题 2:您可以调整现有 md 数组的大小吗?是的(阅读mdadm手册!),但它可能不值得付出努力。您必须备份所有内容,然后调整 RAID 设备的内容大小,然后调整设备本身的大小——所有这些都很容易出现错误、计算错误和其他会花费您数据的事情(痛苦的经历) .

不值得冒险和努力。如果您有一个新的空白磁盘,这里是如何调整它的大小并始终保持所有数据的一到两个副本(假设您有 2 个磁盘 RAID1):

  1. md(4)在其上创建一个新阵列(缺少一个磁盘)。
  2. 重新创建数组内容的结构(加密、LVM、分区表、它们的任意组合,无论您的船如何漂浮)。
  3. 将数据从现有磁盘复制到新磁盘。
  4. 使用新磁盘重新启动。
  5. 擦除旧磁盘的分区表(或将md(4)超级块归零)。如有必要,创建所需的分区以匹配新磁盘上的方案。
  6. 将旧磁盘添加到新阵列。
  7. 等待阵列成员同步。喝杯咖啡。就此而言,飞往拉丁美洲并挑选自己的咖啡豆。:)(如果您住拉丁美洲,请改为飞往非洲)。

注意:是的,这与他的回答中描述的技术 0xC0000022L 相同。

问题3.驱动器短1G怎么办?:) 别担心。您的更换驱动器可能会更大。事实上,像它上面的策略付出得到更便宜的更大的驱动器,每当一个失败(或更便宜的升级)。您可以获得渐进式升级。

实验证明

实验装置

首先,让我们伪造一些块设备。我们将使用/tmp/sdx/tmp/sdy(每个 100M)和/tmp/sdz(99M)。

cd /tmp
dd if=/dev/zero of=sdx bs=1M count=100
sudo losetup -f sdx
dd if=/dev/zero of=sdy bs=1M count=100
sudo losetup -f sdy
dd if=/dev/zero of=sdz bs=1M count=99  # Here's a smaller one!
sudo losetup -f sdz
Run Code Online (Sandbox Code Playgroud)

这将三个文件设置为三个环回块设备:/dev/loop0/dev/loop1/dev/loop2、分别映射到sdxsdysdz。让我们检查一下尺寸:

sudo grep loop[012] /proc/partitions
   7        0     102400 loop0
   7        1     102400 loop1
   7        2     101376 loop2
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,我们有两个正好 100M(102400 KiB = 100 MiB)的循环设备和一个 99M(正好 99×1024 1K 块)。

使用相同大小的设备制作 RAID 阵列

开始:

sudo mdadm  --create -e 1.2 -n 2 -l 1 /dev/md100 /dev/loop0 /dev/loop1
mdadm: array /dev/md100 started.
Run Code Online (Sandbox Code Playgroud)

检查尺寸:

sudo grep md100 /proc/partitions
   9      100     102272 md100
Run Code Online (Sandbox Code Playgroud)

这是precicely我们所期望的:一看mdadm的手册提醒我们,版本1.2元数据占用128K:128 + 102272 = 102400.现在让我们破坏它在第二个实验做准备。

sudo mdadm --stop /dev/md100
sudo mdadm --misc --zero-superblock /dev/loop0
sudo mdadm --misc --zero-superblock /dev/loop1
Run Code Online (Sandbox Code Playgroud)

使用大小不等的设备制作 RAID 阵列

这次我们将使用小块设备。

sudo mdadm  --create -e 1.2 -n 2 -l 1 /dev/md100 /dev/loop0 /dev/loop2
mdadm: largest drive (/dev/loop0) exceeds size (101248K) by more than 1%
Continue creating array? y
mdadm: array /dev/md100 started.
Run Code Online (Sandbox Code Playgroud)

好吧,我们得到了警告,但数组已经制作好了。让我们检查一下尺寸:

sudo grep md100 /proc/partitions
   9      100     101248 md100
Run Code Online (Sandbox Code Playgroud)

我们在这里得到的是 101,248 个块。101248 + 128 = 101376 = 99 × 1024。可用空间是最小设备的可用空间(加上128K RAID元数据)。让我们在上次实验中再次将其全部还原:

sudo mdadm --stop /dev/md100
sudo mdadm --misc --zero-superblock /dev/loop0
sudo mdadm --misc --zero-superblock /dev/loop2
Run Code Online (Sandbox Code Playgroud)

最后:将较小的设备添加到正在运行的阵列

首先,让我们使用 100M 磁盘中的一个来制作 RAID1 阵列。阵列会降级,但我们并不关心。我们只想要一个开始的数组。该missing关键字是一个占位符,上面写着“我没有为你的设备还没有,现在就开始他阵列,我会以后再添加一个”。

sudo mdadm  --create -e 1.2 -n 2 -l 1 /dev/md100 /dev/loop0 missing
Run Code Online (Sandbox Code Playgroud)

再次,让我们检查一下大小:

sudo grep md100 /proc/partitions
   9      100     102272 md100
Run Code Online (Sandbox Code Playgroud)

果然,它比 102400 个块少了 128K。添加较小的磁盘:

sudo mdadm  --add /dev/md100 /dev/loop2
mdadm: /dev/loop2 not large enough to join array
Run Code Online (Sandbox Code Playgroud)

繁荣!它不会让我们这样做,而且错误很明显。


0xC*_*22L 1

设置mdX设备的方法有多种。方法是使用gdisk(或者sgdisk如果您更喜欢仅命令行版本)将其分区为 GPT。如果您想从阵列启动,请创建一个“BIOS 启动分区”,输入 code ef02。仅当您想启动该阵列时才需要这样做,否则无需关心。然后,创建一个与要添加到阵列中的最小磁盘大小相同或更小的分区。最后但并非最不重要的一点是,将 GPT 数据复制到另一个磁盘(gdisk使用中的专家菜单x,然后u指定目标设备)。这是一个破坏性的过程。

如果文件系统允许,应该可以将现有分区的大小调整为较小的值,然后使用相同的方法复制 GPT 数据。然而,这会让你陷入一些混乱。因为现在你有两个磁盘,但仍然没有mdX设备。其中之一必须准备为mdX,无论是分区方式(我上面暗示的)还是磁盘方式),然后数据必须从现有磁盘移动到该磁盘。

所以:

  1. 大磁盘(/dev/sda)包含数据,数据小于 3001 GB,分区不存在
  2. 较小的磁盘/dev/sdb被添加到系统中
  3. /dev/sdb分区gdisk
  4. 您从每个相应的分区创建一个数组 ( mdadm -C /dev/md2 -l 1 -n 1 /dev/sdb2)
  5. 您在新阵列上创建文件系统
  6. 您复制所有数据,确保您的系统准备好运行 GPT 磁盘并使 GRUB2 理解其含义(见下文)
  7. 您将 GPT 分区数据从 复制/dev/sdb/dev/sda
  8. 您将“原始”分区添加/dev/sda到现有数组中
  9. 您等待/proc/mdstat显示同步已完成

如果您遵循了所有步骤,您现在应该能够从 mdX 阵列启动到新系统。不过,请随身携带救援 CD 或 PXE 启动选项,以防万一。


GRUB2 将无法立即识别该设置。所以你需要一些“魔法”。这是一行:

for i in /dev/disk/by-id/md-uuid-*; do DEV=$(readlink $i); echo "(${DEV##*/}) $i"; done|sort|tee /boot/grub/devicemap
Run Code Online (Sandbox Code Playgroud)

或者让我们更详细一点:

for i in /dev/disk/by-id/md-uuid-*
do
  DEV=$(readlink $i)
  echo "(${DEV##*/}) $i"
done|sort|sudo tee /boot/grub/devicemap
Run Code Online (Sandbox Code Playgroud)

这将创建(或覆盖)默认值/boot/grub/devicemap,告诉 GRUB2 在哪里可以找到每个相应的磁盘。结果将类似于此列表:

(md0) /dev/disk/by-id/md-uuid-...
(md2) /dev/disk/by-id/md-uuid-...
(md3) /dev/disk/by-id/md-uuid-...
(md4) /dev/disk/by-id/md-uuid-...
Run Code Online (Sandbox Code Playgroud)

如果您使用旧版 GRUB,您还需要使用元数据版本 0.9 创建“BIOS 引导分区”,使用mdadm -e 0 ...过程会有所不同。不过我还没有这样做。