我的小型家庭服务器运行在具有 ZFS 的发行版上。在该系统上,我实现了滚动快照方案:
- 每小时创建一个快照
- 每天一次,链条变细,这样我就有了一组每小时/每天/每周/每月的快照
我想将一些文件系统的异地备份存储在我办公室的 USB 驱动器上。计划是每隔一周更新一次驱动器。然而,由于滚动快照方案,我在实现增量快照时遇到了麻烦。
为了给你一个例子,这是我想要的程序:
- 初始快照:
zfs snap tank/fs@snap0
- 传输初始快照:
zfs send tank/fs@snap0 | zfs recv -Fduv backup_tank
backup_tank
异地存储- 拍几张快照
zfs snap tank/fs@snap1
:zfs snap tank/fs@snap2
- 细化链条:
zfs destroy tank/fs@snap0
- 返回
backup_tank
并对文件系统进行增量更新 - 显然,由于不再存在
zfs send -I snap0 tank/fs@snap2 | zfs recv -Fduv backup_tank
而失败。snap0
tank
长话短说:
是否有一个巧妙的解决方案可以将快照链的细化和增量send
/结合起来recv
?每次我连接驱动器并运行一些命令时,我都希望在此时拥有文件系统的副本。在此示例中,backup_tank
应包含快照fs@snap1
和fs@snap2
.
答案1
你不能完全做你想做的事。
每当您创建zfs send
流时,该流都会创建为两个快照之间的增量。 (这是当前实现 ZFS 的唯一方法。)为了将该流应用于不同的数据集,目标数据集必须包含流的起始快照;如果没有,那么两者就没有共同的参考点。当您销毁源数据集上的 @snap0 快照时,就会造成 ZFS 无法协调的情况。
执行您所要求的操作的方法是始终在两个数据集之间保留一个共同的快照,并使用该共同快照作为下一个发送流的起点。
因此,您可以在步骤 1 中创建快照 @backup0,然后在步骤 6 附近创建并使用快照 @backup1 以用于更新异地备份。然后,您传输 @backup0 和 @backup1 之间的增量流(其中将包括所有中间快照),然后删除@backup0但保留@backup1(成为新的共同点)。下次刷新备份时,您可以创建@backup2(而不是@backup1)并传输@backup1和@backup2(而不是@backup0和@backup1)之间的增量,然后删除@backup1(而不是@backup0),并且很快。
答案2
快照有任意名称。并且zfs send -i [snapshot1] [snapshot2]
可以发送任意两个快照之间的差异。您可以利用它来拥有两组(或更多)具有不同保留策略的快照。
例如,拥有一组快照,名称如下@snap.$timestamp
(其中$timestamp
适合您的日期/时间格式(time_t 最容易进行计算,但对人类来说并不容易阅读。 @snap.%s.%Y%M%D%H%M%S
两者都提供)。您的每小时/每日/每周/每月快照删除代码应忽略所有不以@snap
.
第二组,你可以打电话@offsite.$timestamp
。它应该具有对该任务有意义的任何快照保留/删除策略,并且用于管理它的代码应该忽略所有不以@offsite
.
顺便说一句,这可能说明了显而易见的问题,但您可以将其用于每小时、每天、每周、每月快照,因此每个快照都可以有不同的保留策略。例如@hourly.$timestamp
,@daily.$timestamp
等等,而不仅仅是@snap.$timestamp
.
同样明显的是,这将使用更多的磁盘空间,因为数据集使用的块不会被释放,直到有不留下的快照引用了他们。