x86_64 Linux A/B 系统设计:从 GRUB 选槽到 OverlayFS 根文件系统

1. 设计目标与启动全貌 设备在线升级时,写入镜像只是其中一步。更新可能在断电时中止,新内核可能无法挂载根目录,业务也可能在系统启动后才暴露问题。A/B 设计的目标,是在候选版本尚未被确认时保留一套可启动的旧系统,并为失败后的重启指定明确的去向。 本文面向熟悉 Linux 分区、挂载与 systemd 的读者,讨论 Legacy BIOS + GPT 的 x86_64 设备:GRUB 2 选择启动槽位,自定义 BusyBox initramfs 组装根文件系统,systemd 启动主系统并组织健康检查。RootFS 使用只读 SquashFS,运行时写入由持久化的 OverlayFS 可写层(upper)承接。 这是一篇架构设计与关键机制说明:给出分区约定、状态转换、挂载顺序和验收条件。GRUB 选槽使用伪代码,/init 展示核心片段;完整部署还需实现错误分支、升级程序、超时监督和恢复环境。文中没有提供目标硬件实测记录,因此不据此宣称已经达到生产级可靠性。 设计遵循三个约定: 成套更新:一个槽位包含匹配的 kernel、initramfs 和 RootFS,始终一起选择、一起升级。 保留回退对象:当前运行槽与已确认的稳定槽一致时,才允许更新另一槽;候选版本经过健康检查后才成为默认版本。 分离系统与数据:系统基线保存在 SquashFS;系统写入进入槽位独立的可写层;需要跨版本保留的业务数据单独存放。 选择 SquashFS,是为了把系统基线做成可整体校验、替换的只读镜像;选择 OverlayFS,是为了兼容需要可写根目录的软件。代价是 upper 会保存偏离基线的内容,必须与镜像版本一起管理。普通重启不会恢复出厂状态;本文也不覆盖纯 UEFI 启动、磁盘冗余或完整的可信启动链。 设备上电 → BIOS 自检、初始化启动所需硬件,选择磁盘 → 执行磁盘 LBA 0(保护性 MBR)中的 GRUB 引导代码 → 加载 p1 内嵌的 GRUB core.img,访问 p2 的模块与 grub.cfg → grub.cfg 读取启动状态,选择 A/B,将该槽 kernel 和 initramfs 装入内存 → GRUB 按 Linux 启动协议传参并跳转到内核入口 → kernel 解压、初始化内存和驱动,将 initramfs 解包到初始根文件系统 → 执行 initramfs 中的 /init(PID 1,本文为 BusyBox shell 脚本) → /init 挂载 SquashFS 和 DATA,再挂载 OverlayFS 到 /newroot → exec switch_root /newroot /sbin/init → systemd 接管 PID 1,按依赖启动服务,开放登录或业务接口 → 独立健康检查通过后,才确认试启动版本 initramfs 是文件系统归档,不是独立执行的程序;OverlayFS 是内核文件系统,由早期用户态请求挂载。 /init 与 systemd 属于同一个内核下的前后两个用户态阶段,切根不会重新启动内核。若改用 systemd 构建 initramfs,它会更早成为 PID 1,并通过 systemctl switch-root 交接,不能原样套用本文的 BusyBox 脚本。两种方式见 systemd initrd 接口。 ...

September 14, 2026 · 9 min · zhumouren