什么是 BCP,用于在不使用硬件 RAID 的情况下使 EFI 系统分区冗余?
如果我在不同的设备上创建 3x EFI 系统分区,然后将对主设备(安装在/boot/efi
)所做的任何更改备份到备份设备(安装在/boot/efi-[bc]
):
- 如果主设备出现故障,系统是否还能启动?即,系统是否会选择其中一个备份 EFI 系统分区?
- 系统启动时是否会确定性地选择一个 EFI 系统分区,也就是说,在下次重新启动之前是否必须在备份上复制对主分区的更改?
有没有更好的方法,使得主设备出现故障时系统仍能启动?
答案1
- UEFI 规范缺乏有关软件 RAID 的任何知识。这是已知的缺陷。
我猜测可能是因为它很大程度上受到了微软人员的影响,他们无法在 Windows 中创建可靠的软件 RAID 阵列,而且他们不知道可以使用没有特殊内部结构的简单超级块来创建分区阵列(Windows 只能使用转换为“动态”逻辑磁盘管理器或存储空间格式的磁盘构建阵列)。
- 您可以在不同的设备上制作多个 ESP,并手动同步它们。
例如,如果您在 ZFS“软件 RAID”上安装 Proxmox VE,它将创建多个 ESP,并安装在内核、引导加载程序和其他引导相关内容更新后运行的特殊“钩子”,该钩子确保所有 ESP 保持同步。
您还可以添加 Grub 钩子以将其安装在两个 ESP 上,如中所述这个答案:
创建包含以下内容的文件/etc/grub.d/90_copy_to_boot_efi2
并使其可执行:
#!/bin/sh
set -e
if mountpoint -q /boot/efi && mountpoint -q /boot/efi2 ; then
rsync -t --recursive --delete /boot/efi/ /boot/efi2/
fi
exit 0
然后,每当你或系统运行时,update-grub
它都会运行这个脚本。还要注意,这个脚本有点发生灾害时很危险;如果主设备包含/boot/efi
发生故障并被替换此脚本将删除有效内容来自 /boot/efi2。因此在这种情况下,您需要禁用它(删除可执行位),或者在运行 rsync 之前检查钩子中的源条件。
- 如果主设备发生故障,为了使备用 ESP 能够接管,您应该为所有 ESP 设置 UEFI 启动项。在 Linux 中,操作如下:
efibootmgr -c -d /dev/sdb -l \\EFI\\DEBIAN\\GRUBX64.EFI -L debian-sdb
efibootmgr -c -d /dev/sdc -l \\EFI\\DEBIAN\\GRUBX64.EFI -L debian-sdc
efibootmgr -c -d /dev/sdd -l \\EFI\\DEBIAN\\GRUBX64.EFI -L debian-sdd
efibootmgr -c -d /dev/sda -l \\EFI\\DEBIAN\\GRUBX64.EFI -L debian-sda
这是我的一个受管系统的真实示例。它假设 ESP 是每个磁盘的第一个分区。这应该在同步 ESP 的内容后完成。efibootmgr -v
将确认您以这种方式创建的所有启动项都使用不同的设备。
也可以看看:https://askubuntu.com/questions/66637/can-the-efi-system-partition-be-raided
答案2
EFI 分区的内容应该相对稳定,因此在更新后手动将更改克隆到其他磁盘上的其他副本应该没问题。即使没有克隆更改,旧副本也可能没问题,只要它们没有太多修订。
系统是否会从备用 EFI 启动?这是一个比较难的问题。大多数现代 BIOS 版本都支持多个启动设备,并且可能会按顺序尝试所有启动设备,直到其中一个启动成功。因此,您只需确保它们都在那里并且顺序正确即可。您可能需要手动运行 linux 命令来更新 EFI 引导加载程序列表和顺序。
但是,最好不要在发生故障时自动启动。如果主 EFI 磁盘发生故障,您可能还是想手动启动并尝试修复。但即使备份 EFI 不在启动顺序中,它也能使恢复变得容易得多。
另一种观点是——如果 RAID 系统中的磁盘即将发生故障,则系统启动时该磁盘很可能也会发生故障。如果您在下次启动之前检测到这种情况,则可以轻松激活其中一个备份 EFI 副本(甚至可以将其设为主副本),直到故障磁盘被替换。
答案3
每个系统都会在指定的启动设备上搜索 EFI 分区。只要这些分区更新正确,系统就应该能够启动。除此之外,分布式启动管理器当然是另一回事了。
我已经创建了一个要点来查看 systemd 环境中的设置,该设置将在系统关闭时同步所有这些分区:
https://gist.github.com/thhart/35f6e4e715c70c2cbe7c5846311d1f9f