BTRFS 存储驱动程序
Btrfs 是一种支持多种高级存储技术的写时复制文件系统,非常适合 Docker。Btrfs 包含在主线 Linux 内核中。
Docker 的 btrfs
存储驱动程序利用 Btrfs 的许多功能来管理镜像和容器。这些功能包括块级操作、精简配置、写时复制快照和易于管理。您可以将多个物理块设备组合到单个 Btrfs 文件系统中。
本页将 Docker 的 Btrfs 存储驱动程序称为 btrfs
,将整体 Btrfs 文件系统称为 Btrfs。
注意
btrfs
存储驱动程序仅支持在 SLES、Ubuntu 和 Debian 系统上的 Docker Engine CE。
先决条件
如果您满足以下先决条件,则支持 btrfs
仅建议在 Ubuntu 或 Debian 系统上的 Docker CE 中使用
btrfs
。更改存储驱动程序会使您已创建的任何容器在本地系统上无法访问。使用
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 上基本相同。
停止 Docker。
将
/var/lib/docker/
的内容复制到备份位置,然后清空/var/lib/docker/
的内容。$ sudo cp -au /var/lib/docker /var/lib/docker.bk $ sudo rm -rf /var/lib/docker/*
将您的专用块设备或设备格式化为 Btrfs 文件系统。此示例假设您使用的是名为
/dev/xvdf
和/dev/xvdg
的两个块设备。仔细检查块设备名称,因为这是一个破坏性操作。$ sudo mkfs.btrfs -f /dev/xvdf /dev/xvdg
Btrfs 有更多选项,包括条带化和 RAID。请参阅Btrfs 文档。
将新的 Btrfs 文件系统安装到
/var/lib/docker/
挂载点。您可以指定用于创建 Btrfs 文件系统的任何块设备。$ sudo mount -t btrfs /dev/xvdf /var/lib/docker
注意
通过向
/etc/fstab
添加条目,使更改在重新启动后保持不变。将
/var/lib/docker.bk
的内容复制到/var/lib/docker/
。$ sudo cp -au /var/lib/docker.bk/* /var/lib/docker/
配置 Docker 以使用
btrfs
存储驱动程序。即使/var/lib/docker/
现在使用 Btrfs 文件系统,这也是必需的。编辑或创建文件/etc/docker/daemon.json
。如果这是一个新文件,请添加以下内容。如果它是一个现有文件,则仅添加键和值,如果它不是在结束大括号 (}
) 之前的最后一行,请注意以逗号结尾。{ "storage-driver": "btrfs" }
请参阅守护程序参考文档中每个存储驱动程序的所有存储选项
启动 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 <...>
准备好后,删除
/var/lib/docker.bk
目录。
管理 Btrfs 卷
Btrfs 的优势之一在于能够轻松管理 Btrfs 文件系统,无需卸载文件系统或重启 Docker。
当空间不足时,Btrfs 会自动以大约 1 GB 的块大小扩展卷。
要向 Btrfs 卷添加块设备,请使用btrfs device add
和 btrfs 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 主机上创建镜像和容器的高级过程如下所示
镜像的基础层存储在
/var/lib/docker/btrfs/subvolumes
下的 Btrfs *子卷*中。后续的镜像层存储为父层的子卷或快照的 Btrfs *快照*,但包含此层引入的更改。这些差异存储在块级别。
容器的可写层是最终镜像层的 Btrfs 快照,其中包含运行容器引入的差异。这些差异存储在块级别。
btrfs
如何处理容器的读写操作
读取文件
容器是镜像的节省空间的快照。快照中的元数据指向存储池中的实际数据块。这与子卷相同。因此,对快照执行的读取与对子卷执行的读取基本相同。
写入文件
总的来说需要注意的是,使用 Btrfs 写入和更新大量小文件会导致性能下降。
考虑三个场景,其中容器以写访问方式打开 Btrfs 文件。
写入新文件
向容器写入新文件会调用按需分配操作,以便向容器的快照分配新的数据块。然后将文件写入此新空间。按需分配操作是所有 Btrfs 写入的固有操作,与向子卷写入新数据相同。因此,向容器的快照写入新文件以 Btrfs 原生速度运行。
修改现有文件
更新容器中的现有文件是一个写时复制操作(重定向写入是 Btrfs 术语)。从当前存在文件的层读取原始数据,并且仅将修改的块写入容器的可写层。接下来,Btrfs 驱动程序更新快照中的文件系统元数据以指向此新数据。此行为会产生少量开销。
删除文件或目录
如果容器删除下层中存在的文 件或目录,Btrfs 将屏蔽下层中文件或目录的存在。如果容器创建文件然后删除它,则此操作在 Btrfs 文件系统本身中执行,并且空间将被回收。
Btrfs 和 Docker 性能
有几个因素会影响btrfs
存储驱动程序下 Docker 的性能。
注意
许多这些因素可以通过对写入密集型工作负载使用 Docker 卷来减轻,而不是依赖于将数据存储在容器的可写层中。但是,在 Btrfs 的情况下,除非
/var/lib/docker/volumes/
没有由 Btrfs 支持,否则 Docker 卷仍然会受到这些缺点的影响。
页面缓存
Btrfs 不支持页面缓存共享。这意味着每个访问同一文件的进程都会将文件复制到 Docker 主机的内存中。因此,对于高密度用例(例如 PaaS),btrfs
驱动程序可能不是最佳选择。
小写入
执行大量小写入的容器(此使用模式与在短时间内启动和停止许多容器时发生的情况相匹配)会导致 Btrfs 块的使用效率低下。这可能会过早地填满 Btrfs 文件系统,并导致 Docker 主机空间不足。使用btrfs filesys show
密切监控 Btrfs 设备上的可用空间量。
顺序写入
Btrfs 在写入磁盘时使用日志记录技术。这可能会影响顺序写入的性能,最多可降低 50% 的性能。
碎片
碎片是像 Btrfs 这样的写时复制文件系统的自然副产品。许多小的随机写入会加剧这个问题。碎片可能表现为使用 SSD 时出现 CPU 峰值,或使用旋转磁盘时出现磁头寻道过多。这两个问题都会损害性能。
如果您的 Linux 内核版本为 3.9 或更高版本,则可以在挂载 Btrfs 卷时启用autodefrag
功能。在将此功能部署到生产环境之前,请在您自己的工作负载上测试此功能,因为某些测试表明它会对性能产生负面影响。
SSD 性能
Btrfs 包含针对 SSD 介质的原生优化。要启用这些功能,请使用-o ssd
挂载选项挂载 Btrfs 文件系统。这些优化包括通过避免不适用于固态介质的优化(例如寻道优化)来增强 SSD 写入性能。
经常平衡 Btrfs 文件系统
使用操作系统实用程序(例如cron
作业)定期在非高峰时段平衡 Btrfs 文件系统。这将回收未分配的块,并有助于防止文件系统不必要地填满。除非您向文件系统添加其他物理块设备,否则您无法重新平衡完全填满的 Btrfs 文件系统。
请参阅Btrfs Wiki。
使用快速存储
固态硬盘 (SSD) 提供比旋转磁盘更快的读写速度。
对写入密集型工作负载使用卷
对于写入密集型工作负载,卷提供最佳且最可预测的性能。这是因为它们绕过了存储驱动程序,并且不会产生精简配置和写时复制带来的任何潜在开销。卷还有其他好处,例如允许您在容器之间共享数据,即使没有运行的容器使用它们也能持久存在。