使用 LVM 将 MBR/BIOS RAID 1 根分区迁移到 GPT/UEFI

使用 LVM 将 MBR/BIOS RAID 1 根分区迁移到 GPT/UEFI

我已经思考了一段时间,并搜索了各种帖子,但找不到与我的情况相符的内容。

我目前在 RAID 1 中的几块 SSD 上运行 18.04.3 LTS(以及在一堆 HDD 上带有 LVM 的单独数据 RAID 6)。几年前我设置了这个(当时使用 14.04 LTS),当时我的主板仅支持 MBR/BIOS。

从那时起,我已将主板升级为支持 UEFI 的主板。现在我正准备升级 SSD(更大的 M.2 单元)。

我一直在考虑:除了维持当前设置并更换 SSD 之外,我还在考虑:

  • 将设置更改为 GPT/UEFI,以及
  • 在 RAID 1 上安装 LVM。

我正在尝试找出实现上述任一或两项操作的最佳方法。我曾考虑过在新的 SSD 上进行全新安装(这种方法很有吸引力,可以摆脱多年来积累的垃圾),但一想到要重新配置所有内容(有很多……),我就不寒而栗。

还有其他方法吗?

关于迁移到 GPT/UEFI,我研究过这样做的可能性就地类似于Boot-Repair。我考虑的另一个选择是使用我想要的方案对新 SSD 进行分区(简单的 EFI 启动分区和根分区),然后依次将它们引入阵列 - 有点像

但是我不完全清楚这两种方法是否可行,例如是否可以Boot-Repair在不破坏数据的情况下修改实时系统(并且是否会在磁盘启动时插入 EFI 启动分区mdadm),以及如果我不重新安装操作系统,如何在手动创建的 EFI 启动分区上安装 EFI 引导加载程序?

至于在现有 RAID 1 上安装 LVM 的问题,我正在努力思考如何实现。

一些当前设置(就相关而言 - 我已经删除了多余的信息)以供进一步了解:

$ cat /proc/mdstat

md1 : active raid1 sdg5[2] sdh5[3]
      16757632 blocks super 1.2 [2/2] [UU]
      
md0 : active raid1 sdg1[2] sdh1[3]
      100386688 blocks super 1.2 [2/2] [UU]

和:

$ sudo fdisk -l

Disk /dev/sdg: 111.8 GiB, 120034123776 bytes, 234441648 sectors                                                                                                                                         
Units: sectors of 1 * 512 = 512 bytes                                                                                                                                                                   
Sector size (logical/physical): 512 bytes / 512 bytes                                                                                                                                                   
I/O size (minimum/optimal): 512 bytes / 512 bytes                                                                                                                                                       
Disklabel type: dos                                                                                                                                                                                     
Disk identifier: 0x0001cb75                                                                                                                                                                             
                                                                                                                                                                                                        
Device     Boot     Start       End   Sectors  Size Id Type                                                                                                                                             
/dev/sdg1  *         2048 200906751 200904704 95.8G fd Linux RAID autodetect                                                                                                                            
/dev/sdg2       200908798 234440703  33531906   16G  5 Extended                                                                                                                                         
/dev/sdg5       200908800 234440703  33531904   16G fd Linux RAID autodetect                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                   
Disk /dev/sdh: 111.8 GiB, 120034123776 bytes, 234441648 sectors                                                                                                                                         
Units: sectors of 1 * 512 = 512 bytes                                                                                                                                                                   
Sector size (logical/physical): 512 bytes / 512 bytes                                                                                                                                                   
I/O size (minimum/optimal): 512 bytes / 512 bytes                                                                                                                                                       
Disklabel type: dos
Disklabel type: dos                                                                                                                                                                                     
Disk identifier: 0x0001cb75

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sdh1  *         2048 200906751 200904704 95.8G fd Linux RAID autodetect
/dev/sdh2       200908798 234440703  33531906   16G  5 Extended
/dev/sdh5       200908800 234440703  33531904   16G fd Linux RAID autodetect

/dev/md0安装在根目录(ext4)上,并被/dev/md1分配为交换分区。

如果我能够将系统转换为 LVM,我会取消物理交换分区,只创建一个 LVM 交换分区。我认为这也可能有助于迁移过程,因为它会释放当前 SSD 上的一些空间。

有什么想法吗?谢谢。

答案1

好吧,尽管尝试了几次,我还是设法完成了这次迁移。

方法总结

我最终没有采用我最初考虑的任何方法。相反,我的方法包括:

  • 在新的 SSD 上创建新的分区方案(EFI 启动分区加上根分区)
  • 在 EFI 启动分区上安装 UEFI 引导加载程序
  • 在根分区上创建 RAID 1 阵列
  • 使用 RAID 1 阵列创建 LVM 物理卷,并使用该卷创建 LVM 卷组
  • 在该卷组上创建 LVM 根逻辑卷
  • 将根分区的内容从旧 SSD 复制到新 SSD
  • 在 RAID 1 阵列上的卷组上创建 LVM 交换逻辑卷
  • 整理

我的第一次尝试是手动创建分区并在这些分区上手动安装 UEFI 引导加载程序。经过几次小失误后,最终在新的 SSD 上获得了可启动的系统,但使用了错误的引导加载程序(后备BOOTX64.EFI而不是 Ubuntugrubx64.efishimx64.efi引导加载程序)。

我可能可以通过执行下面的第 27 步来解决这个问题,但这是我在第二次尝试时才发现的。但现在请看这个答案的附录。

所以我重新开始了整个过程。

第二次尝试是使用 Ubuntu Live USB 在新的 SSD 之一上执行全新安装(使用我的新分区方案,但没有 RAID 或 LVM)。我认为这将为我提供一个反映 Ubuntu 默认设置(大小、内容)的 EFI 启动分区。

这种方法还使我有机会注意到默认安装包含哪些参数/etc/fstab,以便我可以在我的新安装上正确地复制这些参数。

Ubuntu Live USB 完成默认安装后,我将 EFI 启动分区复制到另一个 SSD。然后,我删除了已安装的根分区并将其替换为新分区,以擦除已安装的操作系统。然后,我将该分区复制到另一个 SSD 上,并继续执行其余步骤(创建 RAID 阵列等)。

正如您所看到的,这导致系统最初无法启动,但我设法将其挽救回来,grub现在一切都正常。

请继续阅读详细步骤。我必须承认,在某种程度上,这些步骤是我所做工作的重构,因为在此过程中我做了一些小改动,但从根本上讲,我下面概述的内容准确反映了我所做工作的实质。

参考

在准备和实施我的两次尝试时,我参考了一些教程,特别是:

没有一个完全符合我的用例,并且概述的一些步骤实际上给我带来了问题,但它们确实在各个方面提供了帮助。

所有细节

设置场景:

  • 我安装的是 Ubuntu 18.04.3 LTS
  • 我的旧安装已打开/dev/md0,并打开了交换分区/dev/md1,均在我的旧 SSD 上
  • 我在单独的 HDD 上还有一个 RAID 6 数据阵列 ( /dev/md2),我想在新安装时保留它们
  • 我的新 SSD/dev/nvme0n1/dev/nvme1n1

现在来看看步骤:

步骤1

我实际上并没有执行这第一步,但事后看来,它可能有所帮助。它涉及准备我的旧 Ubuntu 安装(我最终会复制的那个),安装一些在 UEFI 下运行时需要的软件包。因此,当启动到我的旧安装时:

$ sudo apt-get update
$ sudo apt-get install grub-efi-amd64 efibootmgr

第2步

在继续操作之前,我禁用了旧安装上的交换分区,只是为了避免在复制根分区内容时保留任何旧设置。我不确定这是否会是一个实际问题,但想确定一下:

$ sudo swapoff /dev/md1

然后我/etc/fstab在我最喜欢的文本编辑器中更新以注释掉交换条目,然后:

$ sudo mount -a

步骤3

然后我以 UEFI 模式启动 Ubuntu Live USB(桌面版,而不是服务器版,尽管我安装的是服务器版),并选择“安装 Ubuntu”。您可能需要调整主板固件设置以确保以 UEFI 模式启动。

我想我也可以使用服务器版本来完成这一步,但考虑到我需要桌面版本来完成后面的步骤,我决定保持简单。

我选择了引导式安装,选择使用我的第一个新 SSD(/dev/nvme0n1)并使用整个驱动器进行安装。我没有设置 RAID 或 LVM。这导致 (a) 一个 EFI 启动分区,以及 (b) 一个根分区,占用了驱动器的其余部分,Ubuntu Desktop 安装在该分区上。

步骤4

完成后,我以 UEFI 模式重新启动进入 Ubuntu Live USB,这次选择“尝试不安装 Ubuntu”。您可以通过打开终端(Ctrl-Alt-T)并运行来测试您是否处于 UEFI 模式:

$ ls /sys/firmware/efi

如果显示多个文件,则表示您处于 UEFI 模式。

步骤5

在终端提示符下,我升级了 Ubuntu Live 并安装了所需的软件包:

$ sudo apt-get update && sudo apt-get dist-upgrade
$ sudo apt-get install -y mdadm

第 6 步

然后,我检查了新安装的分区方案,以便可以正确地将其复制到另一个 SSD 上:

$ sudo parted /dev/nvme0n1
(parted) unit MiB print
Model: Samsung SSD 970 EVO Plus 500GB (nvme)
Disk /dev/nvme0n1: 476940MiB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start    End        Size       File system  Name                  Flags
 1      1.00MiB  513MiB     512MiB     fat32        EFI System Partition  boot, esp
 2      513MiB   476939MiB  476426MiB  ext4         

(parted) quit

这表明默认的 EFI 分区大小为 512 MiB,从驱动器开头 1 MiB 开始,采用 FAT32 文件系统。

步骤7

然后,我还检查了默认挂载参数/etc/fstab(下面的 UUID 被屏蔽为“NUMBER”):

$ sudo mkdir -p /mnt/newroot
$ sudo mount /dev/nvme0n1p2 /mnt/newroot
$ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
## / was on /dev/nvme0n1p2 during installation

UUID=NUMBER /               ext4    errors=remount-ro 0       1

# /boot/efi was on /dev/nvme0n1p1 during installation

UUID=NUMBER  /boot/efi       vfat    umask=0077      0       1

/swapfile                                 none            swap    sw              0       0

$ sudo umount /mnt/newroot

我记下了这些参数,以便稍后可以复制它们。

步骤8

然后,我删除了第一个 SSD 上已安装的根分区,以删除桌面安装,并在其位置创建一个新分区(大小相同)。请注意,我没有使用任何文件系统类型创建它,因为 RAID 阵列和 LVM 卷组将覆盖在上面:

$ sudo parted -a optimal /dev/nvme0n1
(parted) rm
Partition number? 2
(parted) mkpart primary 513MiB 100%
(parted) name 2 "Ubuntu Filesystem"
(parted) align-check optimal 2
(parted) set 2 raid on

步骤9

当仍然处于 parted 交互式提示中时,我选择了另一个新的 SSD(/dev/nvme1n1)来复制分区方案:

(parted) select /dev/nvme1n1
(parted) mklabel gpt
(parted) mkpart primary fat32 1MiB 513MiB
(parted) set 1 esp on
(parted) set 1 boot on
(parted) mkpart primary 513MiB 100%
(parted) name 2 "Ubuntu Filesystem"
(parted) align-check optimal 2
(parted) set 2 raid on
(parted) unit MiB print
Model: Samsung SSD 970 EVO Plus 500GB (nvme)
Disk /dev/nvme1n1: 476940MiB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start    End        Size       File system  Name                  Flags
 1      1.00MiB  513MiB     512MiB     fat32        EFI System Partition  boot, esp
 2      513MiB   476939MiB  476426MiB  ext4         Ubuntu Filesystem     raid

(parted) quit

第 10 步

然后我在根分区上创建了一个 RAID 1 阵列,/dev/nvme0n1p2并且/dev/nvme1n1p2。我将其命名/dev/md3为 ,以区别于我的旧系统下已经创建的 RAID 阵列,并避免在迁移过程中发生命名冲突,目的是在新系统启动并运行时稍后重命名它:

$ sudo mdadm --create --bitmap=internal /dev/md3 --level=1 --raid-devices=2 /dev/nvme0n1p2 /dev/nvme1n1p2

我等到 RAID 阵列完成同步后再继续,通过检查:

$ cat /proc/mdstat

步骤11

然后,我在 RAID 1 阵列之外创建了一个 LVM 物理卷,并vgmain使用该物理卷创建了一个卷组(称为),然后在该卷组上创建了一个 LVM 根逻辑卷(称为lvroot和 ,大小为 100 GiB):

$ sudo pvcreate /dev/md3
$ sudo vgcreate vgmain /dev/md3
$ sudo lvcreate -L 100G -n lvroot vgmain

步骤12

然后我在根逻辑卷上创建了一个 EXT4 文件系统:

$ sudo mkfs.ext4 -b 4096 -E stride=128,stripe-width=256 /dev/vgmain/lvroot

步骤13

此时,我组装了旧的 RAID 设备,以便我的旧根分区 ( /dev/md0) 可用于复制数据。显然,要做到这一点,我的旧 SSD 仍然必须连接并通电:

$ sudo mdadm --assemble --scan

步骤14

组装完成后,我安装了旧的根分区:

$ sudo mkdir -p /mnt/oldroot
$ sudo mount /dev/md0 /mnt/oldroot

步骤15

我还挂载了新的根分区(记住挂载点之前已在步骤 7 中创建):

$ sudo mount /dev/vgmain/lvroot /mnt/newroot

步骤16

现在我可以将旧根分区的内容复制到新分区:

$ sudo rsync -axHAX --progress /mnt/oldroot/ /mnt/newroot

步骤17

一旦完成后,就可以卸载旧的根分区并停止旧的 RAID 阵列:

$ sudo umount /mnt/oldroot
$ sudo mdadm --stop /dev/md0

步骤18

现在说点题外话。事后看来,如果我当时执行了第 27 步,我最后遇到的启动问题可能就可以避免。为此,我会执行以下操作:

$ sudo mkdir -p /mnt/newroot/boot/efi
$ sudo mount /dev/nvme0n1p1 /mnt/newroot/boot/efi
$ for d in /dev /dev/pts /sys /proc; do sudo mount -B $d /mnt/newroot$d; done
$ sudo chroot /mnt/newroot
# grub-install
# update-grub
# umount /dev/nvme0n1p1

我不确定这是否能解决后来遇到的问题,但问题已经解决了。但现在请看这个答案的附录。

步骤19

回到我实际做的事情。将旧根分区的内容复制到新根分区(当然,在 RAID 1 阵列中是镜像的)后,我需要将 EFI 启动分区的内容从第一个 SSD 复制到第二个 SSD:

$ sudo dd if=/dev/nvme0n1p1 of=/dev/nvme1n1p1

为了检查这是否成功,我检查了完成后每个上的 UUID 是否相同:

$ sudo blkid

步骤20

为了完整性,我还想将第二个 SSD 放入启动链中,以确保我可以从任一 SSD 顺利启动。此时,新的根分区仍处于挂载状态,但我还需要从 Ubuntu Live USB 挂载其他目录(如果我实施了第 18 步,我就不必在这里挂载这些目录了):

$ for d in /dev /dev/pts /sys /proc; do sudo mount -B $d /mnt/newroot$d; done
$ sudo chroot /mnt/newroot
# efibootmgr -v

## Comment: The above command showed me the file entry for "ubuntu", which in my case was
## \EFI\ubuntu\grubx64.efi (I could have also used \EFI\ubuntu\shimx64.efi).
## I then used that in the next command

# efibootmgr -c -d /dev/nvme1n1 -p 1 -L ubuntu -l '\EFI\ubuntu\grubx64.efi'

显然,对新 SSD 的影响chroot是,我进入该环境就像启动它一样,因此我在 jail 中运行的命令是在 SSD 上执行的,而不是在 Ubuntu Live USB 上执行的。在 jail 中chroot,命令以 root 身份运行(如“#”提示符所示),因此sudo不需要。当然,鉴于 SSD 实际上并未启动,我必须从 Ubuntu Live USB 安装一些关键目录才能获得所需的功能。

(顺便说一句,我必须指出,由于我实际上没有完成第 1 步,当我尝试运行时,efibootmgr我发现它没有安装,因为我已经复制了我的旧安装,即 MBR/BIOS 安装。所以我必须在此阶段安装它。为此,我发现我还需要/run从 Ubuntu Live USB 安装,以便我可以访问互联网。我还安装了grub-efi-amd64。)

步骤21

我还通过检查 返回的详细信息检查了启动顺序是否正确,即/dev/nvme0n1p1启动链中的第一个是哪个,第二个是哪个。如有必要,可以通过按要求的顺序运行以下命令并使用每个相关磁盘或分区的 4 位代码来修复顺序,例如:/dev/nvme1n1p1efibootmgr -v

# efibootmgr -o 0000,0001,0002,0005,0004

步骤22

然后,我/etc/fstab用我最喜欢的文本编辑器进行了更新,以包含根挂载点和/boot/efi挂载点(从中确定blkid)的新 UUID。我使用了步骤 7 中的参数,添加noatime到根挂载点(与我的旧安装一致)。

当然,我保留了旧数据 RAID 6 阵列的挂载点条目,因为它将继续用于新安装,以及固定挂载点/tmp

步骤23

新 SSD 上的 mdadm 配置详细信息也需要更新,我通过/dev/md3以下命令添加新阵列的详细信息,然后/etc/mdadm/mdadm.conf使用文本编辑器手动编辑以确保删除旧的遗留/dev/md0条目/dev/md1

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

清理配置文件后,我运行:

# update-initramfs -u

步骤24

此时我基本上已经完成了(或者我是这么认为的)。因此,为了干净利落地完成,我退出chroot并卸载了所有内容:

# exit
$ for d in /dev /dev/pts /sys /proc; do sudo umount /mnt/newroot$d; done
$ sudo umount /mnt/newroot

步骤25

最后,关键时刻到了——我移除了 Ubuntu Live USB,然后重启了系统,检查主板固件,发现启动顺序中第一个新 SSD 位于最顶部,这样我就可以从 启动了/dev/nvme0n1p1。如有必要,您可以在启动时通过运行 来检查从哪个驱动器启动efibootmgr -v

步骤26

不过,此时,我遇到了启动问题。系统无法启动,并在提示符处停止grub。为了解决这个问题,我在提示符下执行以下操作:

grub> ls

## Comment: The above command showed me the available partitions and directories, so I knew
## what my root partition was called and could use it in the next command

grub> set root=(lvm/vgmain-lvroot)
grub> linux /vmlinuz root=/dev/mapper/vgmain-lvroot
grub> initrd /initrd.img
grub> boot

步骤27

执行此操作后,我启动了新的 SSD。此时,我运行了以下命令,如果我在第 18 步执行了这些操作,则可能不需要执行这些操作:

$ sudo grub-install
$ sudo update-grub

我发现运行这些命令后, 的大小grubx64.efi发生/boot/efi/EFI/ubuntu了变化,因此看起来原始引导加载程序安装存在问题。但现在请看此答案的附录。

步骤28

然后,我重复了步骤 19 和 20 中的相关命令,将更新后的 EFI 启动分区的内容从 复制/dev/nvme0n1p1/dev/nvme1n1p1,并更新启动链。如果您发现还有需要删除的旧条目,请使用:

$ sudo efibootmgr -b 0003 -B  # Eg to delete entry Boot0003

步骤29

最后,我重新创建了交换分区,这次作为 LVM 逻辑卷:

$ sudo lvcreate -L 16G -n lvswap vgmain
$ sudo mkswap /dev/vgmain/lvswap
$ sudo swapon /dev/vgmain/lvswap

/etc/fstab使用相关UUID和步骤7中确定的参数进行更新:

UUID=NUMBER none    swap    sw  0   0

就是这样!我现在有一个完全迁移并正常运行的系统。我最终会将我的新 RAID 1 重命名为md0(仅出于强迫症原因),但那是另一回事了。

附录

第 1 项

在尝试迁移之前,我学习的准备教程说,在开始之前应该在主板固件上禁用安全启动。我没有这么做,因为我发现我的主板(华硕)很难做到这一点(后来我研究了一下,发现可以通过删除安全启动键来实现)。我的启动问题可能是由于安全启动仍然有效而引起的。

第 2 项

您会发现,在 UEFI 模式下启动迁移的系统时,它会在 grub 菜单处暂停 30 秒,然后继续。这显然是为了让用户有时间访问菜单,因为在某些情况下,否则菜单可能无法访问。如果您对启动时间的额外延迟感到烦恼,可以通过将以下内容添加到 来减少这种情况/etc/default/grub

GRUB_RECORDFAIL_TIMEOUT=5  # Eg to reduce to five seconds

不要将其减少到零。然后:

$ sudo update-grub

相关内容