BTRFS 存储驱动程序

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

Docker 的存储驱动程序利用许多 Btrfs 功能来实现镜像和 容器管理。这些功能包括块级操作、thin 预置、写入时复制快照和易管理性。您可以 将多个物理块设备合并到单个 Btrfs 文件系统中。btrfs

本页将 Docker 的 Btrfs 存储驱动程序称为整体 Btrfs 文件系统设置为 Btrfs。btrfs

注意

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

先决条件

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

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

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

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

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

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

配置 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 文件系统挂载到挂载点上。你 可以指定用于创建 Btrfs 文件系统的任何块设备。/var/lib/docker/

    $ 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 文件系统。 编辑或创建文件 .如果是新文件,请添加 以下内容。如果是已有文件,则添加 key 和 value 只是,如果不是韵母,请小心地以逗号结束这一行 行 ()。btrfs/var/lib/docker//etc/docker/daemon.json}

    {
      "storage-driver": "btrfs"
    }

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

  7. 启动 Docker。当它运行时,验证是否被用作 storage 驱动程序。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 卷,请使用 and 命令。btrfs device addbtrfs filesystem balance

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

$ sudo btrfs filesystem balance /var/lib/docker

注意

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

btrfs 存储驱动程序的工作原理

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

磁盘上的镜像和容器层

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

子卷示例

只有镜像的 Base Layer 存储为 true subvolume。所有其他 图层存储为快照,其中仅包含引入的差异 在该层中。您可以创建快照的快照,如图所示 下面。

快照图

在磁盘上,快照的外观和感觉就像子卷,但实际上它们确实是 体积更小,空间更节省。使用写入时复制来最大化存储空间 效率并最小化层大小,并在容器的可写层中写入 在区块级别进行管理。下图显示了一个子卷及其 快照共享数据。

快照和子卷共享数据

为了实现最高效率,当容器需要更多空间时,它会被分配到 大小约为 1 GB 的块。

Docker 的存储驱动程序将每个镜像层和容器存储在其 拥有 Btrfs 子卷或快照。镜像的 Base Layer 存储为 subvolume 的 S S Package,而子镜像层和容器则存储为快照。 如下图所示。btrfs

Btrfs container layers

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

  1. 镜像的 Base Layer 存储在 下的 Btrfs 子卷中。/var/lib/docker/btrfs/subvolumes

  2. 后续镜像图层将存储为父级的 Btrfs 快照 layer 的子卷或快照,但由此引入的更改 层。这些差异存储在块级别。

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

容器读取和写入如何与 btrfs 配合使用

读取文件

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

写入文件

作为一般的警告,使用 Btrfs 可能会导致性能降低。

考虑三种情况,其中容器使用 Btrfs 的。

编写新文件

将新文件写入容器会调用 allocate-on-demand 操作,以 将新数据块分配给容器的快照。然后写入该文件 到这个新空间。按需分配操作是所有写入的原生操作 和 与 write new data to a subvolume 相同。因此, 将新文件写入容器的快照以本机 Btrfs 速度运行。

修改现有文件

更新容器中的现有文件是写入时复制操作 (redirect-on-write 是 Btrfs 术语)。原始数据从 文件当前所在的图层,并且只有修改后的块是 写入容器的可写层。接下来,Btrfs 驱动程序会更新 filesystem 元数据指向此新数据。此行为 产生少量开销。

删除文件或目录

如果容器删除了存在于较低层中的文件或目录,则 Btrfs 遮罩下层中文件或目录的存在。如果容器 创建一个文件,然后删除它,此操作在 Btrfs 中执行 filesystem 本身,并且空间将被回收。

Btrfs 和 Docker 性能

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

注意

通过使用 Docker 卷进行大量写入操作,可以缓解其中的许多因素 工作负载,而不是依赖于将数据存储在容器的 writable 中 层。但是,对于 Btrfs,Docker 卷仍然会受到这些 draw-backs 除非没有 Btrfs 支持。/var/lib/docker/volumes/

页面缓存

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

小写入

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

顺序写入

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

破碎

碎片是 Btrfs 等写时复制文件系统的自然副产品。 许多小的随机写入可能会使此问题复杂化。碎片化可以表现为 使用 SSD 时出现 CPU 峰值,使用旋转磁盘时出现磁头抖动。也 可能会损害性能。

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

SSD 性能

Btrfs 包括对 SSD 介质的本机优化。要启用这些功能, 使用 mount 选项挂载 Btrfs 文件系统。这些优化 通过避免搜索等优化来增强 SSD 写入性能 不适用于固态媒体的优化。-o ssd

经常平衡 Btrfs 文件系统

使用操作系统实用程序(如 job)来平衡 Btrfs filesystem。这将回收未分配的块 并有助于防止文件系统不必要地填满。你不能 重新平衡完全完整的 Btrfs 文件系统,除非您添加额外的物理文件系统 将设备块添加到文件系统中。cron

请参阅 Btrfs 维基

使用快速存储

固态驱动器 (SSD) 的读取和写入速度比旋转磁盘更快。

将卷用于写入密集型工作负载

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