18.3. RAID1 - 镜像

镜像(或 RAID1)是许多公司和家庭用户使用的一种无须中断的备份技术。 简单地说, 镜像的概念就是 磁盘B 是同步复制 (replicate) 的 磁盘A 的副本, 或者 磁盘C+D 是 diskA+B 的同步复制副本, 等等。 无论磁盘配置如何, 这种技术的共同特点都是一块磁盘或分区的内容会同步复制到另外的地方。 这样, 除了能够很容易地恢复信息之外, 还能够在无须中断服务或访问的情况下进行备份, 甚至直接将副本送到数据保安公司异地储存。

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

按照惯例,镜像模式中的两个磁盘容量相同,但 gmirror(8) 对此并无要求。如果两个磁盘容量不同,镜像模式下可用容量大小为两个磁盘中容量较小的那个。较大磁盘上的的额外空间将不被使用。以后插入镜像的驱动器的容量必须至少与镜像中已存在的最小驱动器的容量相同。

警告:

虽然镜像过程不会损坏原有数据,不过在操作之前先进行完整备份。

警告:

虽然dump(8)在这些过程中用于复制文件系统,但它不适用于具有软更新日志的文件系统。有关检测和禁用软更新日志的信息,请参阅tunefs(8)

18.3.1. Metadata问题

一些硬盘会将元数据(metadata)保存在硬盘末尾。旧的 metadata 在组成镜像前应被删除。大多数问题是由两种特定类型的遗留元数据引起的:GPT分区表和先前镜像中的老 metadata。

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

# gpart destroy -F ada8

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

# gmirror remove gm4 ada8

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

# gmirror clear ada8

gmirror(8) 在磁盘末尾存储元数据(metadata)。由于GPT 将分区方案放在磁盘末尾,不建议在 GPT 磁盘上使用gmirror(8)做镜像。这里使用MBR因为它仅将分区表放在磁盘开头,不与镜像元数据冲突。

18.3.2. 使用两个新磁盘建立镜像

在这个例子中,FreeBSD 已安装在 ada0 上。ada1ada2 已接入系统。本例将在这两块磁盘上创建镜像并用它来替换老磁盘(ada0)。

使用gmirror(8)前需将geom_mirror.ko模块编译或加载进内核。使用以下命令加载此模块:

# gmirror load

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

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

gm0 是将用户选择的镜像名。镜像创建好后可以在/dev/mirror/中看到镜像名。

现在可以使用 gpart(8) 在镜像上创建MBRbsdlabel 分区表。本例使用一个传统的文件系统布局,分区为/,swap,/var/tmp,和/usr。只创建/和 swap 分区也行。

镜像上的分区不必与现有磁盘上的分区大小相同,但它们必须足够大,以保存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

在新镜像上格式化文件系统,启用 soft-updates。

# newfs -U /dev/mirror/gm0s1a
# newfs -U /dev/mirror/gm0s1d
# newfs -U /dev/mirror/gm0s1e
# newfs -U /dev/mirror/gm0s1f

ada0上的文件系统可以使用 dump(8)restore(8) 复制到镜像中。

# 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 中看到的将是两个独立的磁盘,而非一个镜像。原因是磁盘是等价的,所以选择哪个引导并不重要。

如果出现问题,请参阅第 18.3.4 节 “故障排除”。关闭电源并断开ada0磁盘的连接将使其保留为脱机备份。

镜像的使用方式与源磁盘完全相同。

18.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等于ada0的磁盘大小,如上面diskinfo所示。

# 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)

在这种情况下,必须编辑分区表以将mirror/gm0上的容量减少一个扇区。过程稍后介绍。

在这两种情况下,应首先使用gpart backupgpart restore复制主磁盘上的分区表。

# gpart backup ada0 > table.ada0
# gpart backup ada0s1 > table.ada0s1

这些命令创建两个文件,table.ada0table.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挂载在/gm0s1d挂载在/vargm0s1e挂载在/usrgm0s1f挂载在/data1gm0s1g挂载在/data2

# 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以前相同的数据。如果引导时出问题,请查看第 18.3.4 节 “故障排除”

此时,镜像仍仅包含单个ada1磁盘。

成功从mirror/gm0启动后,将ada0插入镜像中。

重要:

ada0插入到镜像中时,其以前的内容将被镜像中的数据覆盖。在将ada0添加到镜像之前,请确保镜像/gm0的内容与ada0相同。如果转储(8)之前复制的内容和还原(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)

mirror/gm0现在由两个磁盘ada0ada1组成,内容会自动同步。在使用中,mirror/gm0将像原始单驱动器一样工作。

18.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:
  <fstype>:<device> [options]
      Mount <device> using filesystem <fstype>
      and with the specified (optional) option list.

    eg. 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)
  <empty line>    Abort manual input

mountroot>

Forgetting to load the geom_mirror.ko module in /boot/loader.conf can cause this problem. To fix it, boot from a FreeBSD installation media and choose Shell at the first prompt. Then load the mirror module and mount the mirror device:

# gmirror load
# mount /dev/mirror/gm0s1a /mnt

添加下列行到/mnt/boot/loader.conf,这样就能在系统启动时加载镜像模块:

geom_mirror_load="YES"

保存文件并重新启动。

Other problems that cause error 19 require more effort to fix. Although the system should boot from ada0, another prompt to select a shell will appear if /etc/fstab is incorrect. Enter ufs:/dev/ada0s1a at the boot loader prompt and press Enter. Undo the edits in /etc/fstab then mount the file systems from the original disk (ada0) instead of the mirror. Reboot the system and try the procedure again.

Enter full pathname of shell or RETURN for /bin/sh:
# cp /etc/fstab.orig /etc/fstab
# reboot

18.3.5. 从磁盘故障中恢复

磁盘镜像的好处是单个磁盘可能会失败,而不会导致镜像丢失任何数据。在上面的示例中,如果ada0发生故障,镜像将继续工作,提供来自剩余工作驱动器ada1的数据。

要更换发生故障的驱动器,请关闭系统,然后用容量相等或更大的新驱动器物理替换故障驱动器。制造商在以千兆字节为单位对驱动器进行评级时使用一些任意值,而真正确定的唯一方法是比较diskinfo -v显示的扇区总数。容量大于后视镜的驱动器将工作,但新驱动器上的额外空间将不使用。

计算机重新通电后,镜像将在只有一个驱动器的degraded 模式下运行。镜像被告知要忽略当前未连接的驱动器:

# gmirror forget gm0

应使用第 18.3.1 节 “Metadata问题”中的说明从替换磁盘中清除所有旧的元数据。然后, 替换 ada4,在本例中,将其插入到镜像中:

# gmirror insert gm0 /dev/ada4

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

可以使用gmirror status来监视进度,该状态显示正在同步的驱动器和完成百分比。在重新同步过程中,状态为DEGRADED,完成后状态改编为COMPLETE

本文档和其它文档可从这里下载: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题,请先阅读 文档,如不能解决再联系 <questions@FreeBSD.org>.

关于本文档的问题请发信联系 <doc@FreeBSD.org>.