自动修剪旧的 ZFS 快照

自动修剪旧的 ZFS 快照

所以我在安装 Ubuntu 22.04 时选择了 ZFS,因为我想尝试一下。我喜欢快照功能,但我发现由于每天apt-upgrade都会积累大量快照,占用了大量空间。(并开始抱怨 rpool/bpool 上的空间不足)

如何以及在哪里可以设置一些合理的自动删除规则?

例如我想自动保留

  • 手动命名的快照
  • 最后 3 张apt-upgrade快照
  • 每周/每月 1 或 2 次备份快照。

似乎尤其是当包含大型二进制文件的包(例如 CUDA)进行更新时,大量空间会被用于快照……

答案1

Canonical 没有提供实用程序来执行此操作,因为要以涵盖所有极端情况的方式稳健而出色地完成此操作需要大量工作。而且您不想在大规模删除其他人的数据时犯错误。我认为 Canonical 低估了他们的 zsys 项目的范围以及他们对在十万个安装中自动修剪根数据集的信心。

尽管如此,我已经写了一个足够好的剧本。它是否适合您的目的则完全是另一个问题,我无法回答。将 的值调整keep为您想要保留的快照数量。您可以将此脚本/etc/cron.daily作为 zfs-prune.sh(或任何您喜欢的名称)放入并将其标记为可执行。

#!/bin/bash

keep=10
num_snaps=$(zfs list -t snapshot -o name -S creation | grep -Po '@autozsys_[a-zA-Z0-9]+$' | uniq | wc -l)
printf "Found %d autosys versions. Configured to keep %d.\n" $num_snaps $keep
if [[ $num_snaps -le $keep ]]; then
    printf "no need to prune.\n"
    exit 0
fi

num_to_prune=$(( num_snaps - keep ))
printf "Pruning %d zsys versions.\n" $num_to_prune
if [[ $num_to_prune -le 0 ]]; then
    printf "Error - no snapshots to prune.\n"
    exit 127
fi

if [[ $num_to_prune -ge $num_snaps ]]; then
    printf "Error - won't remove all snapshots.\n"
    exit 127
fi


for zsys_snap in $(zfs list -t snapshot -o name -S creation | grep -Po '@autozsys_[a-zA-Z0-9]+$' | uniq | tail -n $num_to_prune); do
    printf "Removing $zsys_snap\n"
    zfs list -t snapshot -o name | grep "${zsys_snap}$" | xargs -n 1 zfs destroy -vr
done

限制

该脚本有一些限制,您在使用之前应该了解并接受(或解决)。

  • 它不区分 USERDATA 和 ROOT 数据集,因此如果您有大量其中一个或另一个的较新的 zsys 快照,则可能会没有另一个的快照。
  • 这对 grub 启动选项没有任何作用(我不确定 zsys 是否有作用)。
  • 我只进行了一些检查以避免明显的计算/溢出错误。
  • 该脚本假定所有同名快照都是在同一日期创建的,并依靠zfs list按创建日期排序来确定哪些快照是旧的。

如果您能接受这些限制并愿意将数据押在上面,那就试试吧。但本产品不提供任何担保或保证。使用时风险自负。

答案2

我使用这个实用程序zfs-auto-snapshot以实现自动化。

可以使用以下方式安装:

sudo apt install zfs-auto-snapshot

该程序将以下文件放到您的系统上以供调度:/etc/cron.d/zfs-auto-snapshot,其中我有以下内容:

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# */5 * * * * root zfs-auto-snapshot -q -g --label=frequent --keep=12 //
# 00 * * * * root zfs-auto-snapshot -q -g --label=hourly --keep=24 //
45 23 * * * root zfs-auto-snapshot -q -g --label=daily --keep=30 //
# 59 23 * * 0 root zfs-auto-snapshot -q -g --label=weekly --keep=4 //
# 00 00 1 * * root zfs-auto-snapshot -q -g --label=monthly --keep=12 //

如您所见,这可以让您定义以不同间隔运行的不同快照标签,以及保留多少个快照标签。

您可以添加以下行来删除带有标签的其他快照apt-upgrade

59 23 * * * root zfs-auto-snapshot -q -g --label=apt-upgrade --destroy-only --keep=3 //

请注意//每行末尾的所有 ZFS 数据集。您还可以在此处指定文件系统或卷名称,以便将操作仅应用于该数据集。

还请注意,zfs-auto-snapshot还将文件放入所有目录/etc/cron.hourly/etc/cron.daily/etc/cron.weekly/etc/cron.monthly。我已通过删除可执行属性禁用它们。

答案3

谢谢这个答案在回答姐妹网站上的一个问题时,我发现zfs-prune-snapshots,一个 bash 脚本作者:Dave Eddy. 参见其用法部分了解详情。

要下载最新版本的脚本并使其可执行:

wget https://raw.githubusercontent.com/bahamas10/zfs-prune-snapshots/master/zfs-prune-snapshots

chmod +x ./zfs-prune-snapshots

要在干燥模式下运行脚本,即不进行实际修剪,请使用标志-n。要查看从所有 zpools 中删除超过一周的快照的输出,请运行:

./zfs-prune-snapshots -n -v 1w

如果您想删除所有列出的快照,请运行:

sudo ./zfs-prune-snapshots -R -v 1w

该脚本使用zfs destroy在需要超级用户权限的情况下。该-R标志指示它以递归方式销毁所有依赖项(目标层次结构之外的子级和克隆文件系统)。如果没有该-R标志,在我的情况下,无法删除任何快照。

就我而言,运行上述操作会导致删除超过 3000 个快照,这些快照是在连续使用 Ubuntu 22.04 约 10 个月期间积累的。通过删除这些快照,启动时间减少了几分钟,现在又像最初安装 Ubuntu 后一样快了。

您可以通过 Cronjob 运行上述操作来自动执行快照修剪。但请注意zfs destroy手册页中指出:

在使用时应格外小心-r或者-R选项,因为它们可能会破坏池的大部分并导致正在使用的已挂载文件系统出现意外行为。

相关内容