如何利用修复光盘将一个 CentOS 5 系统转换成 RAID1

1. 引言

1.1. 内容

这个文档要描述的是将一个缺省的 CentOS 5 系统转换为 RAID 1 的程序。我盼望你能够将这个技巧扩展到一个更复杂的系统,因为本作者缺乏足够耐性来枚举所有可能的系统设置,及如何转换成所有可能的硬盘阵列类型。

通过修复模式,现存的文件系统可以在非运行中、只读的状况下被复制,这样对系统比较有保障。

1.2. 警告

为了规范程序,下面是数个限制……

1.3. 先决条件

要有效地应用这份文档,我们推荐你拥有……

1.4. 免责声明

这里并不提供任何类型的保证。系统间的差异实在太大,令这份文档不能涵盖所有可能性。系统管理员请留意:如果你的系统毁坏了,你要了承担一切后果(这句有版权吗?)。

2. 引导修复模式

修复模式是维修损坏了的系统最迫不得已时才用的方法。一个系统总会有某种修复用的开机方法。

2.1. 利用安装媒体开机

这可以是 CD、DVD、USB 存储器或 PXE 映像。创建安装媒体的方法超越了这份文档的范围,但你可以假设这个媒体存在,因为你拥有一台安装成功的机器。如果这个媒体并不存在,请查看 http://www.centos.org

2.2. 选择修复模式

在开机的提示符,输入

linux rescue

然后按 Enter。

2.3. 选择语言

利用箭嘴键选择所需语言并按 Enter。

2.4. 选择键盘类型

利用箭嘴键选择所需键盘分配并按 Enter。

2.5. 网络界面

网络界面并非必要的。请用箭嘴键选择 No 并按 Enter。

2.6. 省略挂载现有系统

在修复划面,利用箭嘴键选择 Skip 并按 Enter。我们稍后将会进行挂载。

2.7. 修复模式

恭喜你!你已经进入修复模式!

修复模式在这些情况下很有用……

3. 设置新设备

此刻,新设备的实物应该已经安装在系统中,并且正确地接了线。普遍来说,这是在切了电源的情形下进行。

3.1. 判断新设备的名称

假设新的存储设备已经安装在系统内,并且接驳了合适的数据及电源线,那么你多数可以用这个方法来判断现有及新设备的名称……

fdisk -l

样例的系统返回……

Disk /dev/sda: 250.0 GB, 250000000000 bytes
255 heads, 63 sectors/track, 30394 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          13      104391   83  Linux
/dev/sda2              14       30394   244035382+  8e  Linux LVM

Disk /dev/sdb: 250.0 GB, 250000000000 bytes
255 heads, 63 sectors/track, 30394 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Disk /dev/sdb doesn't contain a valid partition table

在这个例子里,现有系统正在使用 /dev/sda,而新的设备名叫 dev/sdb。如果是 ATA 的话,它们大可以是 /dev/hda 及 /dev/hdc。可能的话,这两个设备应该在不同的界面上。就 SATA 及 SCSI 而言,设备的名称不能透露它们位于哪个界面上,但就 ATA 而言,/dev/hda 及 /dev/hdb 表示它们在同一个界面上。这或许是无可避免,但却不可取。

3.2. 创建新的分区

根据可追溯到 SunOS 年代的传统智慧,把 /boot 放在 RAID 1 设备上带来潜在的安全性及容错问题。以人手方式复制 /boot 至另一个转轴(随着传统扩展,包括 Solaris 上的 / 分区映像)提供一个安全性备份,因为拥有两个可访问的 /boot 分区增加某个 /boot 仍旧可用的机会。

你可以说这个做法能创建一个更可靠的系统,因为它在主分区被更新或恶意破坏时,提供了另一个开机修复的途径,而代价只是(通过挂载、一个 rsync 指命、及卸下)保持次要及主要分区同步。若然真的要修复开机设备,你只须编辑 grub 的指命行并指定后备的 /root 设备问题便能「迎刃而解」。另外值得留意的,就是运用「双重 /root」这个方案时必须预备一台本地的终端機。

一旦主要的 /boot 分区被修改及成功地测试后,你便可以用手动的方式定时将它同步。针对修复时备用及失效时提供保障,利用 raid 把内容「分布」到两个转轴的「好处」并不胜于在两个转轴保留基本的 /boot 分区。这是由于 raid 层级加入额外的复杂性及故障点。话虽如此,有些人基于其它人不同意的理由希望在每一处应用磁盘数组,而这篇文章会继续讨论这个做法。

这篇文章的目标是要拥有一台通过 raid 能抵受设备出现故障的系统,而不是其它做法。我我们将忽视其它考虑因素。我们会将 /boot 放在磁盘数组,藉以简化程序。

/!\ 注:上述句子所谓「简化程序」的复杂情度其实过于在两个实体硬盘上装入传统分区,然后定时定候通过 rsync 把次设备与主设备同步。

缺省的安装为 / 创建一个颇复杂的设置,而我们加入 RAID 1 时将会令它更复杂。使用 LVM 的好处就是你可以移动分区来迎合不同的空间需求。

请利用 fdisk 这个分区工具程序……

fdisk /dev/sdb

n 及 Enter 来创建一个新的分区。按 p 及 Enter 来选择主分区。按 1 及 Enter 来选择首个分区。按 Enter 来选择新分区在设备的头开始。输入 +100M 及按 Enter 来限制新分区的尺寸为 100M。按 t 及 Enter,接着输入 fd 及按 Enter 来更改分区类型为 RAID。

n 及 Enter 来创建第二个新的分区。按 p 及 Enter 来选择主分区。按 2 及 Enter 来选择第二个分区。按 Enter 来选择新分区由下一个柱面开始。按 Enter 来使用设备上余下的空间。按 t 及 Enter 来更改分区类型。由于我们将会有多个分区,我们须要选择 2 并按 Enter。输入 fd 及按 Enter 来选择 RAID。

p 及 Enter 来确定分区的设置。

w 及 Enter 将修改写入。

系统的回复应该是……

The number of cylinders for this disk is set to 30394.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-30394, default 1): 
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-30394, default 30394): +100M

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): fd
Changed system type of partition 1 to fd (Linux raid autodetect)

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (14-30394, default 14): 
Using default value 14
Last cylinder or +size or +sizeM or +sizeK (14-30394, default 30394): 
Using default value 30394

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): fd
Changed system type of partition 2 to fd (Linux raid autodetect)

Command (m for help): p

Disk /dev/sdb: 250.0 GB, 250000000000 bytes
255 heads, 63 sectors/track, 30394 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1          13      104391   fd  Linux raid autodetect
/dev/sdb2              14       30394   244035382+  fd  Linux raid autodetect

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

至于那些想剪贴指令的人……

echo -e "n\np\n1\n\n+100M\nt\nfd\nn\np\n2\n\n\nt\n2\nfd\np\nw" | fdisk /dev/sdb

3.3. 创建 RAID 设备

为 /boot 创建一个 RAID 1 设备。由于第二个设备暂时仍未存在,因此它需要预留一个地方。我们稍后便会加入第二个设备。

mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 missing

所得的输出应该是……

mdadm: array /dev/md0 started.

为 / 创建第二个 RAID 1 设备。

mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sdb2 missing

所得的输出应该是……

mdadm: array /dev/md1 started.

3.4. 将新的 /boot 设备格式化

缺省的安装会将一个 ext3 分区放置在 /boot。标签可以帮助系统判断分区应该挂载在哪里。要依从这个标准……

mkfs.ext3 -L '/boot' /dev/md0

所得的输出应该是……

mke2fs 1.39 (29-May-2006)
Filesystem label=/boot
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
26104 inodes, 104320 blocks
5216 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
13 block groups
8192 blocks per group, 8192 fragments per group
2008 inodes per group
Superblock backups stored on blocks:
        8193, 24577, 40961, 57345, 73729

Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 30 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

3.5. 创建新的 / 分区

这样将 /dev/md1 设置为一个实体扇区……

lvm pvcreate /dev/md1

创建一个新的扇区群组……

lvm vgcreate RaidSys /dev/md1

创建一个新的逻辑调换扇区……

lvm lvcreate --size 4G --name swap RaidSys

创建一个新的逻辑 root 扇区……

lvm lvcreate --size 200G --name Root RaidSys

将新的调换设备格式化……

mkswap /dev/RaidSys/swap

将新的 / 设备格式化……

mkfs.ext3 -L '/' /dev/RaidSys/Root

3.6. 挂载分区

将所有设备挂载在我们找得着的地方……

mkdir /mnt/boot.old
mount -o ro /dev/sda1 /mnt/boot.old

mkdir /mnt/boot.new
mount /dev/md0 /mnt/boot.new

lvm vgchange --available y VolGroup00
mkdir /mnt/root.old
mount -o ro /dev/VolGroup00/LogVol00 /mnt/root.old

mkdir /mnt/root.new
mount /dev/RaidSys/Root /mnt/root.new

4. 移动数据至新设备

4.1. 对 /boot 进行同步

rsync 这个工具应该能够保留拥有权及更改日期,加上 X 标志更能保留扩展属性。加入 H 旗可以保留硬连结(多谢 Phil)。很不幸地,它似乎不能保留 SELinux 的属性。请将数据同步……

rsync -avXH /mnt/boot.old/* /mnt/boot.new/

对于较喜欢用 tar 的人们,这样做会从旧的 /boot 创建一个没有加压的压缩档,然后将它解压到新的设备上……

tar -C /mnt/boot.old -cf - . | tar -C /mnt/boot.new -xf -

4.2. 对 / 进行同步

再一次利用 rsync 工具……

rsync -avXH /mnt/root.old/* /mnt/root.new/

或者 tar……

tar -C /mnt/root.old -cf - . | tar -C /mnt/root.new -xf -

4.3. 重新标签 SELinux

为要请求 SELinux 的属性在开机时重新被标签,创建一个标志文件……

touch /mnt/root.new/.autorelabel

4.4. 令新的设备可作开机之用

你必须完成某些修改新系统的维护项目才能令它可以开机。

4.4.1. 安装 grub

令新的 RAID 设备可以用来开机……

grub
root (hd1,0)
setup (hd1)
quit

4.4.2. 编辑 grub 配置文件

root 设备是与别不同的,grub 需要知道关于它来告诉内核。编辑 /mnt/boot.new/grub/menu.lst。安装媒体内包括 joe,它可以用来仿真 nano 及 vi。请用你觉得舒服的指令。将所有 /dev/VolGroup00/LogVol00 的地方改为 /dev/RaidSys/Root。存储你的修改。

4.4.3. 编辑文件系统列表

一旦系统能够再次开机,你需要知道新的 root 设备是什么。编辑 /mnt/root.new/etc/fstab,将所有 /dev/VolGroup00/LogVol00 改为 /dev/RaidSys/Root。一般来说,/boot 是靠标签来挂载,但我们现在于每个硬盘上都有 /boot。让我们将 LABEL=/boot 改为 /dev/md0。将 /dev/VolGroup00/LogVol01 改为 /dev/RaidSys/swap。存储你的修改。

4.4.4. 创建新的 initrd

旧的系统在开机并不需要 RAID 驱动程序。现在它需要了。我们必须在 initrd 设置 RAID 驱动程序。以一个运作中的系统来完成这步骤会最容易。我们可以将 proc、dev、sys 及 selinux 这些虚拟目录联系到修复系统的版本,让它看似一个运作中的系统。

umount /mnt/boot.new
mount /dev/md0 /mnt/root.new/boot
mount -o bind /proc /mnt/root.new/proc
mount -o bind /dev /mnt/root.new/dev
mount -o bind /sys /mnt/root.new/sys
mount -o bind /selinux /mnt/root.new/selinux

现在进入新的系统……

chroot /mnt/root.new

查看现有的映像来判断你现有的系统是什么……

ls /boot/*.img

在测试的系统上,这样做返回……

/boot/initrd-2.6.18-128.1.6.el5.img  /boot/initrd-2.6.18-128.el5.img

这表示 2.6.18-128.1.6.el5 是最新版的内核。创建一个新的 initrd……

mkinitrd -f /boot/initrd-2.6.18-128.1.6.el5.img 2.6.18-128.1.6.el5

返回修复模式……

exit

4.5. 清理

在重新开机前,先将系统撤消到未挂载的状况。这样会告诉系统是时候写入任何留在高速缓冲内的改动。

umount /mnt/root.new/selinux
umount /mnt/root.new/sys
umount /mnt/root.new/dev
umount /mnt/root.new/proc
umount /mnt/root.new/boot
umount /mnt/root.new
umount /mnt/boot.old
umount /mnt/root.old

5. 利用新设备开机

我们现在已经准备好测试我们的单硬盘 RAID 1 系统。我们并没有对现有的设备作出任何改动,因此我们可以忽略我们所做的一切事情,并以现有的设备重新开机。

5.1. 移动设备

我们已经干净俐落地卸除了我们的存储设备,因此我们可以简单切断系统电源,又或者使用这个指令……

exit

它会令系统重新引导。由于我们在下一步需要系统是关闭的,当它完成关机准备重新引导时,请关闭它并切断电源。

将第二个存储设备连接到首个界面上。在我们的测试中,请勿连接原有设备。请在 BIOS 中为硬件改动更新设置。

5.2. 测试系统

删除修复媒体并打开系统。它应该能如同未作出改动般引导。

登录、进到命令行、并输入以下指令来检查我们有否应用 RAID 装罝……

mount

我们应该获得类似这样的输出……

/dev/mapper/RaidSys-Root on / type ext3 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
/dev/md0 on /boot type ext3 (rw)
tmpfs on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)

重要的部份是 /dev/mapper/RaidSys-Root on / type ext3 (rw)/dev/md0 on /boot type ext3 (rw)。我们的系统现已应用 RAID/LVM。

6. 扩展 RAID 分区至第二个设备

我们已经有一台运作中的单碟 RAID 1 系统。这个系统已被检查过能正常运作,而并证实藏有数据。这个系统已经准备好扩展为一个多碟 RAID 1 系统。

由这点开始,原有的存储设备将会被修改。这小心确定新的 RAID 系统的确能正常运作。

你可以选择于系统运作的同时扩展到第二个设备。除了较复杂之外,没有其它理由阻止你这样做。

6.1. 重新安装原先/第二个设备

关闭系统并安装原先的设备,将它连接在第二个界面上,作为附屬件。

6.2. 用修复媒体开机

执行早前引导修复模式部份内的指令。

6.3. 启用 RAID 设备

安装媒体并不包含缺省的 mdadm.conf 档,因此你需要创建它。一个简单的方法是……

mdadm --examine --scan > /etc/mdadm.conf

接着,启用所有被检测到的 RAID 设备……

mdadm --assemble --scan

6.4. 转换第二个设备上的分区

我们需要设置第二个设备存储设备,好让它能与配合其它 RAID 设备。通过 fdisk,先删除旧的分区,然后创建新的……

fdisk /dev/sdb

d 及 Enter,然后 2 及 Enter 来删除第二个分区,。

d 及 Enter 来删除首个分区。

n 及 Enter 来创建新的 /boot 分区。按 p 及 Enter 来选择主分区。接 1 及 Enter 来选择首个分区。按 Enter 来选择新分区在设备的头开始。输入 +100M 及按 Enter 来限制新分区的尺寸为 100M。按 t 及 Enter,接着输入 fd 及按 Enter 来更改 /boot 分区的类型。

n 及 Enter 来创建别一个分区。按 p 及 Enter 来选择主分区。按 2 及 Enter 来选择第二个分区。按 Enter 来选择新分区由可用的空间的起首开始。按 Enter 来使用设备上余下的空间。按 t、Enter、2 及 Enter 来选择更改第二个分区的类型,接着输入 fd 及按 Enter 来选择。

p 及 Enter 来显示分区的设置,以便检查。

w 及 Enter 将新的分区表写进设备内。

The number of cylinders for this disk is set to 30394.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): d
Partition number (1-4): 2
Command (m for help): d
Selected partition 1

Command (m for help): n

Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-30394, default 1): 
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-30394, default 30394): +100M

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): fd
Changed system type of partition 1 to fd (Linux raid autodetect)

Command (m for help): n

Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (14-30394, default 14): 
Using default value 14
Last cylinder or +size or +sizeM or +sizeK (14-30394, default 30394): 
Using default value 30394

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): fd
Changed system type of partition 2 to fd (Linux raid autodetect)

Command (m for help): p

Disk /dev/sdb: 250.0 GB, 250000000000 bytes
255 heads, 63 sectors/track, 30394 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1          13      104391   fd  Linux raid autodetect
/dev/sdb2              14       30394   244035382+  fd  Linux raid autodetect

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

6.5. 扩展 RAID 的 /boot 分区至第二个设备

要查看 RAID 现时的状态……

cat /proc/mdstat

系统返回的应该类似……

Personalities : [raid0] [raid1] [raid6] [raid5] [raid4] 
md1 : active raid1 sda2[0]
      244035264 blocks [2/1] [U_]
      
md0 : active raid1 sda1[0]
      104320 blocks [2/1] [U_]
      
unused devices: <none>

6.5.1. 加入第二个 /boot 分区至 RAID 设备

利用 mdadm 将第二个设备上的首个分区加进头一个 RAID 设备内

mdadm /dev/md0 -a /dev/sdb1

6.5.2. 检查 RAID 的 /boot 设备

我们想检查第二个设备是否已被加入……

cat /proc/mdstat

它应该返回……

Personalities : [raid0] [raid1] [raid6] [raid5] [raid4] 
md1 : active raid1 sda2[0]
      244035264 blocks [2/1] [U_]
      
md0 : active raid1 sdb1[1] sda1[0]
      104320 blocks [2/2] [UU]
      
unused devices: <none>

留意 md0 现在有两个使用中的设备 [UU]

6.6. 扩展 RAID 的 / 分区至第二个设备

6.6.1. 加入第二个 / 分区至 RAID 设备

同样地针对 /boot……

mdadm /dev/md1 -a /dev/sdb2

6.6.2. 检查 RAID 的 / 设备

加入第二个设备到 md1 后,立即执行……

cat /proc/mdstat

它应该返回……

Personalities : [raid0] [raid1] [raid6] [raid5] [raid4] 
md1 : active raid1 sdb2[2] sda2[0]
      244035264 blocks [2/1] [U_]
      [>....................]  recovery =  0.1% (254976/244035264) finish=63.7min speed=63744K/sec
      
md0 : active raid1 sdb1[1] sda1[0]
      104320 blocks [2/2] [UU]
      
unused devices: <none>

这是一个较大的分区,因此需较长时间来同步。估计的完成时间是 63.7 分钟。

一旦 md1 完成同步,cat /proc/mdstat 应该返回……

Personalities : [raid0] [raid1] [raid6] [raid5] [raid4] 
md1 : active raid1 sdb2[1] sda2[0]
      244035264 blocks [2/2] [UU]
      
md0 : active raid1 sdb1[1] sda1[0]
      104320 blocks [2/2] [UU]
      
unused devices: <none>

我们推荐完成同步后才重新开机。

6.7. 在第二个设备上安装 grub

令第二个设备可以用来开机……

grub
root (hd1,0)
setup (hd1)
quit

6.8. 重新引导完整的 RAID 1 系统

要离开修复模式,请输入……

exit

如果需要的话,请亦删除所有安装媒体。

7. 总结

整个程序现在已经完成,而且系统应该能够运作。

8. 更多阅读

CentOS 5 文档部署指南Chapter 4. Redundant Array of Independent Disks (RAID)

CentOS 5 文档LVM 管理指引Chapter 2. LVM Components

mdadm、lvm 的指令说明


本页的英文版本由 Ed Heron 创建。

Translation of revision 37

zh/HowTos/CentOS5ConvertToRAID (last edited 2019-12-09 09:11:22 by anonymous)