随着快照数量的增加,LXD ZFS 快照创建速度变慢

随着快照数量的增加,LXD ZFS 快照创建速度变慢

Ubuntu 18.04 LTS - LXD Ubuntu 使用环回 ZFS 启动(约 400MB)

# lxc launch ubuntu:16.04 test -s ianzfspool

(我还有另外一个空闲的多 GB 容器使用相同的 ianzfspool。)我在池中有很多空间:

# zpool list                                    
NAME         SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
ianzfspool  99.5G  13.7G  85.8G         -     2%    13%  1.00x  ONLINE  -

如果我循环使用lxc来创建空闲测试容器 (400MB) 的快照,第一个快照会在几秒钟内创建。随着lxc快照数量的增加(目前超过 1,200 个),现在它们需要几分钟才能创建。我在测试容器中运行一个脚本,每隔几秒钟将当前日期放入 /tmp 中的文件中,因此我有一个文件在每个快照中都在容器中发生变化;否则,容器大部分时间处于空闲状态。第一个lxc快照使用了大约 25K;当前快照(1,200 个快照后)使用了 66K。(2,470 个快照后,它们每个使用 115K,7,500 个快照后,它们每个使用 293K。)

#!/bin/sh -u                                                                   
# Create snapshots of the Ubuntu test container.
count=0
while : ; do
    count=$(( count + 1 ))
    cp=$( printf "%05d" $count )
    lxc snapshot test snap$cp
    echo "$0: done $cp" >/tmp/icount.txt
done

编辑1:我目前有大约 2,470 个lxc快照,每个新快照大约需要四分钟来创建,并使用大约 115K。如果我zfs snapshot直接调用来拍摄容器快照,而不是使用lxc snapshot,则拍摄快照只需不到一秒钟,即使有 2,470 个现有快照。直接zfs快照仅使用 20K(而不是 115K)。运行zfs list只需一两秒钟。如果我运行lxc list(而不是zfs list),目前需要四分钟以上,现有快照有 2,470 个。因此,快照创建和列表速度减慢不是由 ZFS 引起的,而是由 LXD 引起的。事实上,lxd到目前为止,在这个快照创建实验中,该过程本身已经使用了 4,253 CPU 秒,VSIZE 为 3.9G。

我暂停了lxc快照创建脚本,并编写了一个脚本来循环创建直接zfs快照,它在五分钟内创建的快照比lxc三天内创建的还多。我在大约 3,000 个直接 ZFS 快照后暂停了它。

我刚刚重新运行lxc list,当然它仍然只显示 2,471 个lxc快照,但现在它只运行了 40 秒,而不是 4 分钟。我刚刚创建了另一个lxc snapshot,它只花了 49 秒,而不是 4 分钟。发生了什么变化?创建一堆直接zfs快照是否以某种方式加快了lxc快照创建和列表?lxc快照的创建速度仍然比直接zfs快照慢得多,但快照创建方面有所改进lxc(从 4 分钟到 49 秒)。

我让 ZFS 快照创建继续进行,直到创建了 10,000 个直接 ZFS 快照。(因此现在我有 2,472 个lxc快照和 10,000 个zfs此测试容器的直接快照。)lxc list现在需要 90 秒(而不是 40 秒)和lxc snapshot100 秒(而不是 49 秒)。直接使用 ZFS 仍然比通过 LXD 快两个数量级。


编辑2:重启后,LXD 快照创建速度加快了。我通过lxc snapshot循环创建了 7,470 个快照,每个快照现在大约需要 30 秒才能创建,大小为 293K。需要lxc list45 秒。zfs list需要 105 秒并产生 17,507 行输出(其中包括 10,000 个直接 ZFS 快照)。zfs snapshot ianzfspool/containers/test@iansnap10001直接执行(不通过 LXD)只需不到半秒——仍然比通过 LXD 快得多。


在哪里可以找到有关 LXD 快照创建速度变慢的原因以及如何加快速度的文档?(如果带有 ZFS 快照的 LXD 像我所相信的那样便宜,我希望每 5 分钟运行一次快照并保留大约一周,也就是 2,016 个快照。我读到过 LVM 快照会降低性能,但我读到的关于带有 ZFS 的 LXD 的说法都不一样。我知道我可以绕过 LXD 并使用 ZFS 快照,但为什么我需要这样做?LXD 可以修复吗?)

主机上的进程lxd正在使用大量 CPU,并且变得越来越大(这是在 1,200 个快照之后):

  PID VSTACK   VSIZE   RSIZE  PSIZE   VGROW   RGROW SWAPSZ   MEM  CMD        1/8
10663   132K    3.7G    1.1G     0K      0K      0K  2580K   14%  lxd

答案1

我没有使用过lxd snapshot,所以我能做的就是猜测它的实现并告诉你有关 ZFS 快照的更多细节。

ZFS 快照的设计不会给正在进行的读写增加任何开销。(正如您所提到的,LVM 快照确实会以写入放大的形式增加性能损失。)为了实现这一点,ZFS 有一个名为 a 的内部操作,它就txg_sync像是对所有最近的异步 IO 进行批量写入,并且每 10 秒自动发生一次,以及在文件系统结构发生变化时(例如当您拍摄快照时)。这会导致大量 IO 发生,因此理论上会由于拥塞导致并发同步写入速度减慢(尽管同步写入应该优先)。但是,似乎您几乎没有向文件系统写入任何内容(并且可能没有向池的其余部分写入太多内容)。

我猜想是元数据读取变慢了。理论上,lxd snapshot可以只拍摄 ZFS 快照并继续,这应该需要一段恒定的时间(假设 IO 负载恒定)。但是,我猜想它还会尝试在该操作期间列出所有快照(相当于zfs list),这涉及读取每个快照的一大堆元数据,这些元数据通常分布在整个池中,并且会随着快照数量线性增长。要检查是否是这种情况,您可以尝试zfs snapshot直接在文件系统上计时,然后在文件系统及其快照上执行zfs list -t all,看看哪一个比另一个花费的时间长得多(应该是第二个)。

在 ZFS 社区中,这是一个众所周知的问题,但很难修复,因为这需要更改大量磁盘上的元数据结构才能改进,而且保留这么多快照的情况很少见。如果lxd努力避免列出所有快照来运行其快照操作,我认为这可以解决您的问题。

或者,您可以每 5 分钟拍摄一次快照,然后相对较快地删除它们,只保留(例如)5 分钟、10 分钟、15 分钟、30 分钟、1 小时、2 小时、3 小时、6 小时、12 小时、24 小时等的快照。这样可以在您最有可能需要的时间段内为您提供高分辨率,并且不会导致lxd snapshot速度变慢。

相关内容