使用AUFS存储驱动

已弃用

AuFS 存储驱动程序已被弃用,并在 Docker Engine v24.0 中被删除。如果您使用 AufS,则必须先迁移到受支持的存储驱动程序,然后再升级到 Docker Engine v24.0。请阅读 Docker 存储驱动程序 页面以了解支持的存储驱动程序。

AUFS 是一个联合文件系统。存储驱动程序aufs以前是用于管理 Ubuntu 和 Stretch 之前的 Debian 版本 Docker 上的映像和层的默认存储驱动程序。如果您的 Linux 内核是 4.0 或更高版本,并且您使用 Docker Engine - Community,请考虑使用较新的 overlay2,它比存储驱动程序具有潜在的性能优势aufs

先决条件

  • 对于 Docker 引擎 - 社区,Ubuntu 以及 Stretch 之前的 Debian 版本支持 AUFS。
  • 对于 Docker EE,Ubuntu 支持 AUFS。
  • 如果您使用Ubuntu,则需要将AUFS模块添加到内核中。如果您不安装这些软件包,则需要使用overlay2.
  • AUFS 无法使用以下后备文件系统:aufsbtrfsecryptfs。这意味着包含的文件系统 /var/lib/docker/aufs不能是这些文件系统类型之一。

使用 aufs 存储驱动程序配置 Docker

如果启动 Docker 时已将 AUFS 驱动加载到内核中,并且没有配置其他存储驱动,则 Docker 默认使用它。

  1. 使用以下命令验证您的内核是否支持 AUFS。

    $ grep aufs /proc/filesystems
    
    nodev   aufs
    
  2. 检查 Docker 使用的是哪个存储驱动程序。

    $ docker info
    
    <truncated output>
    Storage Driver: aufs
     Root Dir: /var/lib/docker/aufs
     Backing Filesystem: extfs
     Dirs: 0
     Dirperm1 Supported: true
    <truncated output>
    
  3. 如果您使用不同的存储驱动程序,则 AUFS 未包含在内核中(在这种情况下使用不同的默认驱动程序),或者 Docker 已被显式配置为使用不同的驱动程序。检查 /etc/docker/daemon.json或 的输出ps auxw | grep dockerd以查看 Docker 是否已使用该--storage-driver标志启动。

aufs 存储驱动程序如何工作

AUFS 是一个联合文件系统,这意味着它在单个 Linux 主机上分层多个目录并将它们呈现为单个目录。这些目录在 AUFS 术语中称为分支,在 Docker 术语中称为层。

统一过程称为联合安装

下图显示了基于该ubuntu:latest镜像的 Docker 容器。

Ubuntu 容器的层

每个镜像层和容器层在 Docker 主机上都表示为/var/lib/docker/.联合安装提供所有层的统一视图。目录名称并不直接对应于层本身的 ID。

AUFS 使用写时复制 (CoW) 策略来最大限度地提高存储效率并最大限度地减少开销。

示例:磁盘上的映像和容器构造

以下docker pull命令显示 Docker 主机下载包含五层的 Docker 映像。

$ docker pull ubuntu

Using default tag: latest
latest: Pulling from library/ubuntu
b6f892c0043b: Pull complete
55010f332b04: Pull complete
2955fb827c94: Pull complete
3deef3fcbd30: Pull complete
cf9722e506aa: Pull complete
Digest: sha256:382452f82a8bbd34443b2c727650af46aced0f94a44463c62a9848133ecb1aa8
Status: Downloaded newer image for ubuntu:latest

图像层

警告:不要直接操作其中的任何文件或目录 /var/lib/docker/。这些文件和目录由 Docker 管理。

有关图像和容器层的所有信息都存储在/var/lib/docker/aufs/.

  • diff/:每一层的内容,各自存放在单独的子目录中
  • layers/:有关图像层如何堆叠的元数据。该目录包含 Docker 主机上每个映像或容器层的一个文件。每个文件都包含堆栈中位于其下方的所有层(其父层)的 ID。
  • mnt/:挂载点,每个镜像或容器层一个,用于组装和挂载容器的统一文件系统。对于只读图像,这些目录始终为空。

容器层

如果容器正在运行,内容会/var/lib/docker/aufs/以下列方式发生变化:

  • diff/:可写容器层中引入的差异,例如新文件或修改文件。
  • layers/:有关可写容器层的父层的元数据。
  • mnt/:每个正在运行的容器的统一文件系统的安装点,与容器内的显示完全相同。

容器如何与aufs一起读写

读取文件

考虑容器使用 aufs 打开文件进行读取访问的三种场景。

  • 容器层中不存在该文件:如果容器打开一个文件进行读访问,并且该文件在容器层中尚不存在,则存储驱动程序会在镜像层中搜索该文件,从该文件正下方的层开始容器层。它是从找到它的层中读取的。

  • 该文件仅存在于容器层中:如果容器打开一个文件进行读取访问,并且该文件存在于容器层中,则从那里读取该文件。

  • 文件同时存在于容器层和镜像层:如果容器打开一个文件进行读访问,并且该文件存在于容器层和一个或多个镜像层中,则从容器层读取该文件。容器层中的文件会掩盖镜像层中同名的文件。

修改文件或目录

考虑一些修改容器中的文件的场景。

  • 首次写入文件:容器首次写入现有文件时,该文件在容器中不存在 ( upperdir)。驱动aufs程序执行copy_up操作将文件从其所在的镜像层复制到可写容器层。然后,容器将更改写入容器层中文件的新副本。

    然而,AUFS 在文件级别而不是块级别工作。这意味着所有 copy_up 操作都会复制整个文件,即使文件非常大并且只修改了其中的一小部分。这会对容器写入性能产生显着影响。在多层图像中搜索文件时,AUFS 可能会出现明显的延迟。但是,值得注意的是,copy_up 操作仅在第一次写入给定文件时发生。对同一文件的后续写入将针对已复制到容器的文件副本进行操作。

  • 删除文件和目录

    • 当在容器内删除文件时,会在容器层中创建一个whiteout文件。图像层中的文件版本不会被删除(因为图像层是只读的)。但是,whiteout 文件会阻止容器使用它。

    • 当删除容器内的目录时,会在容器层中创建一个不透明文件。这与whiteout文件的工作方式相同,并且有效地防止目录被访问,即使它仍然存在于图像层中。

  • 重命名目录rename(2)AUFS 不完全支持调用目录。EXDEV即使源路径和目标路径位于同一 AUFS 层,它也会返回(“不允许跨设备链接”),除非该目录没有子目录。您的应用程序需要设计为能够处理EXDEV和回退到“复制和取消链接”策略。

AUFS 和 Docker 性能

总结一些已经提到的与性能相关的方面:

  • AUFS 存储驱动程序的性能低于overlay2驱动程序,但对于 PaaS 和容器密度很重要的其他类似用例来说是一个不错的选择。这是因为 AUFS 在多个正在运行的容器之间有效地共享映像,从而实现快速容器启动时间和最少的磁盘空间使用。

  • AUFS 如何在镜像层和容器之间共享文件的底层机制非常有效地使用页面缓存。

  • AUFS 存储驱动程序可能会给容器写入性能带来显着的延迟。这是因为容器第一次写入任何文件时,需要找到该文件并将其复制到容器的顶层可写层中。当这些文件存在于许多图像层下方并且文件本身很大时,这些延迟会增加并加剧。

性能最佳实践

以下通用性能最佳实践也适用于 AUFS。

  • 固态设备 (SSD)提供比旋转磁盘更快的读取和写入速度。

  • 将卷用于写入密集型工作负载:卷为写入密集型工作负载提供最佳且最可预测的性能。这是因为它们绕过存储驱动程序,并且不会产生精简配置和写时复制带来的任何潜在开销。卷还有其他好处,例如允许您在容器之间共享数据,甚至在没有正在运行的容器使用它们时也能保留数据。