如何清理Docker ZFS旧共享

时间:2018-09-18 13:03:14

标签: docker zfs volumes

摘要

鉴于:

  • docker个存储驱动程序用户是ZFS;
  • docker创建legacy数据集;

重击:

$ docker ps -a | wc -l
16

$ docker volume ls | wc -l
12

$ zfs list | grep legacy | wc -l
157

16个容器(正在运行和已停止)。 12册。 157个数据集。。这似乎有很多旧数据集。我想知道他们中的许多人是否是如此孤立,以至于docker都不再了解他们,因此他们没有得到清理。

理性

我的Debian zfs池中有大量旧卷。当我开始在这台机器上使用Docker时,它们开始出现:

$ sudo zfs list | grep legacy | wc -l
486

它们都具有以下形式:

pool/var/<64-char-hash>                  202K  6,18T   818M  legacy

此位置仅由docker使用。

$ docker info | grep -e Storage -e Dataset
Storage Driver: zfs
 Parent Dataset: pool/var

我开始清理。

$ docker system prune -a
  (...)
$ sudo zfs list | grep legacy | wc -l
154

那更好。但是,我只运行了大约15个容器,并且在运行docker system prune -a之后,历史记录或每个容器都显示只有最后一个图像层仍然可用。其余的为<missing>(因为它们已被清理)。

$ docker images | wc -l
15

如果所有容器在修剪完其余部分后仅使用最后一个图像层,那么 docker不应只使用15个图像层和15个正在运行的容器,总共30个卷吗?

$ sudo zfs list | grep legacy | wc -l
154

我可以找出容器/图像是否正在使用它们吗?是否有命令可遍历ZFS中的所有pool/var/<hash>数据集并找出它们所属的docker容器/映像?要么很多都可以删除,要么我不知道如何找出(仅仅相信docker system prune之外)。

码头工人对zfs卷的过度使用在视觉上和性能上都弄乱了我的zfs list命令。列出zfs卷现在需要大约10秒,而不是<1。

证明Docker不再有悬空计数

$ docker ps -qa --no-trunc --filter "status=exited"
  (no output)
$ docker images --filter "dangling=true" -q --no-trunc
  (no output)
$ docker volume ls -qf dangling=true
  (no output)

zfs list示例:

NAME                                                                                       USED  AVAIL  REFER  MOUNTPOINT
pool                                                                                      11,8T  5,81T   128K  /pool
pool/var                                                                                   154G  5,81T   147G  /mnt/var
pool/var/0028ab70abecb2e052d1b7ffc4fdccb74546350d33857894e22dcde2ed592c1c                 1,43M  5,81T  1,42M  legacy
pool/var/0028ab70abecb2e052d1b7ffc4fdccb74546350d33857894e22dcde2ed592c1c@211422332       10,7K      -  1,42M  -
# and 150 more of the last two with different hashes

2 个答案:

答案 0 :(得分:2)

我有同样的问题,但找不到满意的答案。添加what I eventually found,因为此问题是搜索量最高的结果之一。

背景

用于Docker的ZFS存储驱动程序将每个图像的每一层存储为单独的旧数据集。

即使只有很少的图像也可能导致大量的图层,每个图层都对应一个legacy ZFS数据集。

  • 来自Docker ZFS driver docs的语录:

    图像的基础层是ZFS文件系统。每个子层都是一个基于其下一层的ZFS快照的ZFS克隆。容器是一个ZFS克隆,它基于从其创建图像的顶层的ZFS快照。

调查

您可以通过运行以下命令检查一张图像使用的数据集:

 $ docker image inspect [IMAGE_NAME]

示例输出:

...
"RootFS": {
    "Type": "layers",
    "Layers": [
        "sha256:f2cb0ecef392f2a630fa1205b874ab2e2aedf96de04d0b8838e4e728e28142da",
        ...
        ...
        ...
        "sha256:2e8cc9f5313f9555a4decca744655ed461e21fbe48a0f078ed5f7c4e5292ad2e",
    ]
},
...

这说明了为什么仅运行十几个容器就可以看到150多个创建的数据集。

解决方案

  1. 修剪并删除未使用的图像。

    $ docker image prune -a
    
  2. 为避免变慢zfs list,请指定感兴趣的数据集。
    假设您将docker存储在tank/docker中,其他文件存储在tank/data中。通过递归选项仅列出data数据集:

    # recursively list tank/data/*
    $ zfs list tank/data -r
    

答案 1 :(得分:0)

Prune introductions在docker.com上。

我认为您的docker版本低于V17.06。由于您执行了docker system prune -a,因此旧图层的建筑物信息和体积都丢失了。 -a/--all标志意味着所有没有至少一个容器的图像都将被删除。如果没有-a/--all标志,则仅删除悬空的图像。

此外,我认为您对<missing>标记和晃晃的图像有误解。 <missing>并不表示标记为缺失的图层确实缺失。这仅意味着这些层可以在其他计算机上构建。悬空图像是非参考图像。即使名称和标记都标记为<none>,该图像仍然可以被其他图像引用,可以用docker history image_id进行检查。

在您的情况下,这些图层被标记为丢失,因为您已删除了包含建筑物信息的旧图像版本。您在上面说过-仅提供最新版本的图像-因此,只有最新层未标记为丢失。

请注意:docker system prune是管理Docker的所有对象(图像/容器/卷/网络/缓存)的一种惰性方法。