使用 Sanoid 自动管理 ZFS 快照
坑边闲话:ZFS 快照任务是非常关键的,依赖手动快照在大多数情况下无法避免意外事件,借助自动化的快照机制,可以有效提高抗风险能力。本文基于 Debian bookworm 系统介绍开源快照管理软件 Sanoid 的使用方法。
1. 快照的自动管理·
此前笔者的快照也是自动化编排的,只是行为比较简单。笔者编写了一个自动执行快照的 Systemd Timer,然后定期执行某个脚本:
- 在脚本里定义了执行快照的逻辑;
- 在 Systemd Timer 和 Service 定义执行时间和执行路径。
然而,自己重复造轮子的代价就是会翻车,然后重复解决前人已经解决的问题。因此推荐使用开发多年的工具 Sanoid. 该工具原理与笔者此前的开发工作类似,只是它以 TOML 配置文件对快照任务进行了抽象,而且增加了对快照生命周期的支持,能够自动销毁过期的快照。
2. 安装 Sanoid·
Sanoid 的主要开发语言是 Perl,因此不需要经过复杂的编译即可使用。目前的 Sanoid 没有集成到 ZFS 工具链上游,也没有集成到 Debian 发行版的软件包仓库,用户需要安装 Debian 打包工具,创建自己的 .deb
安装文件。执行下列代码即可创建 .deb
文件并本地化安装。
1 | # 下载编译打包工具 |
3. 配置 Sanoid 任务·
1 | [zroot] |
1 | [zroot] |
1 | sudo systemctl enable --now sanoid.timer |
3.1 时区问题·
在 Debian 上,查看文件 /usr/lib/systemd/system/sanoid.service
,可以发现 Sanoid 使用的时区是 UTC.
1 |
|
4. 与 TrueNAS 的 Zettarepl 模块集成·
Zettarepl 是 TrueNAS 开发的一套基于 Python 语言的中间件,其使命就是进行 ZFS 文件系统 Replication.
在中文语境里 Replication 很难找到匹配的词汇,直接翻译为「复制」则难以与 Copy 区分,毕竟 Copy 和 Replication 是大不相同的。Replication 通常带有以下含义:
- 忠实重现:强调对原始对象、数据或现象的精准复现。
- 分布和同步:在数据库、存储系统等领域,指的是数据在多个节点之间的同步。
- 验证或验证性实验:在科学研究中,指重复实验以验证原始结果的可靠性。
Copy 则更偏向于直接的、单次的复制行为,没有强调“忠实”或“同步”的含义。因此本文直接用英文词汇,不做翻译。
4.1 错误示范与问题解决·
此前笔者使用基于名字的快照匹配策略进行待发送快照的选取,过滤模式如下所示。然而,Zettarepl 在这种模式下会遇到问题。
1 | # 基于 date 命令的匹配字符串 |
Sanoid 会按照小时、日、月进行快照,由于 ZFS 快照很快,所以一秒钟之内即可完成。很多时候会生成如下命名的相邻快照:
1 | zroot/home@autosnap_2025-01-04_00:00:04_daily |
两者的字面时间完全一致,只有 monthly 和 hourly 差别。使用下面的命令检查创建时间也无法区分。
1 | date -u -d @$(zfs get -p creation zroot/home@autosnap_2025-01-04_00:00:04_daily -o value -H)Matching regular expression |
其实,每个快照都有创建日期和 GUID,快照创建顺序在 zfs list
的输出中有严格显示。问题在于 TrueNAS Zettarepl 故意忽略快照元数据。Zettarepl 是一个严格的基于名称的工具,它需要“可解析的”快照名字。iXsystems 这样做的原因大概是为了做性能优化,毕竟备份所需的时间越短越好。解析快照名称比读取和比较快照元数据要快得多!特别是当生产环境中有大量的快照时。
解决的方案很简单:将 Matching naming schema 改为 Matching regular expression 即可。比如使用正则表达式 autosnap_\d{4}-\d{2}-\d{2}_\d{2}:\d{2}:\d{2}_(hourly|daily|monthly)
替代原先的三个名字匹配模式。
4.2 Sanoid 递归配置·
在使用 Sanoid 进行递归创建时,建议设置为 recursive=zfs
而非 recursive=yes
,前者性能更好而且不易出错。
4.3 备份目的地存储池的属性设置·
Zettarepl 需要先在 TrueNAS 上创建备份数据集。笔者推荐使用如下命令进行创建并设置属性:
1 | DESTINATION_DATASET=DapuStor_R5100_RAID-Z1/machines/4950-debian |
compression=lz4
一般不用设置,毕竟zfs receive
会按照源数据集的压缩模式进行本地存储。这里手动设置,是为了防止后期出现潜在问题。canmount=off
在一般情况下也不用设置。然而,当待备份数据集和本地数据集的所属 pool 名字、数据集名字完全一致时,自动挂载会产生混淆,甚至引起系统异常。为了保证安全需要关闭自动挂载。然而,在关闭canmount
之后,在 TrueNAS 界面点击相应数据集会提示找不到本地路径的警告,忽略即可。readonly=on
很重要,它可以防止本地数据集被修改。开启readonly
之后,对数据集的任何写操作均会被拒绝,但是不影响zfs receive
快照接收.
4.4 备份的保留策略·
在 TrueNAS 中,建议将备份保留策略设置为与源数据集相同。
如果需要保留特殊备份,也可以手动管理。
总结·
本文详细介绍了 ZFS 数据备份中的一些细节,作为一个存储系统,能把数据安全存储起来是至关重要的,但与此同时,能把数据稳定高效安全地 Replicate 到其他系统、介质上也是关键的。