使用 BTRFS 存储驱动程序

Btrfs 是一种写时复制文件系统,支持许多高级存储技术,非常适合 Docker。 Btrfs 包含在主线 Linux 内核中。

Docker 的btrfs存储驱动程序利用许多 Btrfs 功能来进行映像和容器管理。这些功能包括块级操作、精简配置、写时复制快照和易于管理。您可以将多个物理块设备组合到一个 Btrfs 文件系统中。

本页面将 Docker 的 Btrfs 存储驱动程序称为 Btrfs,btrfs并将整个 Btrfs 文件系统称为 Btrfs。

笔记

btrfs仅 SLES、Ubuntu 和 Debian 系统上的 Docker Engine CE 支持存储驱动程序。

先决条件

btrfs如果您满足以下先决条件,则受支持:

  • btrfs仅建议在 Ubuntu 或 Debian 系统上与 Docker CE 一起使用。

  • 更改存储驱动程序会使您已创建的任何容器在本地系统上无法访问。用于docker save保存容器,并将现有镜像推送到 Docker Hub 或私有存储库,以便您以后无需重新创建它们。

  • btrfs需要专用的块存储设备,例如物理磁盘。该块设备必须针对 Btrfs 进行格式化并安装到/var/lib/docker/.下面的配置说明将引导您完成此过程。默认情况下,SLES/文件系统采用 Btrfs 进行格式化,因此对于 SLES,您不需要使用单独的块设备,但出于性能原因您可以选择这样做。

  • btrfs您的内核中必须存在支持。要检查这一点,请运行以下命令:

    $ grep btrfs /proc/filesystems
    
    btrfs
    
  • 要在操作系统级别管理 Btrfs 文件系统,您需要该 btrfs命令。如果没有此命令,请安装btrfsprogs 软件包 (SLES) 或btrfs-tools软件包 (Ubuntu)。

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

此过程在 SLES 和 Ubuntu 上基本相同。

  1. 停止 Docker。

  2. 将 的内容复制/var/lib/docker/到备份位置,然后清空 的内容/var/lib/docker/

    $ sudo cp -au /var/lib/docker /var/lib/docker.bk
    $ sudo rm -rf /var/lib/docker/*
    
  3. 将您的一个或多个专用块设备格式化为 Btrfs 文件系统。此示例假设您使用两个名为/dev/xvdf和 的 块设备/dev/xvdg。仔细检查块设备名称,因为这是破坏性操作。

    $ sudo mkfs.btrfs -f /dev/xvdf /dev/xvdg
    

    Btrfs 还有更多选项,包括条带化和 RAID。请参阅 Btrfs 文档

  4. 在装载点上装载新的 Btrfs 文件系统/var/lib/docker/。您可以指定用于创建 Btrfs 文件系统的任何块设备。

    $ sudo mount -t btrfs /dev/xvdf /var/lib/docker
    

    笔记

    通过添加一个条目来使更改在重新启动后永久生效 /etc/fstab

  5. 将内容复制/var/lib/docker.bk/var/lib/docker/.

    $ sudo cp -au /var/lib/docker.bk/* /var/lib/docker/
    
  6. 配置 Docker 以使用btrfs存储驱动程序。即使/var/lib/docker/现在使用 Btrfs 文件系统,这也是必需的。编辑或创建文件/etc/docker/daemon.json。如果是新文件,则添加以下内容。如果它是现有文件,则仅添加键和值,如果不是结束大括号 ( }) 之前的最后一行,请小心地以逗号结束该行。

    {
      "storage-driver": "btrfs"
    }

    请参阅守护程序参考文档中每个存储驱动程序的所有存储选项

  7. 启动 Docker。当它运行时,验证它btrfs是否被用作存储驱动程序。

    $ docker info
    
    Containers: 0
     Running: 0
     Paused: 0
     Stopped: 0
    Images: 0
    Server Version: 17.03.1-ce
    Storage Driver: btrfs
     Build Version: Btrfs v4.4
     Library Version: 101
    <...>
    
  8. 准备好后,删除该/var/lib/docker.bk目录。

管理 Btrfs 卷

Btrfs 的优点之一是可以轻松管理 Btrfs 文件系统,无需卸载文件系统或重新启动 Docker。

当空间不足时,Btrfs 会自动以大约 1 GB 的块扩展卷。

要将块设备添加到 Btrfs 卷,请使用btrfs device addbtrfs filesystem balance命令。

$ sudo btrfs device add /dev/svdh /var/lib/docker

$ sudo btrfs filesystem balance /var/lib/docker

笔记

虽然您可以在 Docker 运行时执行这些操作,但性能会受到影响。最好计划一个中断窗口来平衡 Btrfs 文件系统。

btrfs 存储驱动程序如何工作

btrfs存储驱动程序的工作方式与其他存储驱动程序不同,因为您的整个/var/lib/docker/目录都存储在 Btrfs 卷上。

磁盘上的映像和容器层

有关图像层和可写容器层的信息存储在 /var/lib/docker/btrfs/subvolumes/.该子目录包含每个图像或容器层一个目录,以及从一层及其所有父层构建的统一文件系统。子卷本质上是写时复制,并从底层存储池按需分配空间。它们还可以嵌套和快照。下图显示了 4 个子卷。 “子卷 2”和“子卷 3”是嵌套的,而“子卷 4”显示其自己的内部目录树。

子卷示例

仅图像的基础层被存储为真正的子体积。所有其他层都存储为快照,其中仅包含该层中引入的差异。您可以创建快照的快照,如下图所示。

快照图

在磁盘上,快照看起来和感觉就像子卷,但实际上它们要小得多并且更节省空间。写时复制用于最大化存储效率并最小化层大小,并且容器可写层中的写入在块级别进行管理。下图显示了子卷及其快照共享数据。

快照和子卷共享数据

为了最大程度地提高效率,当容器需要更多空间时,会以大约 1 GB 大小的块进行分配。

Docker 的btrfs存储驱动程序将每个映像层和容器存储在其自己的 Btrfs 子卷或快照中。映像的基础层存储为子卷,而子映像层和容器存储为快照。如下图所示。

Btrfs 容器层

在运行驱动程序的 Docker 主机上创建映像和容器的高级流程btrfs如下:

  1. 图像的基础层存储在下的 Btrfs子卷/var/lib/docker/btrfs/subvolumes中。

  2. 后续映像层存储为父层子卷或快照的Btrfs快照,但包含该层引入的更改。这些差异存储在块级别。

  3. 容器的可写层是最终镜像层的 Btrfs 快照,其中存在由运行容器引入的差异。这些差异存储在块级别。

容器如何与 btrfs 一起读写

读取文件

容器是镜像的节省空间的快照。快照中的元数据指向存储池中的实际数据块。这与子卷相同。因此,对快照执行的读取本质上与对子卷执行的读取相同。

写入文件

一般注意事项是,使用 Btrfs 写入和更新大量小文件可能会导致性能下降。

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

写入新文件

将新文件写入容器会调用按需分配操作,将新数据块分配给容器的快照。然后文件被写入这个新空间。按需分配操作是 Btrfs 的所有写入操作的本机操作,与将新数据写入子卷相同。因此,将新文件写入容器的快照将以本机 Btrfs 速度运行。

修改现有文件

更新容器中的现有文件是写时复制操作(写时重定向是 Btrfs 术语)。从文件当前所在的层读取原始数据,仅将修改的块写入容器的可写层。接下来,Btrfs 驱动程序更新快照中的文件系统元数据以指向此新数据。此行为会产生少量开销。

删除文件或目录

如果容器删除了下层存在的文件或目录,Btrfs 会屏蔽下层文件或目录的存在。如果容器创建一个文件然后删除它,则该操作将在 Btrfs 文件系统本身中执行,并回收空间。

Btrfs 和 Docker 性能

在存储驱动下影响Docker性能的因素有几个btrfs

笔记

通过使用 Docker 卷来处理写入量大的工作负载,而不是依赖于将数据存储在容器的可写层中,可以缓解许多这些因素。然而,就 Btrfs 而言,Docker 卷仍然存在这些缺点,除非/var/lib/docker/volumes/不受 Btrfs 支持。

页面缓存

Btrfs 不支持页面缓存共享。这意味着访问同一文件的每个进程都会将该文件复制到 Docker 主机的内存中。因此,该btrfs驱动程序可能不是 PaaS 等高密度用例的最佳选择。

小写

执行大量小写入的容器(这种使用模式也与您在短时间内启动和停止许多容器时发生的情况相匹配)可能会导致 Btrfs 块的使用不当。这可能会过早填满 Btrfs 文件系统并导致 Docker 主机上出现空间不足的情况。用于btrfs filesys show密切监控 Btrfs 设备上的可用空间量。

顺序写入

Btrfs 在写入磁盘时使用日志技术。这可能会影响顺序写入的性能,使性能降低高达 50%。

碎片化

碎片是 Btrfs 等写时复制文件系统的自然副产品。许多小的随机写入会使这个问题变得更加复杂。碎片可能表现为使用 SSD 时的 CPU 峰值或使用旋转磁盘时的磁头抖动。这些问题中的任何一个都会损害性能。

如果您的 Linux 内核版本为 3.9 或更高版本,则可以autodefrag 在挂载 Btrfs 卷时启用该功能。在将其部署到生产环境之前,请在您自己的工作负载上测试此功能,因为一些测试表明会对性能产生负面影响。

固态硬盘性能

Btrfs 包括针对 SSD 介质的本机优化。要启用这些功能,请使用 mount 选项挂载 Btrfs 文件系统-o ssd。这些优化包括通过避免优化(例如不适用于固态介质的寻道优化)来增强 SSD 写入性能。

经常平衡 Btrfs 文件系统

使用操作系统实用程序(例如cron作业)在非高峰时段定期平衡 Btrfs 文件系统。这会回收未分配的块并有助于防止文件系统不必要地填满。除非向文件系统添加额外的物理块设备,否则无法重新平衡完全满的 Btrfs 文件系统。

请参阅 Btrfs 维基

使用快速存储

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

使用卷来处理写入量大的工作负载

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