5.8 ZFS 启动环境与多版本共存

本章系统介绍 ZFS 启动环境(Boot Environment,BE)的创建与管理,以及基于 pkgbase 的系统版本升级方法。ZFS 启动环境与 pkgbase 相结合,为 FreeBSD 提供了安全、灵活的系统更新与多版本共存机制,是现代 FreeBSD 系统管理的重要技术手段。

创建启动环境 15.0-RELEASE

ZFS 启动环境(Boot Environment,BE)是 FreeBSD 的一个重要特性,它允许我们在系统中创建多个独立的系统环境,从而实现不同系统版本的共存与安全切换。下面我们将创建一个名为 15.0-RELEASE 的启动环境。

  • 使用工具 bectl 创建启动环境 15.0-RELEASE

# bectl create 15.0-RELEASE

注意

我们只是将其命名为 15.0,实际上系统仍然是 14.3-RELEASE。

  • 使用 bectl 检查启动环境:

$ bectl list # 显示所有启动环境
BE           Active Mountpoint Space Created
15.0-RELEASE -      -          176K  2025-12-05 22:27
default      NR     /          10.6G 2025-01-14 20:36

Active 字段解释(来自 bectl(8) 手册页arrow-up-right):

  • “N”:表示该启动环境当前是否处于活动状态(当前是否位于此环境中)

  • “R”:在重启时是否处于活动状态(下次是否选中,用于固定选项)

  • “T”:是否会在下次启动时生效(且仅下次,用于一次性选项)

  • “NRT”:这些标识(N / R / T)理论上可以组合出现(但实际不会出现,该组合在语义上存在矛盾)

  • 列出系统中所有 ZFS 文件系统及其属性:

注意 zroot/ROOT/15.0-RELEASE 8K 83.8G 10.6G / 这一行是刚刚创建的。

将启动环境中的系统版本更新到 15.0-RELEASE

创建好启动环境后,我们需要在其中进行系统版本的更新操作。整个过程分为挂载启动环境、验证版本、转换为 pkgbase 以及升级到目标版本等步骤。

挂载启动环境 15.0-RELEASE

要对启动环境进行操作,首先需要将其挂载到文件系统中的某个目录。下面我们将创建一个临时目录并挂载启动环境。

  • 创建一个临时目录用于更新启动环境 15.0-RELEASE 中的 FreeBSD 系统

  • 将启动环境(实际上是一个数据集)15.0-RELEASE 挂载到上面的路径中

  • 显示已挂载文件系统的磁盘使用情况:

可以看到,已经成功将启动环境 15.0-RELEASE 挂载到了指定路径。

验证当前 FreeBSD 版本

目前 15.0-RELEASE 实际上仍是 14.3-RELEASE。虽然这是已知事实,但仍可使用命令 freebsd-version 进行验证。

/mnt/upgrade 环境中运行 freebsd-version

freebsd-version 参数解释(摘自手册页 freebsd-version(1)arrow-up-right):

  • -k:打印已安装内核的版本和补丁级别。与 uname(1)arrow-up-right 不同的是,如果新的内核已经安装但系统尚未重启,freebsd-version 会打印新内核的版本和补丁级别。

  • -r:打印正在运行中的内核的版本和补丁级别。与 uname(1)arrow-up-right 不同的是,freebsd-version 不受环境变量影响。

  • -u:打印已安装用户态的版本和补丁级别。这些信息在构建过程中会被写入程序 freebsd-version 中。

使用 pkgbase 将启动环境中的 14.3-RELEASE(系统版本)转换到 pkgbase

在开始升级之前,我们需要将传统的 FreeBSD 系统转换为 pkgbase 格式。pkgbase 是 FreeBSD 官方提供的一种新的基本系统打包方式,它使用 pkg 包管理器来管理系统组件。

pkgbase 的设计初衷是为了让 stable、current 和 release(包括 BETA、RC 等)都能使用统一的二进制工具进行更新。之前,stable 和 current 只能通过完整编译源代码的方式进行更新。

注意

仅 FreeBSD 14.0-RELEASE 及更高版本才能直接被转换为 pkgbase。旧版仍需要通过 freebsd-update 进行更新(运行时 pkgbasify 会提示 Unsupported FreeBSD version,即 FreeBSD 版本不受支持)。

警告

存在风险,可能会丢失所有数据!建议在操作之前做好备份。

  • 在 /mnt/upgrade 环境中锁定 pkg 软件包,防止被升级或修改:

  • 下载 pkgbase 转换脚本

  • 使用 pkgbasify 进行转换

警告

在接受 Do you accept this risk and wish to continue? (y/n) 这个风险提示后就没有其他二次确认了!

  • 检查启动环境 15.0-RELEASE 中的系统版本

可以看到,pkgbasify 已将系统更新到最新的补丁版本,并完成了向 pkgbase 的转换。

使用 pkgbase 将启动环境中的系统版本更新到 15.0-RELEASE

成功转换为 pkgbase 后,我们就可以使用 pkg 包管理器来升级系统版本了。下面我们将配置 pkgbase 源并执行升级操作。

  • 创建 pkgbase 软件源目录

  • 编辑 /mnt/upgrade/usr/local/etc/pkg/repos/FreeBSD-base.conf,添加 pkgbase 源

警告

请检查 FreeBSD-base.conf 的内容,尤其是 不应该 在里面手动硬编码写入指定任何具体的版本(如 base_release_3)。

技巧

需要换源的用户可以将 url 这行改成 url = "https://mirrors.ustc.edu.cn/freebsd-pkg/${ABI}/base_release_${VERSION_MINOR}";。而对于那些优先考虑安全性的读者应该维持默认设置。

  • 刷新软件源

  • 使用 pkgbase 将 14.3-RELEASE 更新到 15.0-RELEASE(即将 ABI 指定为 15)

技巧

如果检查不到任何更新,请检查你当前是否已成功转换为 pkgbase,并确认软件源配置是否正确

  • 检查启动环境 15.0-RELEASE 中的系统版本

这里 r 显示为 14.3-RELEASE 并无异常,说明当前运行的仍是 14.3。结合其他参数,可知重启后才会变成 15.0-RELEASE。

  • 解锁 pkg

  • 将所有第三方软件包的 ABI 更新到 FreeBSD 15.0

更新过程中需要多次确认才能完成。

启动到启动环境 15.0-RELEASE

完成所有更新操作后,我们可以尝试启动到新的启动环境中验证更新结果。

  • 在下次启动时进入启动环境 15.0-RELEASE

  • 验证设置是否成功。列出系统中所有 ZFS 启动环境:

注意,这是一次性的(T),此处仅用于验证其是否能够正常启动。我们还需要回到目前的主系统 14.3-RELEASE 来更新 ZFS。

  • 重启以进入启动环境 15.0-RELEASE

  • 验证版本:

可以看到,我们已经成功将启动环境 15.0-RELEASE 中的 FreeBSD 系统升级到了 15.0-RELEASE。现在名副其实了。

并且 R 意味着我们再次重启就会回到启动环境 default(14.3-RELEASE)。

附录:永久性使用 15.0-RELEASE

前面我们使用的是一次性启动环境的方式进行验证。如果验证通过并且不需要再保留旧版本,可以将新环境设置为永久默认。

如果读者不需要多版本共存,并且验证过目前的环境满足需要,也可以将启动环境 15.0-RELEASE 设置为永久的:

随后,读者也可以销毁不再需要的启动环境:

将参数 启动环境 替换为命令 bectl list 输出中 BE 列对应的启动环境名称即可将其销毁。

将基本系统中的 ZFS 替换为 Ports 版本

在实现多版本 FreeBSD 共存时,一个重要的考虑因素是 ZFS 池版本的兼容性问题。不同版本的 FreeBSD 内置的 ZFS 版本可能不同,这可能导致无法互相访问存储池。

通常,在 FreeBSD 大版本之间,ZFS 池版本和特性都会发生变化,例如从 13 到 14 时 zpool 就有所变动。

可通过 Ports 中的 OpenZFS 实现 13、14、15 等多个系统版本的共存。

警告

如不按照下方进行设置就强行升级 ZFS 池/特性,将无法访问旧版系统。

那些有意愿实现多版本共存的读者可以直接重启,进入启动环境 default(14.3-RELEASE)。

验证当前系统版本

在开始操作之前,首先需要确认我们已经回到了默认的启动环境中。

我们需要确定我们的确在启动环境 default(14.3-RELEASE)中。

可以看到,我们已经回来了。

查看内置的 OpenZFS 版本

首先,让我们查看一下当前系统内置的 ZFS 版本信息,以便了解我们要替换的是什么。

显示当前 ZFS 工具和内核模块的版本信息:

目前 FreeBSD 基本系统内置的是 OpenZFS 2.2.7(即来自 https://github.com/openzfs/zfs/commit/e269af1b3arrow-up-right

安装 filesystems/openzfs

Ports 中的 OpenZFS 提供了比基本系统更灵活的版本选择。我们可以使用 pkg 或 Ports 两种方式来安装它。

  • 使用 pkg 安装

  • 使用 ports 安装:

编辑 /boot/loader.conf

安装完成后,我们需要配置系统启动时加载哪个 ZFS 模块。默认情况下,系统会加载基本系统内置的 ZFS 模块,我们需要修改这个行为。

为了防止系统加载基本系统内置的 ZFS 版本,需要在 zfs_load=YES 前加上注释 #,取消其开机自动加载。

形如:

再新增下列数行:

完成后重启系统。

检查 ZFS 版本

配置完成并重启后,我们需要验证系统是否正确加载了 Ports 版本的 OpenZFS。

在重启后,检查 ZFS 版本:

随后即可更新其他存储池或启用新的特性。

警告

考虑到基本系统中的 OpenZFS 版本不一定是最新的,所以你最好对所有版本都使用 Ports 中的版本以期达到统一。换言之,建议读者也在 15.0-RELEASE 中按照相同方法替换 ZFS。

附录:给 pkgbasify 脚本换源

对于网络环境受限制的用户,可能需要为 pkgbasify 脚本配置国内镜像源以提高下载速度。下面介绍如何修改脚本中的源地址。

修改示例(使用 USTC)

中国科学技术大学(USTC)提供了 FreeBSD 的镜像服务,我们可以修改 pkgbasify 脚本来使用这个镜像源。首先需要找到脚本中的相关函数。

找到 Lua 脚本中的 create_base_repo_conf 函数:

将这个函数修改如下,其中在 return 部分指定了镜像站:

警告

请删除 return "pkg+https://" 这行里面的 pkg+,否则会报错。

再找到下面的函数 create_base_repo_conf

修改如下(删除了 srv 相关数行):

注意

对于那些优先考虑安全性的读者应该保持默认设置。

南京大学开源镜像站 NJU

除了 USTC 镜像站外,南京大学也提供了 FreeBSD pkgbase 的镜像源,其地址如下。

网易开源镜像站 163

网易开源镜像站同样提供了 FreeBSD pkgbase 的镜像服务,地址如下。

附录:配置软件源

为了帮助读者更好地配置 pkgbase 源,下面整理了 FreeBSD 官方源的 pkgbase 信息,包括各分支的更新频率和对应的 URL 地址。

分支

更新频率

URL 地址

main(16.0-CURRENT)

每天两次:08:00、20:00

main(16.0-CURRENT)

每周一次:星期日 20:00

stable/14

每周一次:星期日 20:00

releng/14.0(RELEASE)

每天两次:08:00、20:00

releng/14.1(RELEASE)

每天两次:08:00、20:00

releng/14.2(RELEASE)

每天两次:08:00、20:00

releng/14.3(RELEASE)

每天两次:08:00、20:00

以上表格中的时间已转换为北京时间(东八区),对应 FreeBSD 官方镜像站的发布时间。

若官方源下载速度慢,可以考虑换成国内镜像。只需要替换 https://pkg.freebsd.org 这部分。

参考文献

本章介绍的内容涉及多个技术点,下面列出了一些相关的参考资料,供有兴趣的读者进一步学习。

最后更新于