不可变Debian

目录

1. 什么是不可变?

根文件系统不可变的代称。

传统的发行版会采用可变的根文件系统,如果用户尤其是根用户可以随意的修改几乎所有的 文件。而把根目录设置为不可变的即只读的存储可以保证如果系统是可以运行的,那么系统 会一直保持可运行的状态。不可能会有任何修改操作改变系统运行的条件从而让系统崩溃。

同时不可变系统的更新也是基于其不可变的特性来实现的。每一次更新就是基于当前正在运 行的系统重新构建一个全新的系统映像,原来的系统并没有被直接的销毁,而是被保存下来, 随时准备着回滚。

也正因此,不可变操作系统的更新是“原子的”。意为“一次更新就像一个不可被打破的原 子操作一样”。更新只有成功和失败。

基于以上的特性,不可变操作系统具有强大的恢复能力,容灾能力。比如,如果某一次更新 出现了破坏性更新,你在不知情的情况下下载并安装了这个软件。之后许多服务跑不起来, 这时就可以使用不可变操作系统对每次更新创建的之前的映像来回滚到上一次可以运行的系 统版本。

当然Debian作为一个老牌发行版,其无法支撑我们对它的基本结构大动手脚,但是我们至少 可以部署一个以安装软件包为触发事件的备份系统,四舍五入是具有稳定性的,可以在出现 破坏性更新的时候快速回滚至可运行的状态。

2. 需要使用什么软件?

在我的实践中,只需要这么几个就可以:

  • Btrfs
  • snapper
  • systemd-boot

通过这三个软件配合,btrfs负责提供基础的子卷功能,snapper负责调用子卷功能并使用此 功能管理快照,而systemd-boot负责的是,和以上两个功能搭配,提供快照切换的能力。

2.1. Btrfs相关设置

这一部分相对来说没有什么可讲的,只有纯粹的麻烦。

简单来说就是创建7个子卷:

  • @
  • @home
  • @var
  • @opt
  • @root
  • @srv
  • @local

并使用,并在 @ 子卷中创建一个 @/persis 目录,这个目录是用来存放希望跟随根目 录回滚但并没有包含在根目录的特殊文件的。

例如: var 目录中有一个特殊目录, /var/lib/dpkg ,这个目录是Debian的包管理器 dpkg的缓存目录,如果这个目录不跟随主目录发生变化,就会出现dpkg认为一个软件已经安 装了,但是这个软件跟随主目录回滚而消失,导致dpkg的缓存滞后从而出现问题的情况。

针对例子中的问题,我的解决方式是,创建 /persis/dpkg 并使用 mount -o bind 来 将两个目录连接起来,并在 /etc/fstab 中建立一个配置条目来实现自动挂载。这样就可 以实现dpkg和系统状态的同步了。

2.2. snapper

这个工具主要是创建并管理快照,只需要安装并创建针对根子卷的配置即可,而且由于 Debian的钩子脚本设置,snapper还可以自动的在安装软件前后创建快照。保证相当的安全 性。

2.3. systemd-boot

主要就是针对内核启动命令行的设置,使用systemd-boot启动系统的同学需要在 /etc/kernel/cmdline 文件中给出具体的参数,包括两个,一个是需要挂载哪个分区作为 根目录,另一个就是挂载文件系统时使用的选项,务必要留空 subvolsubvolid 这 两个选项。

3. 其他的问题

至于为什么不使用GRUB启动管理器,因为Debian的GRUB软件包会将启动参数通过脚本构建出 来,参数中挂载的子卷是精确到子卷编号的,而这和snapper的工作原理相冲突。

snapper的快照构建方式是:对当前的根目录进行复制,复制到一个新的子卷,这个子卷就 是当前的系统的快照,而如果需要恢复到之前的状态,需要把默认子卷设定到这个子卷。所 谓默认子卷,就是在没有参数的时候直接挂载时默认挂载的子卷。而GRUB把子卷精确到编号 的做法导致默认子卷的设置无法生效,自然就无法切换到快照。

以上就是为什么不使用GRUB。

希望这篇文章可以帮助同学们更好地管理系统。

日期: 2026-07-16 四 00:00

作者: 维修部部长

Created: 2026-09-12 六 15:59