21.3.RAID1——镜像

21.3.RAID1——镜像

RAID1,或者镜像,是将相同数据写入多个磁盘驱动器的技术。通常使用镜像来防止由于驱动器故障而导致的数据丢失。镜像中的每个驱动器包含数据的完全相同副本。当一个驱动器失败时,镜像继续工作,提供仍在运行的驱动器中的数据。计算机继续运行,管理员有时间替换失败的驱动器,而不会影响用户。

这些示例说明了两种常见情况。第一种情况是使用两个新驱动器创建镜像,并将其用作现有单个驱动器的替代品。第二个示例在单个新驱动器上创建镜像,将旧驱动器的数据复制到其中,然后将旧驱动器插入到镜像中。虽然这个过程稍微复杂,但只需要一个新驱动器。

传统上,镜像中的两个驱动器在型号和容量上是相同的,但 gmirror(8) 并不要求如此。使用不同驱动器创建的镜像的容量将等于镜像中最小驱动器的容量。较大驱动器上的额外空间将不会被使用。稍后插入到镜像中的驱动器必须至少具有镜像中最小驱动器的容量。

此处显示的镜像过程是非破坏性的,但与任何重要的磁盘操作一样,请先进行完整备份。 在这些过程中使用 dump(8)来复制文件系统,但在具有软更新日志记录的文件系统上无法工作。有关检测和禁用软更新日志记录的信息,请参阅 tunefs(8)。 21.3.1. 元数据问题 许多磁盘系统在每个磁盘的末尾存储元数据。在将磁盘用于镜像之前,应擦除旧元数据。大多数问题是由两种特定类型的残留元数据引起的:GPT 分区表和来自先前镜像的旧元数据。

使用 gpart(8) 可以擦除 GPT 元数据。此示例从磁盘 ada8 上擦除主 GPT 分区表和备份 GPT 分区表:

gpart destroy -F ada8

可以使用 gmirror(8) 一步移除活动镜像中的磁盘,并擦除元数据。此处,示例磁盘 ada8 从活动镜像 gm4 中移除:

gmirror remove gm4 ada8

如果镜像未运行,但旧的镜像元数据仍然在磁盘上,请使用 gmirror clear 将其移除:

gmirror clear ada8

gmirror(8) 在磁盘末尾存储一个块的元数据。由于 GPT 分区方案也在磁盘末尾存储元数据,因此不建议使用 gmirror(8) 镜像整个 GPT 磁盘。这里使用 MBR 分区是因为它只在磁盘开头存储分区表,不会与镜像的元数据冲突。

创建具有两个新磁盘的镜像 在本示例中,FreeBSD 已安装在单个磁盘 ada0 上。已连接两个新磁盘 ada1 和 ada2 到系统。将在这两个磁盘上创建一个新的镜像,并用它们替换旧的单个磁盘。

geom_mirror.ko 内核模块必须构建到内核中或在启动或运行时加载。现在手动加载内核模块:

gmirror load

使用两个新驱动器创建镜像:

gmirror label -v gm0 /dev/ada1 /dev/ada2

gm0 是分配给新镜像的用户选择的设备名称。镜像启动后,此设备名称将出现在/dev/mirror/中。

MBR 和 bsdlabel 分区表现在可以使用 gpart(8) 在镜像上创建。此示例使用传统的文件系统布局,包括用于 /、交换、/var、/tmp 和 /usr 的分区。单独使用 / 和交换分区也可以。

镜像上的分区大小不必与现有磁盘上的分区大小相同,但必须足够大以容纳已经存在于 ada0 上的所有数据。

gpart create -s MBR mirror/gm0

gpart add -t freebsd -a 4k mirror/gm0

gpart show mirror/gm0

=> 63 156301423 mirror/gm0 MBR (74G) 63 63 - free - (31k) 126 156301299 1 freebsd (74G) 156301425 61 - free - (30k)

gpart create -s BSD mirror/gm0s1

gpart add -t freebsd-ufs -a 4k -s 2g mirror/gm0s1

gpart add -t freebsd-swap -a 4k -s 4g mirror/gm0s1

gpart add -t freebsd-ufs -a 4k -s 2g mirror/gm0s1

gpart add -t freebsd-ufs -a 4k -s 1g mirror/gm0s1

gpart add -t freebsd-ufs -a 4k mirror/gm0s1

gpart show mirror/gm0s1

=> 0 156301299 mirror/gm0s1 BSD (74G) 0 2 - free - (1.0k) 2 4194304 1 freebsd-ufs (2.0G) 4194306 8388608 2 freebsd-swap (4.0G) 12582914 4194304 4 freebsd-ufs (2.0G) 16777218 2097152 5 freebsd-ufs (1.0G) 18874370 137426928 6 freebsd-ufs (65G) 156301298 1 - free - (512B) 通过在 MBR 和 bsdlabel 上安装引导代码并设置活动分区,使镜像可引导:

gpart bootcode -b /boot/mbr mirror/gm0

gpart set -a active -i 1 mirror/gm0

gpart bootcode -b /boot/boot mirror/gm0s1

在新镜像上格式化文件系统,启用软更新。

newfs -U /dev/mirror/gm0s1a

newfs -U /dev/mirror/gm0s1d

newfs -U /dev/mirror/gm0s1e

newfs -U /dev/mirror/gm0s1f

现在可以使用 dump(8)和 restore(8)将原来的 ada0 磁盘上的文件系统复制到镜像上。

mount /dev/mirror/gm0s1a /mnt

dump -C16 -b64 -0aL -f - / | (cd /mnt && restore -rf -)

mount /dev/mirror/gm0s1d /mnt/var

mount /dev/mirror/gm0s1e /mnt/tmp

mount /dev/mirror/gm0s1f /mnt/usr

dump -C16 -b64 -0aL -f - /var | (cd /mnt/var && restore -rf -)

dump -C16 -b64 -0aL -f - /tmp | (cd /mnt/tmp && restore -rf -)

dump -C16 -b64 -0aL -f - /usr | (cd /mnt/usr && restore -rf -)

编辑/mnt/etc/fstab 以指向新镜像文件系统:

Device Mountpoint FStype Options Dump Pass#

/dev/mirror/gm0s1a / ufs rw 1 1 /dev/mirror/gm0s1b none swap sw 0 0 /dev/mirror/gm0s1d /var ufs rw 2 2 /dev/mirror/gm0s1e /tmp ufs rw 2 2 /dev/mirror/gm0s1f /usr ufs rw 2 2 如果 geom_mirror.ko 内核模块没有编译进内核中,需要编辑 /mnt/boot/loader.conf 文件,在启动时加载该模块:

geom_mirror_load="YES" 重启系统以测试新的镜像,并验证所有数据是否已复制。BIOS 将把镜像看作两个独立的驱动器,而不是一个镜像。由于驱动器是相同的,选择哪一个启动并不重要。

如果启动时出现问题,请参阅故障排除。关闭电源并断开原始的 ada0 磁盘可以将其保留为离线备份。

在使用中,镜像将表现得就像原始的单个驱动器一样。

21.3.3. 使用现有驱动器创建镜像 在这个例子中,FreeBSD 已经安装在单个磁盘 ada0 上。一个新的磁盘 ada1 已连接到系统。将在新磁盘上创建一个单盘镜像,并将现有系统复制到其中,然后将旧磁盘插入镜像中。这个稍微复杂的过程是必需的,因为 gmirror 需要在每个磁盘的末尾放置一个 512 字节的元数据块,而现有的 ada0 通常已经分配了所有的空间。

载入 geom_mirror.ko 内核模块:

gmirror load

使用 diskinfo 检查原始磁盘的媒体大小:

diskinfo -v ada0 | head -n3

/dev/ada0 512 # sectorsize 1000204821504 # mediasize in bytes (931G) 在新硬盘上创建镜像。为确保镜像容量不大于原始的 ada0 驱动器,使用 gnop(8) 创建一个与原始大小相同的虚拟驱动器。该驱动器不存储任何数据,仅用于限制镜像的大小。当 gmirror(8) 创建镜像时,将限制容量为 gzero.nop 的大小,即使新的 ada1 驱动器有更多的空间。注意,第二行中的 1000204821504 等于 diskinfo 所示的 ada0 的媒体大小。

geom zero load

gnop create -s 1000204821504 gzero

gmirror label -v gm0 gzero.nop ada1

gmirror forget gm0

由于 gzero.nop 不存储任何数据,因此镜像不会将其视为已连接。镜像被告知“忘记”未连接的组件,从而删除对 gzero.nop 的引用。结果是一个只包含单个磁盘 ada1 的镜像设备。

创建 gm0 后,在 ada0 上查看分区表。此输出来自 1 TB 驱动器。如果驱动器末尾有一些未分配空间,则可以直接从 ada0 复制内容到新镜像。

但是,如果输出显示磁盘上的所有空间都已分配,如下列表所示,则磁盘末尾没有空间可用于 512 字节的镜像元数据。

gpart show ada0

=> 63 1953525105 ada0 MBR (931G) 63 1953525105 1 freebsd [active] (931G) 在这种情况下,必须编辑分区表,将镜像/gm0 的容量减少一个扇区。程序将在稍后解释。

在任一情况下,应首先使用 gpart backup 和 gpart restore 复制主磁盘上的分区表。

gpart backup ada0 > table.ada0

gpart backup ada0s1 > table.ada0s1

这些命令将创建两个文件,table.ada0 和 table.ada0s1。这个例子是从一个 1TB 硬盘中提取的。

cat table.ada0

MBR 4 1 freebsd 63 1953525105 [active]

cat table.ada0s1

BSD 8 1 freebsd-ufs 0 4194304 2 freebsd-swap 4194304 33554432 4 freebsd-ufs 37748736 50331648 5 freebsd-ufs 88080384 41943040 6 freebsd-ufs 130023424 838860800 7 freebsd-ufs 968884224 984640881 如果磁盘末尾没有显示空闲空间,则必须将分区和最后一个分区的大小减小一个扇区。编辑这两个文件,将分区和最后一个分区的大小都减小一个。这些都是每个列表中的最后几个数字。

cat table.ada0

MBR 4 1 freebsd 63 1953525104 [active]

cat table.ada0s1

BSD 8 1 freebsd-ufs 0 4194304 2 freebsd-swap 4194304 33554432 4 freebsd-ufs 37748736 50331648 5 freebsd-ufs 88080384 41943040 6 freebsd-ufs 130023424 838860800 7 freebsd-ufs 968884224 984640880 如果磁盘末尾有至少一个未分配的扇区,则这两个文件可以直接使用,无需修改。

现在将分区表恢复到 mirror/gm0:

gpart restore mirror/gm0 < table.ada0

gpart restore mirror/gm0s1 < table.ada0s1

使用 gpart show 检查分区表。此示例中,/ 使用 gm0s1a,/var 使用 gm0s1d,/usr 使用 gm0s1e,/data1 使用 gm0s1f,/data2 使用 gm0s1g。

gpart show mirror/gm0

=> 63 1953525104 mirror/gm0 MBR (931G) 63 1953525042 1 freebsd [active] (931G) 1953525105 62 - free - (31k)

gpart show mirror/gm0s1

=> 0 1953525042 mirror/gm0s1 BSD (931G) 0 2097152 1 freebsd-ufs (1.0G) 2097152 16777216 2 freebsd-swap (8.0G) 18874368 41943040 4 freebsd-ufs (20G) 60817408 20971520 5 freebsd-ufs (10G) 81788928 629145600 6 freebsd-ufs (300G) 710934528 1242590514 7 freebsd-ufs (592G) 1953525042 63 - free - (31k) 切片和最后一个分区必须在磁盘末尾至少有一个空闲块。

在这些新分区上创建文件系统。分区数量将根据原始磁盘 ada0 的情况而变化。

newfs -U /dev/mirror/gm0s1a

newfs -U /dev/mirror/gm0s1d

newfs -U /dev/mirror/gm0s1e

newfs -U /dev/mirror/gm0s1f

newfs -U /dev/mirror/gm0s1g

通过在 MBR 中安装引导代码和 bsdlabel 并设置活动切片使镜像可引导:

gpart bootcode -b /boot/mbr mirror/gm0

gpart set -a active -i 1 mirror/gm0

gpart bootcode -b /boot/boot mirror/gm0s1

调整/etc/fstab 以使用镜像上的新分区。首先通过将其复制到/etc/fstab.orig 备份此文件。

cp /etc/fstab /etc/fstab.orig

编辑/etc/fstab,将/dev/ada0 替换为 mirror/gm0。

Device Mountpoint FStype Options Dump Pass#

/dev/mirror/gm0s1a / ufs rw 1 1 /dev/mirror/gm0s1b none swap sw 0 0 /dev/mirror/gm0s1d /var ufs rw 2 2 /dev/mirror/gm0s1e /usr ufs rw 2 2 /dev/mirror/gm0s1f /data1 ufs rw 2 2 /dev/mirror/gm0s1g /data2 ufs rw 2 2 如果 geom_mirror.ko 内核模块未构建到内核中,请编辑/boot/loader.conf 以在启动时加载它:

geom_mirror_load="YES" 现在可以使用 dump(8)和 restore(8)将原始磁盘上的文件系统复制到镜像中。使用 dump -L 转储的每个文件系统都将首先创建一个快照,这可能需要一些时间。

mount /dev/mirror/gm0s1a /mnt

dump -C16 -b64 -0aL -f - / | (cd /mnt && restore -rf -)

mount /dev/mirror/gm0s1d /mnt/var

mount /dev/mirror/gm0s1e /mnt/usr

mount /dev/mirror/gm0s1f /mnt/data1

mount /dev/mirror/gm0s1g /mnt/data2

dump -C16 -b64 -0aL -f - /usr | (cd /mnt/usr && restore -rf -)

dump -C16 -b64 -0aL -f - /var | (cd /mnt/var && restore -rf -)

dump -C16 -b64 -0aL -f - /data1 | (cd /mnt/data1 && restore -rf -)

dump -C16 -b64 -0aL -f - /data2 | (cd /mnt/data2 && restore -rf -)

重启系统,从 ada1 引导。如果一切正常,系统将从 mirror/gm0 引导,其中现在包含与 ada0 先前相同的数据。如果引导时出现问题,请参阅故障排除。

在这一点上,镜像仍然只包含单个 ada1 磁盘。

成功从镜像/gm0 引导后,最后一步是将 ada0 插入镜像。

当 ada0 被插入镜像时,它原来的内容将被镜像中的数据覆盖。在将 ada0 添加到镜像之前,请确保镜像/gm0 的内容与 ada0 相同。如果通过 dump(8) 和 restore(8) 复制的内容与 ada0 上的内容不一致,请恢复 /etc/fstab 以在 ada0 上挂载文件系统,重启,并重新开始整个过程。

gmirror insert gm0 ada0

GEOM_MIRROR: Device gm0: rebuilding provider ada0 两个磁盘之间的同步将立即开始。使用 gmirror status 查看进度。

gmirror status

  Name    Status  Components

mirror/gm0 DEGRADED ada1 (ACTIVE) ada0 (SYNCHRONIZING, 64%) 一段时间后,同步将完成。

GEOM_MIRROR: Device gm0: rebuilding provider ada0 finished.

gmirror status

  Name    Status  Components

mirror/gm0 COMPLETE ada1 (ACTIVE) ada0 (ACTIVE) 镜像/gm0 现在由两个磁盘 ada0 和 ada1 组成,并且内容会自动相互同步。在使用中,镜像/gm0 会像原始单个驱动器一样行为。

21.3.4. 故障排除 如果系统不再启动,则可能需要更改 BIOS 设置以从新镜像驱动器启动。可以使用任何一块镜像驱动器进行引导,因为它们包含相同的数据。

如果引导停在此消息上,可能是镜像设备出现问题:

Mounting from ufs:/dev/mirror/gm0s1a failed with error 19.

Loader variables: vfs.root.mountfrom=ufs:/dev/mirror/gm0s1a vfs.root.mountfrom.options=rw

Manual root filesystem specification: : [options] Mount using filesystem and with the specified (optional) option list.

e.g. ufs:/dev/da0s1a
    zfs:tank
    cd9660:/dev/acd0 ro
      (which is equivalent to: mount -t cd9660 -o ro /dev/acd0 /)

? List valid disk boot devices . Yield 1 second (for background tasks) Abort manual input

mountroot> 在/boot/loader.conf 中忘记加载 geom_mirror.ko 模块可能会导致此问题。要修复它,请从 FreeBSD 安装媒体引导,并在第一个提示处选择 Shell。然后加载镜像模块并挂载镜像设备:

gmirror load

mount /dev/mirror/gm0s1a /mnt

编辑/mnt/boot/loader.conf,添加一行以加载镜像模块:

geom_mirror_load="YES" 保存文件并重启。

引起 error 19 的其他问题需要更多的努力来修复。尽管系统应该从 ada0 引导,但如果 /etc/fstab 不正确,将出现另一个选择 shell 的提示。在引导装载程序提示符处输入 ufs:/dev/ada0s1a 然后按回车键。撤消 /etc/fstab 中的编辑,然后从原始磁盘(ada0)而不是镜像中装载文件系统。重启系统,然后再尝试该过程。

Enter full pathname of shell or RETURN for /bin/sh:

cp /etc/fstab.orig /etc/fstab

reboot

21.3.5. 从磁盘故障中恢复 磁盘镜像的好处在于个别磁盘可以故障而不会导致镜像丢失任何数据。在上面的示例中,如果 ada0 失效,镜像将继续工作,从其余工作驱动器 ada1 提供数据。

要更换故障的驱动器,请关闭系统,并用容量相同或更大的新驱动器物理替换故障驱动器。制造商在以千兆字节为单位对驱动器进行评级时使用了一些任意值,想要确保的唯一方法是比较 diskinfo -v 所显示的扇区总数。比镜像容量大的驱动器将起作用,尽管新驱动器上的多余空间不会被使用。

计算机重新上电后,镜像将以“降级”模式运行,只有一个驱动器。镜像被告知忘记当前未连接的驱动器:

gmirror forget gm0

应使用“元数据问题”中的说明清除替换磁盘上的任何旧元数据。然后,将替换磁盘(例如,ada4)插入到镜像中:

gmirror insert gm0 /dev/ada4

重新同步开始于将新驱动器插入镜像中。将镜像数据复制到新驱动器的过程可能需要一段时间。在复制过程中,镜像的性能将大大降低,因此最好在计算机需求较低时插入新驱动器。

进度可以通过 gmirror status 进行监控,它显示正在同步的驱动器和完成百分比。在重新同步过程中,状态将为 DEGRADED,在进程完成时变为 COMPLETE。

最后更新于

FreeBSD 中文社区 2024