配置ZFS自动启动
在完成 Docker ZFS 存储驱动 配置并使用之后,如果重启物理主机,你会惊讶地发现 docker.service 启动失败,原因是 /var/lib/docker 没有就绪。
手工启动zfs
此时检查ZFS会发现 zpool 是空的:
# zpool list
no pools available
zfs list
no datasets available
检查
zpool import可以看到存储池是就绪的(但是没有导入):
# zpool import
pool: zpool-docker
id: 4553342928876801142
state: ONLINE
action: The pool can be imported using its name or numeric identifier.
config:
zpool-docker ONLINE
nvme0n1p9 ONLINE
手工导入:
zpool import zpool-docker
此时再次检查就能够看到zfs文件系统已经挂载 ( df -h ):
Filesystem Size Used Avail Use% Mounted on
...
zpool-docker 102G 6.4G 95G 7% /var/lib/docker
并且 zfs list 可以看到所有该存储池下文件系统:
NAME USED AVAIL REFER MOUNTPOINT
zpool-docker 8.04G 94.7G 6.34G /var/lib/docker
zpool-docker/03ebbb6554f2f15ee36cedacade890f080081631375a60e3796fd160e6788a6d 104K 94.7G 16.6M legacy
zpool-docker/09315a96dcbfbfbc33929960905fc09793bd731a7645cdc625d56079d1643545 112K 94.7G 16.6M legacy
...
配置自动导入和启动ZFS
ZFS被其创建者视为"零管理"文件系统,所以配置ZFS非常简单,主要使用 zfs 和 zpool 命令
自动启动
为了实现ZFS的"零管理":
必须启用
zfs-import-cache.service以导入存储池(import pools):zfs-import-cache.service是通过/etc/zfs/zpool.cache配置来导入ZFS存储池必须启用
zfs-mount.service以挂载存储池中可用的文件系统(这样就不需要使用/etc/fstab来挂载ZFS)
对于每个想要 自动 通过 zfs-import-cache.service 自动实现自动导入的存储池,可以执行如下命令:
zpool set cachefile=/etc/zfs/zpool.cache <pool>
备注
从 OpenZFS 0.6.5.8 版本开始,必须明确激活ZFS服务
除了 zfs-mount.service 以外,也可以使用 zfs-mount-generator 来完成 zfs-import-cache.service 之后的zfs挂载,区别在于 zfs-mount.service 不能保证 /var 目录足够提前完成挂载,此时就需要使用 zfs-mount-generator 来替代实现
方法一: zfs-import-cache + zfs-mount
激活
zfs-import-cache+zfs-mount:
sudo systemctl enable zfs-import-cache.service
sudo systemctl enable zfs-mount.service
备注
升级 Arch Linux 系统可能启动时日志显示报错:
[ 0.879506 ] systemd[306]: /usr/lib/systemd/system-generators/zfs-mount-generator failed with exit status 127.
启动后执行 zpool import 报错:
zpool: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file: No such file or directory
原因是系统默认安装最新版本的 openssl 3.0.7-2 ,自动卸载了不需要的 openssl-1.1 1.1.1.s-2 ,但是第三方安装需要这个库,所以单独安装:
pacman -S openssl-1.1
这样就不会再出现 zpool import 报lib库文件问题,启动日志也就不报错了。为避免后续升级 openssl-1.1 被自动清理,采用 Pacman 的版本hold配置,也就是修订 /etc/pacman.conf 添加:
IgnorePkg = openssl-1.1
不过,对于 /var 目录及其下子目录,挂载还是需要采用 zfs-mount-generator
方法二: zfs-import-cache + zfs-mount-generator
对于 Docker ZFS 存储驱动 ,ZFS存储池是位于 /var/lib/docker ,也就是 /var 子目录。如果采用上文 zfs-import-cache + zfs-mount 会发现启动还是没有自动挂载。
原因是 /var 目录需要在系统启动早期时挂载,此时 zfs 内核模块尚未加载。这就导致 zpool-docker 这个 zpool 导入失败。
对于上述问题,需要改为使用 zfs-mount-generator 替代 zfs-mount.service 来确保启动时创建好 systemd mount units ,这样 Systemd进程管理器 就会自动基于 mount units 完成文件系统挂载而无需使用 zfs-mount.service :
创建
/etc/zfs/zfs-list.cache目录:mkdir /etc/zfs/zfs-list.cache
激活 ZFS Event Daemon(ZED) 脚本(称为 ZEDLET) 请求来创建一系列ZFS文件系统挂载列表(对于OpenZFS>=2.0.0这个链接是自动创建的):
ln -s /usr/lib/zfs/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d
激活
zfs.target和zfs-zed.service并启动zfs-zed.servicesystemctl enable zfs-import-cache systemctl disable zfs-mount systemctl enable zfs.target systemctl enable zfs-zed.service systemctl start zfs-zed.service
在
/etc/zfs/zfs-lilst.cache目录下创建存储池命名的空文件:touch /etc/zfs/zfs-list.cache/<pool-name>
检查
/etc/zfs/zfs-list.cache/<pool-name>内容,如果这个文件是空的,则确保zfs-zed.service正在运行情况下,然后通过以下命令修改ZFS文件系统的canmount属性:zfs set canmount=off zroot/fs1
这个命令会导致ZFS的事件被ZED捕获,此时就会运行ZEDLET来更新 /etc/zfs/zfs-list.cache 目录下文件内容。如果此时检查了 /etc/zfs/zfs-list.cache/<pool-name> 有内容之后,再将文件系统重新设置 canmount 属性:
zfs set canmount=on zroot/fs1
备注
我这里没有采用设置 zpool/zpool-docker 的 canmount 属性开关,是因为我这时刚重启主机, zpool-docker 尚未自动导入。所以我采用了命令 zpool import zpool-docker 命令,也同样可以触发 ZED 自动更新 /etc/zfs/zfs-list.cache/zpool-docker 内容。anyway,只要有ZED事件发生就能触发更新。
完整的针对
zpool-dockerzpool存储池的操作命令如下:
mkdir /etc/zfs/zfs-list.cache
systemctl enable zfs-import-cache
systemctl disable zfs-mount
systemctl enable zfs.target
systemctl enable zfs-zed.service
systemctl start zfs-zed.service
touch /etc/zfs/zfs-list.cache/zpool-docker
# 触发 /etc/zfs/zfs-list.cache/zpool-docker 更新
zfs set canmount=off zpool/zpool-docker
zfs set canmount=on zpool/zpool-docker
然后重新启动操作系统观察 /var/lib/docker 就是正常自动挂载的:
Filesystem Size Used Avail Use% Mounted on
...
zpool-docker 102G 6.8G 95G 7% /var/lib/docker
couldn't start libzfs
我在完成 zfs-import-cache + zfs-mount-generator 配置之后,确实启动之后自动导入 zpool/zpool-docker 并挂载好 /var/lib/docker ,但是我发现 dmesg -T 依然有一个ZFS相关报错:
[Mon Nov 21 15:21:34 2022] zfs-mount-generator[322]: couldn't start libzfs, ignoring
[Mon Nov 21 15:21:35 2022] ZFS: Loaded module v2.1.6-1, ZFS pool version 5000, ZFS filesystem version 5
暂时没有发现 zpool 和 zfs 问题,待查