跳至内容

Jixun's Blog 填坑还是开坑,这是个好问题。

迁移 mdadm RAID-1 到新硬盘

一开始是使用 Debian 安装程序自动使用 mdadm 将两块 3.5 寸的机械硬盘组了个 RAID-1 硬盘组。

这段时间发现机械硬盘的一些问题:

  • 耗电更高
  • 噪音会比较大
  • 节能模式唤醒需要时间。

因此,准备了替代的固态硬盘,尝试将硬盘组替换过去。

环境

因为主板的 SATA 口只有四个,不太够用;因此准备一个 Ubuntu 的 LiveCD 环境通过 USB 引导,将四个 SATA 口都接到新旧的四块硬盘上。

如果你的设备有足够的接口,直接在同设备操作也可以。

我选择 Ubuntu 的 Live CD 环境是因为它的 Live 环境包括了如 mdadmgdisk 等这些常用的维护工具。

本文的硬盘/分区 UUID 为了方便阅读,都使用了简单的字符来代替,方便跟随。

搜集信息

安装后可以列出所有硬盘组安装位置:

ls -l /dev/md*

发现旧的 mdadm 设备名为 md127

使用 fdisk 搜寻新插入的硬盘:

fdisk -l

通过对比 Disk model 的型号,可以发现新的硬盘位于 /dev/sda/dev/sdd

对新硬盘进行分区

有一个好处就是相比整个设备用来组 RAID,使用分区的方式在未来替换硬盘更为方便。

分别执行下述指令对两块硬盘进行分区操作:

gparted /dev/sda
gparted /dev/sdd

执行 gparted 时,可以参考下述说明来删除所有分区并重建一个 Linux RAID 分区:

Command (? for help): o
This option deletes all partitions and creates a new protective MBR.
Proceed? (Y/N): y

Command (? for help): n
Partition number (1-128, default 1):
First sector (34-8001573518, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-8001573518, default = 8001572863) or {+-}size{KMGTP}:
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300): fd00
Changed type of partition to 'Linux RAID'

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sdd.
The operation has completed successfully.

利用 mdadm 建立新的 RAID

因为我希望使用分区的 UUID 来识别,而非启动时注册到系统的顺序,因此查询 ID:

blkid -s UUID

找到 sda1sdd1 对应的分区 UUID

/dev/sda1: UUID="00000000-0000-0000-0000-111111111111"
/dev/sdd1: UUID="00000000-0000-0000-0000-222222222222"

然后通知 mdadm 将其组合起来:

mdadm --verbose --create /dev/md0 --level=1 --raid-devices=2 \
  /dev/disk/by-partuuid/00000000-0000-0000-0000-111111111111 \
  /dev/disk/by-partuuid/00000000-0000-0000-0000-222222222222

会询问你是否确定。因为启动盘放在了独立的盘,因此根据说明键入 yes 即可:

mdadm: Note: this array has metadata at the start and
    may not be suitable as a boot device.  If you plan to
    store '/boot' on this device please ensure that
    your boot-loader understands md/v1.x metadata, or use
    --metadata=0.90
mdadm: size set to 4000653312K
mdadm: automatically enabling write-intent bitmap on large array
Continue creating array? yes
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

然后对新的硬盘组进行分区:

gdisk /dev/md0

操作过程:

GPT fdisk (gdisk) version 1.0.10

Partition table scan:
    MBR: not present
    BSD: not present
    APM: not present
    GPT: not present

Creating new GPT entries in memory.

Command (? for help): o
This option deletes all partitions and creates a new protective MBR.
Proceed? (Y/N): y

Command (? for help): n
Partition number (1-128, default 1):
First sector (34-8001306590, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-8001306590, default = 8001304575) or {+-}size{KMGTP}:
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/md0.
The operation has completed successfully.

因为硬盘比较大,因此格式化的时候顺便让它直接进行初始化而非之后在后台慢悠悠的处理:

mkfs.ext4 -E lazy_itable_init=0,lazy_journal_init=0 /dev/md0p1

然后就是将新旧两组挂进系统里,为数据迁移做准备:

mkdir -p /mnt/{hdd-old,ssd-new}
mount /dev/md127p1 /mnt/hdd-old/
mount /dev/md0p1 /mnt/ssd-new/

进行数据迁移,将 lost+found 之外的内容同步过去:

cd /mnt/hdd-old/
rsync --progress -av --numeric-ids --exclude=lost+found/ * /mnt/ssd-new/

※ 使用 partclone 进行分区拷贝也可以。但我不是很熟悉它的参数,此处就不谈了。

完事后就可以使用 poweroff 指令关机啦。

回到系统

执行关机指令后并确认设备断电;然后将旧的两块硬盘移除,并安装上最初的引导盘后启动。

此时新的硬盘组自动被 mdadm 识别,但未能自动挂载为可读写:

cat /proc/mdstat

输出:

Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md0 : active (auto-read-only) raid1 sdb1[1] sdc1[0]
      4000653312 blocks super 1.2 [2/2] [UU]
        resync=PENDING
      bitmap: 15/30 pages [60KB], 65536KB chunk

unused devices: <none>

其中一个原因是因为硬盘组的名称不匹配,可以通过下述指令查询:

mdadm --detail /dev/md0

输出:

/dev/md0:
           Version : 1.2

          ... 省略一些信息 ...

              Name : ubuntu:0
              UUID : 11000000:00000000:00000000:000000ff
            Events : 1234

          ... 省略一些信息 ...

可以看到它的名称是错误的,稍微修正下即可。

mdadm --stop /dev/md0
# 输出: mdadm: stopped /dev/md0

mdadm --assemble --update=name --name="$(hostname):0" /dev/md0 \
  /dev/disk/by-partuuid/00000000-0000-0000-0000-111111111111 \
  /dev/disk/by-partuuid/00000000-0000-0000-0000-222222222222
# 输出: mdadm: /dev/md0 has been started with 2 drives.

# 如果还是自动挂载为只读模式,将其修改为可读写:
mdadm --readwrite /dev/md0

然后编辑 /etc/mdadm/mdadm.conf 的硬盘组配置文件,将旧的硬盘组 ID 和 name 依次更改:

  • UUID - aaaaaaaa:aaaaaaaa:aaaaaaaa:aaaaaaaa11000000:00000000:00000000:000000ff
  • name - zyra:127zyra:0
@@ 更新 mdadm 的说明文件,红色为更改前,绿色为更改后。

 # definitions of existing MD arrays
-ARRAY /dev/md/0  metadata=1.2 UUID=aaaaaaaa:aaaaaaaa:aaaaaaaa:aaaaaaaa name=zyra:127
+ARRAY /dev/md/0  metadata=1.2 UUID=11000000:00000000:00000000:000000ff name=zyra:0

 # This configuration was auto-generated on ...... by mkconf

然后根据该配置文件顶部的说明,更新引导:

update-initramfs -u

最后,因为是在新的硬盘组建立了新的分区,所以分区 ID 也变了。

使用 blkid 查询:

blkid -s PARTUUID /dev/md0p1

得到输出:

/dev/md0p1: PARTUUID="00000000-0000-0000-ffff-333333333333"

因此更改 /etc/fstab,将对应的分区 UUID 也更改:

@@ 更新挂载目标的 UUID
-UUID=00000000-0000-0000-0000-333333333333 /storage/my-linux-iso-collection ext4 defaults,errors=remount-ro,nofail 0 1
+UUID=00000000-0000-0000-ffff-333333333333 /storage/my-linux-iso-collection ext4 defaults,errors=remount-ro,nofail 0 1

确认无误后,就执行 reboot 进行重启吧。

最终确认

连接到服务器,检查挂载点 /storage/my-linux-iso-collection,可以发现里面的数据都能正常访问了。

依赖该路径的应用程序也都可以正常启动。

结语

比 LVM 好使,只需要将 mdadmmd 当作一个虚拟硬盘设备来理解就能充分利用现有的 Linux 知识对它操作了。

知识共享许可协议 本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。

评论区