diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 3a3d3ca..a6b747d 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -40,7 +40,9 @@ export default defineConfig({ link: '/docs/storage/drivers/', items: [ { text: "选择存储驱动程序", link: '/docs/storage/drivers/select-storage-driver' }, - { text: "BTRFS storage driver", link: '/docs/storage/drivers/1' }, + { text: "BTRFS 存储驱动程序", link: '/docs/storage/drivers/btrfs-driver/' }, + { text: "设备映射器存储驱动程序(已弃用)", link: '/docs/storage/drivers/device-mapper-driver/'}, + { text: "OverlayFS 存储驱动程序", link: '/docs/storage/drivers/overlayfs-driver/'} ] }, { text: 'containerd 映像存储', link: '/docs/storage/container-image-store' } diff --git a/docs/storage/drivers/btfs_container_layer.webp b/docs/storage/drivers/btfs_container_layer.webp new file mode 100644 index 0000000..7930845 Binary files /dev/null and b/docs/storage/drivers/btfs_container_layer.webp differ diff --git a/docs/storage/drivers/btfs_pool.webp b/docs/storage/drivers/btfs_pool.webp new file mode 100644 index 0000000..6722175 Binary files /dev/null and b/docs/storage/drivers/btfs_pool.webp differ diff --git a/docs/storage/drivers/btfs_snapshots.webp b/docs/storage/drivers/btfs_snapshots.webp new file mode 100644 index 0000000..d041fcf Binary files /dev/null and b/docs/storage/drivers/btfs_snapshots.webp differ diff --git a/docs/storage/drivers/btfs_subvolume.webp b/docs/storage/drivers/btfs_subvolume.webp new file mode 100644 index 0000000..748557a Binary files /dev/null and b/docs/storage/drivers/btfs_subvolume.webp differ diff --git a/docs/storage/drivers/btrfs-driver.md b/docs/storage/drivers/btrfs-driver.md new file mode 100644 index 0000000..0abd6d5 --- /dev/null +++ b/docs/storage/drivers/btrfs-driver.md @@ -0,0 +1,170 @@ +--- +outline: [2,5] +--- + +# BTRFS 存储驱动程序 +Btrfs 是一种写入时复制文件系统,支持许多高级存储技术,非常适合 Docker。Btrfs 包含在主线 Linux 内核中。 + +Docker 的 `btrfs` 存储驱动程序利用许多 Btrfs 功能进行映像和容器管理。这些功能包括块级操作、精简配置、写入时复制快照和易于管理。您可以将多个物理块设备合并到一个 Btrfs 文件系统中。 + +本页将 Docker 的 Btrfs 存储驱动程序称为 `btrfs`,将整个 Btrfs 文件系统称为 Btrfs。 + +:::tip 注意 +`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` 支持。要检查这一点,请运行以下命令: +```bash +grep btrfs /proc/filesystems + +btrfs +``` +- 要在操作系统级别管理 Btrfs 文件系统,您需要 `btrfs` 命令。如果您没有此命令,请安装 `btrfsprogs` package (SLES) 或 `btrfs-tools` package (Ubuntu) 的 Package。 + +## 配置 Docker 以使用 btrfs 存储驱动程序 +此过程在 SLES 和 Ubuntu 上基本相同。 +1. 停止 Docker。 +2. 将 `/var/lib/docker/` 的内容复制到备份位置,然后清空 `/var/lib/docker/` 的内容: +```bash +sudo cp -au /var/lib/docker /var/lib/docker.bk +sudo rm -rf /var/lib/docker/* +``` +3. 将专用块设备格式化为 Btrfs 文件系统。此示例假定您使用的是两个名为 `/dev/xvdf` 和 `/dev/xvdg` 中。仔细检查块设备名称,因为这是一个破坏性操作。 +```bash +sudo mkfs.btrfs -f /dev/xvdf /dev/xvdg +``` +Btrfs 还有更多选项,包括条带化和 RAID。请参阅 [Btrfs 文档][0]。 +4. 将新的 Btrfs 文件系统挂载到 `/var/lib/docker/` 挂载点。您可以指定用于创建 Btrfs 文件系统的任何块设备。 +```bash +sudo mount -t btrfs /dev/xvdf /var/lib/docker +``` +:::tip 注意 +通过添加一个条目来使更改在重新启动后永久生效 `/etc/fstab` 。 +::: +5. 将 `/var/lib/docker.bk` 的内容复制到 `/var/lib/docker/`。 +```bash +sudo cp -au /var/lib/docker.bk/* /var/lib/docker/ +``` +6. 配置 Docker 以使用`btrfs`存储驱动程序。即使`/var/lib/docker/`现在使用 Btrfs 文件系统,这也是必需的。编辑或创建文件`/etc/docker/daemon.json` 。如果是新文件,添加以下内容。如果它是现有文件,则仅添加键和值,如果不是结束大括号 ( `}` ) 之前的最后一行,请小心地以逗号结束该行。 +```json +{ + "storage-driver": "btrfs" +} +``` +查看每个存储驱动程序的所有存储选项 [守护进程参考文档][1] +7. 启动 Docker。当它运行时,验证`btrfs`是否被用作存储驱动程序。 +```bash +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 add`和 `btrfs filesystem balance`命令。 +```bash +sudo btrfs device add /dev/svdh /var/lib/docker + +sudo btrfs filesystem balance /var/lib/docker +``` + +:::note 笔记 +虽然您可以在 Docker 运行时执行这些操作,但性能会受到影响。最好计划一个中断窗口来平衡 Btrfs 文件系统。 +::: + +## `btrfs`存储驱动程序如何工作 +`btrfs`存储驱动程序的工作方式与其他存储驱动程序不同,因为整个`/var/lib/docker/`目录都存储在 Btrfs 卷上。 + +### 磁盘上的映像和容器层 +有关图像层和可写容器层的信息存储在 `/var/lib/docker/btrfs/subvolumes/` 。该子目录包含每个图像或容器层一个目录,以及从一层及其所有父层构建的统一文件系统。子卷本质上是写时复制,并从底层存储池按需分配空间。它们还可以嵌套和快照。下图显示了 4 个子卷。 “子卷 2”和“子卷 3”是嵌套的,而“子卷 4”显示其自己的内部目录树。 + +![btfs_subvolume](./btfs_subvolume.webp) + +仅图像的基础层被存储为真正的子体积。所有其他层都存储为快照,其中仅包含该层中引入的差异。您可以创建快照的快照,如下图所示。 + +![btfs_snapshots](./btfs_snapshots.webp) + +在磁盘上,快照看起来和感觉上都像子卷,但实际上它们要小得多并且更节省空间。写时复制用于最大化存储效率并最小化层大小,并且容器可写层中的写入在块级别进行管理。下图显示了子卷及其快照共享数据。 + +![btfs_pool](./btfs_pool.webp) + +为了最大程度地提高效率,当容器需要更多空间时,会以大约 1 GB 大小的块进行分配。 + +Docker 的`btrfs`存储驱动程序将每个镜像层和容器存储在其自己的 Btrfs 子卷或快照中。映像的基础层存储为子卷,而子映像层和容器存储为快照。如下图所示。 + +![btfs_container_layer](./btfs_container_layer.webp) + +在运行`btrfs`驱动程序的 Docker 主机上创建映像和容器的高级流程如下: +1. 图像的基础层存储在 Btrfs子卷中 `/var/lib/docker/btrfs/subvolumes` 。 +2. 后续映像层存储为父层子卷或快照的 Btrfs快照,但包含该层引入的更改。这些差异存储在块级别。 +3. 容器的可写层是最终镜像层的 Btrfs 快照,其中存在由运行容器引入的差异。这些差异存储在块级别。 + +## 容器如何与btrfs一起读写 +### 读取文件 +容器是镜像的节省空间的快照。快照中的元数据指向存储池中的实际数据块。这与子卷相同。因此,对快照执行的读取本质上与对子卷执行的读取相同。 +### 写入文件 +一般注意事项是,使用 Btrfs 写入和更新大量小文件可能会导致性能下降。 + +考虑容器使用 Btrfs 打开文件进行写访问的三种场景。 +### 写入新文件 +将新文件写入容器会调用按需分配操作,将新数据块分配给容器的快照。然后文件被写入这个新空间。按需分配操作是 Btrfs 的所有写入操作的本机操作,与将新数据写入子卷相同。因此,将新文件写入容器的快照将以本机 Btrfs 速度运行。 +### 修改现有文件 +更新容器中的现有文件是写时复制操作(写时重定向是 Btrfs 术语)。从文件当前所在的层读取原始数据,仅将修改的块写入容器的可写层。接下来,Btrfs 驱动程序更新快照中的文件系统元数据以指向此新数据。此行为会产生少量开销。 +### 删除文件或目录 +如果容器删除了下层存在的文件或目录,Btrfs 会屏蔽下层文件或目录的存在。如果容器创建一个文件然后删除它,则该操作将在 Btrfs 文件系统本身中执行,并回收空间。 +## Btrfs 和 Docker 性能 +`btrfs`下影响Docker性能的因素有几个 存储驱动程序。 + +:::note 笔记 +通过使用 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 介质的本机优化。要启用这些功能,请使用`-o ssd`挂载选项挂载 Btrfs 文件系统。这些优化包括通过避免优化(例如不适用于固态介质的寻道优化)来增强 SSD 写入性能。 +### 经常平衡 Btrfs 文件系统 +使用操作系统实用程序(例如`cron`作业)在非高峰时段定期平衡 Btrfs 文件系统。这会回收未分配的块并有助于防止文件系统不必要地填满。除非向文件系统添加额外的物理块设备,否则无法重新平衡完全满的 Btrfs 文件系统。 + +请参阅 [维基百科](https://btrfs.wiki.kernel.org/index.php/Balance_Filters#Balancing_to_fix_filesystem_full_errors)。 +### 使用快速存储 +固态硬盘 (SSD) 提供比旋转磁盘更快的读取和写入速度。 +### 使用卷来处理写入量大的工作负载 +卷为写入密集型工作负载提供最佳且最可预测的性能。这是因为它们绕过存储驱动程序,并且不会产生精简配置和写入时复制带来的任何潜在开销。卷还有其他好处,例如允许您在容器之间共享数据,甚至在没有正在运行的容器使用它们时也能保留数据。 + +## 相关信息 +- [卷][20] +- [了解镜像、容器和存储驱动程序][21] +- [选择存储驱动程序][22] + +[0]:https://btrfs.wiki.kernel.org/index.php/Using_Btrfs_with_Multiple_Devices +[1]:https://docs.docker.com/reference/cli/dockerd/#options-per-storage-driver +[20]:# +[21]:# +[22]:./select-storage-driver \ No newline at end of file diff --git a/docs/storage/drivers/device-mapper-driver.md b/docs/storage/drivers/device-mapper-driver.md new file mode 100644 index 0000000..0276269 --- /dev/null +++ b/docs/storage/drivers/device-mapper-driver.md @@ -0,0 +1,528 @@ +--- +outline: [2,5] +--- + +# 设备映射器存储驱动程序(已弃用) +:::info 已启用 +设备映射器驱动程序 [已被弃用](https://docs.docker.com/engine/deprecated/#device-mapper-storage-driver), 并在 Docker Engine v25.0 中被删除。如果您使用设备映射器, 在升级到 Docker 之前,您必须迁移到受支持的存储驱动程序 引擎 v25.0。阅读 [Docker 存储驱动](./select-storage-driver) 支持的存储驱动程序页面。 +::: + +Device Mapper 是一个基于内核的框架,支持 Linux 上的许多高级卷管理技术。 Docker 的`devicemapper`存储驱动程序利用该框架的精简配置和快照功能来进行映像和容器管理。本文将 Device Mapper 存储驱动程序称为`devicemapper` ,将内核框架称为*Device Mapper* 。 + +对于支持它的系统, `devicemapper`支持包含在 Linux 内核中。但是,需要特定配置才能将其与 Docker 一起使用。 + +`devicemapper`驱动程序使用 Docker 专用的块设备,并在块级别(而不是文件级别)运行。这些设备可以通过向 Docker 主机添加物理存储来扩展,并且它们的性能比在操作系统 (OS) 级别使用文件系统更好。 + +## 先决条件 +- `devicemapper` 在 Docker Engine - 在 CentOS、Fedora、SLES 15、Ubuntu、Debian 或 RHEL 上运行的社区受支持。 +- `devicemapper` 需要安装 `lvm2` 和 `device-mapper-persistent-data` 包。 +- 更改存储驱动程序将使您已创建的任何容器在本地系统上都无法访问。使用 `docker save` 保存容器,并将现有镜像推送到 Docker Hub 或私有存储库,这样您以后就不需要重新创建它们。 + +## 使用 `devicemapper` 存储驱动程序配置 Docker +在执行这些过程之前,您必须首先满足所有 [先决条件](#先决条件)。 +### 配置 `loop-lvm` 模式进行测试 +此配置仅适用于测试。 `loop-lvm`模式利用“环回”机制,允许读取和写入本地磁盘上的文件,就像它们是实际的物理磁盘或块设备一样。然而,环回机制的添加以及与操作系统文件系统层的交互意味着 IO 操作可能会很慢并且会占用大量资源。使用环回设备也会引入竞争条件。然而,设置`loop-lvm`模式可以帮助识别基本问题(例如缺少用户空间包、内核驱动程序等),然后再尝试启用direct-lvm模式所需的更复杂的设置。 `loop-lvm`模式应该 因此仅用于在配置之前执行基本测试 `direct-lvm` ​​。 + +对于生产系统,请参阅 [为生产配置 direct-lvm 模式](#为生产配置 direct-lvm 模式)。 +1. 停止 Docker +```bash +sudo systemctl stop docker +``` +2. 编辑`/etc/docker/daemon.json` 。如果尚不存在,请创建它。假设该文件为空,添加以下内容。 +```json +{ + "storage-driver": "devicemapper" +} +``` +查看每个存储驱动程序的所有存储选项 [守护进程参考文档](https://docs.docker.com/reference/cli/dockerd/#options-per-storage-driver) + +如果`daemon.json`文件包含格式错误的 JSON,则 Docker 不会启动。 +3. 启动 Docker。 +```bash +sudo systemctl start docker +``` +4. 验证守护程序是否正在使用`devicemapper`存储驱动程序。使用 `docker info`命令并查找`Storage Driver` 。 +```bash +docker info + + Containers: 0 + Running: 0 + Paused: 0 + Stopped: 0 + Images: 0 + Server Version: 17.03.1-ce + Storage Driver: devicemapper + Pool Name: docker-202:1-8413957-pool + Pool Blocksize: 65.54 kB + Base Device Size: 10.74 GB + Backing Filesystem: xfs + Data file: /dev/loop0 + Metadata file: /dev/loop1 + Data Space Used: 11.8 MB + Data Space Total: 107.4 GB + Data Space Available: 7.44 GB + Metadata Space Used: 581.6 KB + Metadata Space Total: 2.147 GB + Metadata Space Available: 2.147 GB + Thin Pool Minimum Free Space: 10.74 GB + Udev Sync Supported: true + Deferred Removal Enabled: false + Deferred Deletion Enabled: false + Deferred Deleted Device Count: 0 + Data loop file: /var/lib/docker/devicemapper/data + Metadata loop file: /var/lib/docker/devicemapper/metadata + Library Version: 1.02.135-RHEL7 (2016-11-16) +<...> +``` +该主机在`loop-lvm`模式下运行,生产系统不支持该模式。 `Data loop file`这一事实表明了这一点 和`Metadata loop file`位于以下文件上 `/var/lib/docker/devicemapper` 。这些是环回安装的 稀疏文件。对于生产系统,请参阅 [为生产配置 direct-lvm 模式](#为生产配置-direct-lvm-模式)。 +### 为生产配置 direct-lvm 模式 +使用`devicemapper`存储驱动程序的生产主机必须使用`direct-lvm` 模式。此模式使用块设备创建精简池。这比 使用环回设备,更有效地使用系统资源,并阻止 设备可以根据需要增长。然而,比`loop-lvm`需要更多的设置 模式。 + +当你满足了 [先决条件](#先决条件),请按照以下步骤配置 Docker 以在中使用`devicemapper`存储驱动程序 `direct-lvm​​`模式。 + +:::warning 警告 +更改存储驱动程序会使您已创建的任何容器在本地系统上无法访问。使用`docker save`保存容器,并将现有镜像推送到 Docker Hub 或私有存储库,这样您以后就不需要重新创建它们。 +::: + +### 允许Docker配置direct-lvm模式 +Docker可以为你管理块设备,简化`direct-lvm`的配置 模式。这仅适用于新的 Docker 设置。你只能使用一个 单块设备。如果需要使用多个块设备, 而是[手动配置 direct-lvm 模式](#手动配置 direct-lvm 模式)。提供以下新配置选项: +选项 | 描述 | 必需的? | 默认 | 例子 +| - | - | - | - | - | +`dm.directlvm_device` | 要为`direct-lvm`配置的块设备的路径。| 是 | | `dm.directlvm_device="/dev/xvdf"` +`dm.thinp_percent` | 传入的块设备中用于存储的空间百分比。 | 不 | 95 | `dm.thinp_percent=95` +`dm.thinp_metapercent` | 传入的块设备中用于元数据存储的空间百分比。| 不 | 1 | `dm.thinp_metapercent=1` +`dm.thinp_autoextend_threshold` | lvm 应自动扩展精简池的阈值(占总存储空间的百分比)。 | 不 | 80 | `dm.thinp_autoextend_threshold=80` +`dm.thinp_autoextend_percent` | 触发自动扩展时精简池增加的百分比。| 不 | 20 | `dm.thinp_autoextend_percent=20` +`dm.directlvm_device_force` | 是否格式化块设备,即使其上已存在文件系统。如果设置为false并且存在文件系统,则会记录错误并且文件系统保持不变。 | 不 | false | `dm.directlvm_device_force=true` + +编辑`daemon.json`文件并设置适当的选项,然后重新启动 Docker 以使更改生效。以下`daemon.json`配置设置上表中的所有选项。 + +```json +{ + "storage-driver": "devicemapper", + "storage-opts": [ + "dm.directlvm_device=/dev/xdf", + "dm.thinp_percent=95", + "dm.thinp_metapercent=1", + "dm.thinp_autoextend_threshold=80", + "dm.thinp_autoextend_percent=20", + "dm.directlvm_device_force=false" + ] +} +``` +查看每个存储驱动程序的所有存储选项 [守护进程参考文档](https://docs.docker.com/reference/cli/dockerd/#options-per-storage-driver) + +重新启动 Docker 以使更改生效。 Docker 调用命令来为您配置块设备。 + +:::warning 警告 +不支持在 Docker 为您准备好块设备后更改这些值,并且会导致错误。 +::: + +你还需要 [执行定期维护任务][定期维护任务]。 + +### 手动配置direct-lvm模式 +以下过程创建一个配置为精简池的逻辑卷,以用作存储池的后备。它假设您在`/dev/xvdf`处有一个备用块设备,并且有足够的可用空间来完成任务。您的环境中的设备标识符和卷大小可能有所不同,您应该在整个过程中替换您自己的值。该过程还假设 Docker 守护程序处于`stopped`状态。 +1. 确定您要使用的块设备。该设备位于 `/dev/` (例如`/dev/xvdf` )并且需要足够的可用空间来存储主机运行的工作负载的映像和容器层。固态硬盘是理想的选择。 +2. 停止 Docker。 +```bash +sudo systemctl stop docker +``` +3. 安装以下软件包: + - RHEL / CentOS : `device-mapper-persistent-dat`a 、 `lvm2`和所有依赖项 + - Ubuntu / Debian / SLES 15 : `thin-provisioning-tools` 、 `lvm2`和所有依赖项 +4. 使用以下命令在步骤 1 中的块设备上创建物理卷 `pvcreate`命令。将`/dev/xvdf`替换为您的设备名称。 +:::warning 警告 +接下来的几个步骤具有破坏性,因此请确保您指定了正确的设备。 +::: +```bash +sudo pvcreate /dev/xvdf + +Physical volume "/dev/xvdf" successfully created. +``` +5. 使用`vgcreate`在同一设备上创建`docker`卷组 命令。 +```bash +sudo vgcreate docker /dev/xvdf + +Volume group "docker" successfully created +``` +6. 使用以下命令创建两个名为`thinpool`和`thinpoolmeta`的逻辑卷 `lvcreate`命令。最后一个参数指定可用空间量,以允许在空间不足时自动扩展数据或元数据,作为临时的权宜之计。这些是推荐值。 +```bash +sudo lvcreate --wipesignatures y -n thinpool docker -l 95%VG + +Logical volume "thinpool" created. + +sudo lvcreate --wipesignatures y -n thinpoolmeta docker -l 1%VG + +Logical volume "thinpoolmeta" created. +``` +7. 使用`lvconvert`命令将卷转换为精简池以及精简池元数据的存储位置。 +```bash +sudo lvconvert -y \ +--zero n \ +-c 512K \ +--thinpool docker/thinpool \ +--poolmetadata docker/thinpoolmeta + +WARNING: Converting logical volume docker/thinpool and docker/thinpoolmeta to +thin pool's data and metadata volumes with metadata wiping. +THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.) +Converted docker/thinpool to thin pool. +``` +8. 通过`lvm`配置文件配置精简池的自动扩展。 +```bash +sudo vi /etc/lvm/profile/docker-thinpool.profile +``` +9. 指定`thin_pool_autoextend_threshold`和`thin_pool_autoextend_percent` 价值观。 + +`thin_pool_autoextend_threshold`是`lvm`之前使用的空间百分比 尝试自动扩展可用空间(100 = 禁用,不推荐)。 + +`thin_pool_autoextend_percent`是自动扩展时添加到设备的空间量(0 = 禁用)。 + +下面的示例在磁盘使用率达到 80% 时增加 20% 的容量。 +```text +activation { + thin_pool_autoextend_threshold=80 + thin_pool_autoextend_percent=20 +} +``` +保存文件。 +10. 使用`lvchange`命令应用 LVM 配置文件。 +```bash +sudo lvchange --metadataprofile docker-thinpool docker/thinpool + +Logical volume docker/thinpool changed. +``` +11. 确保启用逻辑卷监控。 +```bash +sudo lvs -o+seg_monitor + +LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert Monitor +thinpool docker twi-a-t--- 95.00g 0.00 0.01 not monitored +``` +如果`Monitor`列中的输出报告如上所示,则卷为 `not monitored` ,则需要显式启用监控。如果没有此步骤,无论应用的配置文件中的任何设置如何,都不会发生逻辑卷的自动扩展。 + +```bash +sudo lvchange --monitor y docker/thinpool +``` +通过运行 `sudo lvs -o+seg_monitor` 命令。`Monitor` 列现在应报告正在监控逻辑卷。 + +12. 如果您以前曾在此主机上运行过 Docker,或者如果 `/var/lib/docker/` 存在,将其移开,以便 Docker 可以使用新的 LVM 池 存储 Image 和 Containers 的内容。 + +```bash +sudo su - +# mkdir /var/lib/docker.bk +# mv /var/lib/docker/* /var/lib/docker.bk +# exit +``` +如果以下任何步骤失败,并且您需要恢复,您可以删除 `/var/lib/docker` 并将其替换为 `/var/lib/docker.bk`。 + +13. 编辑 `/etc/docker/daemon.json` 并配置 `devicemapper` 存储驱动程序。如果文件以前为空,则它现在应包含以下内容: +```bash +{ + "storage-driver": "devicemapper", + "storage-opts": [ + "dm.thinpooldev=/dev/mapper/docker-thinpool", + "dm.use_deferred_removal=true", + "dm.use_deferred_deletion=true" + ] +} +``` + +14. 启动 Docker。 + +systemd: +```bash +sudo systemctl start docker +``` +service: +```bash +sudo service docker start +``` + +15. 使用 `docker info` 验证 Docker 是否正在使用新配置。 +```bash +docker info + +Containers: 0 + Running: 0 + Paused: 0 + Stopped: 0 +Images: 0 +Server Version: 17.03.1-ce +Storage Driver: devicemapper + Pool Name: docker-thinpool + Pool Blocksize: 524.3 kB + Base Device Size: 10.74 GB + Backing Filesystem: xfs + Data file: + Metadata file: + Data Space Used: 19.92 MB + Data Space Total: 102 GB + Data Space Available: 102 GB + Metadata Space Used: 147.5 kB + Metadata Space Total: 1.07 GB + Metadata Space Available: 1.069 GB + Thin Pool Minimum Free Space: 10.2 GB + Udev Sync Supported: true + Deferred Removal Enabled: true + Deferred Deletion Enabled: true + Deferred Deleted Device Count: 0 + Library Version: 1.02.135-RHEL7 (2016-11-16) +<...> +``` +如果 Docker 配置正确,则 `Data file` (数据文件) 和 `Metadata file` (元数据文件) 为空,存储池名称为 `docker-thinpool` 。 + +16. 验证配置正确后,您可以删除 `/var/lib/docker.bk` 目录,其中包含前面的配置。 +```bash +sudo rm -rf /var/lib/docker.bk +``` + +## 管理 devicemapper +### 监视精简池 +不要单独依赖 LVM 自动扩展。卷组会自动扩展,但卷仍可能填满。您可以使用 `lvs` 或 `lvs -a` 监控卷上的可用空间。考虑在 OS 级别使用监控工具,例如 Nagios。 + +要查看 LVM 日志,您可以使用 `journalctl`: + +```bash +sudo journalctl -fu dm-event.service +``` + +如果反复遇到精简池问题,则可以设置存储选项 `dm.min_free_space` 中 `/etc/docker/daemon.json` 中。例如,将其设置为 `10` 可确保 当可用空间等于或接近 10% 时,操作失败并显示警告。 请参阅 [Engine 守护程序参考中的 storage driver 选项][0]。 + +### 增加正在运行的设备的容量 +您可以增加正在运行的精简池设备上的池容量。这是 如果数据的逻辑卷已满且卷组已满,则很有用 能力。具体过程取决于您是否使用 [loop-lvm 精简池][1]或 [direct-lvm thin pool 的 Thin Pool][2]。 +### 调整 loop-lvm thin 池的大小 +调整 loop-lvm thin 池大小的最简单方法是 使用 [device_tool 实用程序][3] 但你可以 [使用操作系统实用程序][4] 相反。 +### 使用 device_tool 实用程序 +一个名为 `device_tool.go` 的社区贡献的脚本在 [moby/moby][5] Github 存储库。您可以使用此工具调整 `loop-lvm` thin pool 的大小,从而避免上述漫长的过程。此工具不能保证有效,但您应该只在非生产系统上使用 `loop-lvm`。 + +如果您不想使用 `device_tool`,您可以 请[改为手动调整精简池的大小](#手动配置direct-lvm模式)。 +1. 要使用该工具,请克隆 Github 存储库,更改为 `contrib/docker-device-tool` 中的说明,然后按照 `README.md` 以编译该工具。 +2. 使用该工具。以下示例将精简池的大小调整为 200GB。 +```console +./device_tool resize 200GB +``` +### 使用操作系统实用程序 +如果您不想 [使用 device-tool 实用程序](#使用-device_tool-实用程序),您可以按照以下过程手动调整 `loop-lvm` 精简池的大小。 + +在 `loop-lvm` 模式下,一个 loopback 设备用于存储数据,另一个用于存储元数据。`loop-lvm` 模式仅支持用于测试,因为它具有明显的性能和稳定性缺点。 + +如果您使用的是 `loop-lvm` 模式,`docker info` 的输出将显示 `Data loop file` 和 `Metadata loop file` 的文件路径: +```bash +docker info |grep 'loop file' + + Data loop file: /var/lib/docker/devicemapper/data + Metadata loop file: /var/lib/docker/devicemapper/metadata +``` + +按照以下步骤增加精简池的大小。在此示例中,精简池为 100 GB,并增加到 200 GB。 +1. 列出设备的大小。 +```bash +sudo ls -lh /var/lib/docker/devicemapper/ + +total 1175492 +-rw------- 1 root root 100G Mar 30 05:22 data +-rw------- 1 root root 2.0G Mar 31 11:17 metadata +``` +2. 使用 `truncate` 命令将`data`增加到 200 G,该命令用于增大或减小文件大小。请注意,减小大小是一种破坏性操作。 +```bash +sudo truncate -s 200G /var/lib/docker/devicemapper/data +``` +3. 验证文件大小是否已更改。 +```bash +sudo ls -lh /var/lib/docker/devicemapper/ + +total 1.2G +-rw------- 1 root root 200G Apr 14 08:47 data +-rw------- 1 root root 2.0G Apr 19 13:27 metadata +``` +4. 环回文件在磁盘上已更改,但在内存中未更改。列出内存中环回设备的大小(以 GB 为单位)。重新加载它,然后再次列出大小。重新加载后,大小为 200 GB。 +```bash +echo $[ $(sudo blockdev --getsize64 /dev/loop0) / 1024 / 1024 / 1024 ] + +100 + +sudo losetup -c /dev/loop0 + +echo $[ $(sudo blockdev --getsize64 /dev/loop0) / 1024 / 1024 / 1024 ] + +200 +``` +5. 重新加载 devicemapper 精简池。 + - a 一个。首先获取池名称。存储池名称是第一个字段,由 `:`。此命令将提取它。 + ```bash + sudo dmsetup status | grep ' thin-pool ' | awk -F ': ' {'print $1'} + docker-8:1-123141-pool + ``` + - b. 转储精简池的设备映射器表。 + ```bash + sudo dmsetup table docker-8:1-123141-pool + 0 209715200 thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing + ``` + - c. 使用输出的第二个字段计算精简池的总扇区数。该数字以 512-k 扇区表示。一个 100G 文件有 209715200 个 512-k 扇区。如果将此数字翻倍到 200G,则得到419430400 512-k 扇区。 + - d. 使用以下三个 dmsetup 命令,使用新的扇区号重新加载精简池。 + ```bash + sudo dmsetup suspend docker-8:1-123141-pool + sudo dmsetup reload docker-8:1-123141-pool --table '0 419430400 thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing' + sudo dmsetup resume docker-8:1-123141-pool + ``` +### 调整 direct-lvm 精简池的大小 +要扩展 `direct-lvm `精简池,您需要首先将新的块设备附加到 Docker 主机,并记下内核为其分配的名称。在此示例中,新的块存储设备是 `/dev/xvdg`。 + +按照此过程扩展 `direct-lvm` 精简池,替换块设备和其他参数以适合您的情况。 + +1. 收集有关卷组的信息。 +使用 `pvdisplay` 命令查找精简池当前正在使用的物理块设备,以及卷组的名称。 +```bash +sudo pvdisplay |grep 'VG Name' + +PV Name /dev/xvdf +VG Name docker +``` +在以下步骤中,根据需要替换块存储设备或卷组名称。 +2. 使用带有 `VG name` 的 `vgextend` 命令扩展卷组 以及新块存储设备的名称。 +```bash +sudo vgextend docker /dev/xvdg + +Physical volume "/dev/xvdg" successfully created. +Volume group "docker" successfully extended +``` +3. 扩展 `docker/thinpool` 逻辑卷。此命令立即使用 100% 的卷,而不自动扩展。要改为扩展元数据精简池,请使用 `docker/thinpool_tmeta`。 +```bash +sudo lvextend -l+100%FREE -n docker/thinpool + +Size of logical volume docker/thinpool_tdata changed from 95.00 GiB (24319 extents) to 198.00 GiB (50688 extents). +Logical volume docker/thinpool_tdata successfully resized. +``` +4. 使用 `docker info` 输出中的 `Data Space Available` 字段验证新的精简池大小。如果您扩展了 `docker/thinpool_tmeta` 逻辑卷,请查找 `Metadata Space Available` (可用元数据空间)。 +```console +Storage Driver: devicemapper + Pool Name: docker-thinpool + Pool Blocksize: 524.3 kB + Base Device Size: 10.74 GB + Backing Filesystem: xfs + Data file: + Metadata file: + Data Space Used: 212.3 MB + Data Space Total: 212.6 GB + Data Space Available: 212.4 GB + Metadata Space Used: 286.7 kB + Metadata Space Total: 1.07 GB + Metadata Space Available: 1.069 GB +<...> +``` +### 重新启动后激活 `devicemapper` +如果重新启动主机并发现 `docker` 服务无法启动,请查找错误“Non existing device”。您需要使用以下命令重新激活逻辑卷: +```bash +sudo lvchange -ay docker/thinpool +``` + +## `devicemapper` 存储驱动程序的工作原理 +:::warning 重要 +不要直接操作 `/var/lib/docker/` 中。这些文件和目录由 Docker 管理。 +::: + +使用 `lsblk` 命令从操作系统的角度查看设备及其池: + +```bash +sudo lsblk + +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT +xvda 202:0 0 8G 0 disk +└─xvda1 202:1 0 8G 0 part / +xvdf 202:80 0 100G 0 disk +├─docker-thinpool_tmeta 253:0 0 1020M 0 lvm +│ └─docker-thinpool 253:2 0 95G 0 lvm +└─docker-thinpool_tdata 253:1 0 95G 0 lvm + └─docker-thinpool 253:2 0 95G 0 lvm +``` + +使用 `mount` 命令查看 Docker 正在使用的挂载点: + +```bash +mount |grep devicemapper +/dev/xvda1 on /var/lib/docker/devicemapper type xfs (rw,relatime,seclabel,attr2,inode64,noquota) +``` + +当您使用 `devicemapper` 时,Docker 将映像和层内容存储在 thinpool 中,并通过将它们挂载到 `/var/lib/docker/devicemapper/` 的子目录下来将它们公开给容器。 + +### 磁盘上的映像和容器层 +`/var/lib/docker/devicemapper/metadata/` 目录包含有关 Devicemapper 配置本身以及存在的每个映像和容器层的元数据。`devicemapper` 存储驱动程序使用快照,此元数据包括有关这些快照的信息。这些文件采用 JSON 格式。 + +`/var/lib/docker/devicemapper/mnt/` 目录包含存在的每个映像和容器层的挂载点。映像层挂载点为空,但容器的挂载点显示容器的文件系统,就像它在容器内部显示的那样。 + +### 图像分层和共享 +`devicemapper` 存储驱动程序使用专用的块设备而不是格式化的文件系统,并在块级别对文件进行操作,以便在写入时复制 (CoW) 操作期间获得最佳性能。 + +### 快照 +`devicemapper` 的另一个特点是它使用快照(有时也称为 *thin devices 或 virtual devices*),它们将每层中引入的差异存储为非常小的轻量级薄池。快照具有许多优势: +- 在容器之间共享的层仅在磁盘上存储一次,除非它们是可写的。例如,如果您有 10 个不同的图像,它们都基于 `alpine`,则 `alpine` 图像及其所有父图像在磁盘上只存储一次。 +- 快照是写入时复制 (CoW) 策略的实现。这意味着,仅当给定文件或目录被容器修改或删除时,才会将其复制到容器的可写层。 +- 由于 `devicemapper` 在块级别运行,因此可以同时修改可写层中的多个块。 +- 可以使用标准的操作系统级备份实用程序备份快照。只需复制 `/var/lib/docker/devicemapper/`。 + +### Devicemapper 工作流程 +当您使用 `devicemapper` 存储驱动程序启动 Docker 时,所有对象 与 映像和容器层的 `/var/lib/docker/devicemapper/` 中,它由一个或多个块级设备提供支持,环回设备(仅限测试)或物理磁盘。 + +- *基本设备*是最低级别的对象。这是 thin pool 本身。您可以使用 `docker info` 对其进行检查。它包含一个文件系统。此基本设备是每个映像和容器层的起点。基本设备是 Device Mapper implementation detail,而不是 Docker 层。 +- 有关基本设备和每个映像或容器层的元数据存储在 JSON 格式的 `/var/lib/docker/devicemapper/metadata/` 中。这些层是写入时复制快照,这意味着它们在与父层分叉之前是空的。 +- 每个容器的可写层都挂载在 `/var/lib/docker/devicemapper/mnt/` 中。每个只读映像层和每个已停止的容器都存在一个空目录。 + +每个图像图层都是其下方图层的快照。每个映像的最低层是池中存在的基本设备的快照。当您运行容器时,它是容器所基于的映像的快照。以下示例显示了具有两个正在运行的容器的 Docker 主机。第一个是 `ubuntu` 容器,第二个是 `busybox` 容器。 + +![](./two_dm_container.webp) + +## 容器读取和写入如何与 `devicemapper` 配合使用 +### 读取文件 +使用 `devicemapper` 时,读取发生在块级别。下图显示了在示例容器中读取单个块 (`0x44f`) 的高级过程。 + +![](./dm_container.webp) + +应用程序对容器中的块`0x44f`发出读取请求。由于容器是映像的精简快照,因此它没有数据块,但它有一个指针,指向它确实存在的最近父映像上的数据块,并从那里读取数据块。该块现在存在于容器的内存中。 + +### 写入文件 +编写新文件:使用 `devicemapper` 驱动程序,通过按需分配操作将新数据写入容器。新文件的每个块都分配在容器的可写层中,并且该块被写入该层。 + +更新现有文件:从文件所在的最近层读取文件的相关块。当容器写入文件时,只有修改后的块会写入容器的可写层。 + +删除文件或目录:当您删除容器的可写层中的文件或目录时,或者当映像层删除其父层中存在的文件时,`devicemapper` 存储驱动程序会拦截对该文件或目录的进一步读取尝试,并响应该文件或目录不存在。 + +写入然后删除文件:如果容器写入文件,然后删除该文件,则所有这些操作都发生在容器的可写层中。在这种情况下,如果您使用的是 `direct-lvm`,则会释放块。如果使用 `loop-lvm`,则可能无法释放块。这是不使用 `loop-lvm` 中。 + +## Device Mapper 和 Docker 性能 + +- `allocate-on demand` (按需分配) 性能影响: +`devicemapper` 存储驱动程序使用按需`分配 (allocate-on-demand)`操作将新块从精简池分配到容器的可写层。每个块为 64KB,因此这是用于写入的最小空间量。 +- 写入时复制性能影响:容器首次修改特定块时,该块将写入容器的可写层。由于这些写入发生在块级别而不是文件级别,因此性能影响最小。但是,写入大量块仍会对性能产生负面影响,在这种情况下,`devicemapper` 存储驱动程序的性能实际上可能比其他存储驱动程序差。对于写入密集型工作负载,您应该使用数据卷,这会完全绕过存储驱动程序。 + +### 性能最佳实践 +请记住这些事项,以便在使用 `devicemapper` 时最大限度地提高性能 storage 驱动程序。 + +- 使用 `direct-lvm`:`loop-lvm` 模式性能不佳,绝不应在生产中使用。 +- 使用快速存储:固态驱动器 (SSD) 提供比旋转磁盘更快的读取和写入速度。 +- 内存使用率:`devicemapper` 使用的内存比其他一些存储驱动程序多。每个启动的容器都会将其文件的一个或多个副本加载到内存中,具体取决于同时修改同一文件的块数。由于内存压力,`devicemapper` 存储驱动程序可能不是高密度使用案例中某些工作负载的正确选择。 +- 将卷用于写入密集型工作负载:卷为写入密集型工作负载提供最佳且最可预测的性能。这是因为它们绕过了存储驱动程序,并且不会产生精简配置和写入时复制引入的任何潜在开销。卷还有其他好处,例如允许您在容器之间共享数据,以及即使没有正在运行的容器正在使用卷也可以保留它们。 + +:::warning 注意 +使用 `devicemapper` 和 `json-file` 日志驱动程序时,容器生成的日志文件仍存储在 Docker 的 dataroot 目录中,默认为 `/var/lib/docker`。如果您的容器生成大量日志消息,这可能会导致磁盘使用量增加或由于磁盘已满而无法管理系统。您可以配置 [log 驱动程序][6]将容器日志存储在外部。 +::: + +## 相关信息 +- [卷][21] +- [了解映像、容器和存储驱动程序][22] +- [选择存储驱动程序][20] + + + +[定期维护任务]:#定期维护任务 +[0]:https://docs.docker.com/reference/cli/dockerd/#daemon-storage-driver +[1]:#调整-loop-lvm-thin-池的大小 +[2]:#调整-loop-lvm-thin-池的大小 +[3]:#使用-device_tool-实用程序 +[4]:#使用操作系统实用程序 +[5]:https://github.com/moby/moby/tree/master/contrib/docker-device-tool +[6]:https://docs.docker.com/engine/logging/configure/ + +[20]:./select-storage-driver +[21]:./../volume +[22]:./index \ No newline at end of file diff --git a/docs/storage/drivers/dm_container.webp b/docs/storage/drivers/dm_container.webp new file mode 100644 index 0000000..1b19e93 Binary files /dev/null and b/docs/storage/drivers/dm_container.webp differ diff --git a/docs/storage/drivers/overlay_constructs.webp b/docs/storage/drivers/overlay_constructs.webp new file mode 100644 index 0000000..4b44775 Binary files /dev/null and b/docs/storage/drivers/overlay_constructs.webp differ diff --git a/docs/storage/drivers/overlayfs-driver.md b/docs/storage/drivers/overlayfs-driver.md new file mode 100644 index 0000000..cf75596 --- /dev/null +++ b/docs/storage/drivers/overlayfs-driver.md @@ -0,0 +1,285 @@ +--- +outline: [2,5] +--- + +# OverlayFS 存储驱动程序 +OverlayFS 是一个联合文件系统。 + +本页将 Linux 内核驱动程序称为` OverlayFS`,将 Docker 存储驱动程序称为 `overlay2`。 +:::info 注意 +对于 `fuse-overlayfs` 驱动程序,请检查 [无根模式文档][rootless-doc]。 +::: + +## 先决条件 +OverlayFS 是推荐的存储驱动程序,如果您满足以下先决条件,则支持 OverlayFS: +- Linux 内核版本 4.0 或更高版本,或者使用内核版本 3.10.0-514 或更高版本的 RHEL 或 CentOS。 +- `xfs` 后备文件系统支持 `overlay2` 驱动程序,但仅在启用 `d_type=true` 的情况下受支持。 + 使用 `xfs_info` 验证 `ftype` 选项是否设置为 `1`。要格式化 `xfs` 文件系统中,请使用标志 `-n ftype=1`。 +- 更改存储驱动程序将使本地系统上的现有容器和映像无法访问。在更改存储驱动程序之前,使用 `docker save` 保存您构建的任何映像或将其推送到 Docker Hub 或私有注册表,这样您以后就不需要重新创建它们。 + +## 使用 `overlay2` 存储驱动程序配置 Docker +在执行此过程之前,您必须首先满足所有 [先决条件](#先决条件)。 + +以下步骤概述了如何配置 `overlay2` 存储驱动程序。 + +1. 停止 Docker。 +```bash +sudo systemctl stop docker +``` +2. 将 `/var/lib/docker` 的内容复制到临时位置。 +```bash +cp -au /var/lib/docker /var/lib/docker.bk +``` +3. 如果要使用与 `/var/lib/` 中,格式化文件系统并将其挂载到 `/var/lib/docker` 中。确保将此挂载添加到 `/etc/fstab` 以使其成为永久挂载。 +4. 编辑 `/etc/docker/daemon.json`。如果尚不存在,请创建它。假设文件为空,请添加以下内容。 +```json +{ + "storage-driver": "overlay2" +} +``` +如果 `daemon.json` 文件包含无效的 JSON,则 Docker 不会启动。 +5. 启动 Docker。 +```bash +sudo systemctl start docker +``` +6. 验证守护程序是否正在使用 `overlay2` 存储驱动程序。使用 `docker info` 命令并查找 `Storage Driver` 和 `Backing filesystem` (后备文件系统)。 +```bash +docker info + +Containers: 0 +Images: 0 +Storage Driver: overlay2 + Backing Filesystem: xfs + Supports d_type: true + Native Overlay Diff: true +<...> +``` +Docker 现在正在使用 `overlay2` 存储驱动程序,并已使用所需的 `lowerdir`、`upperdir`、`merged` 和 `workdir` 构造自动创建了覆盖挂载。 + +继续阅读有关 OverlayFS 如何在 Docker 容器中工作的详细信息,以及性能建议和有关其与不同后备文件系统的兼容性限制的信息。 + +## `overlay2` 驱动程序的工作原理 +OverlayFS 在单个 Linux 主机上对两个目录进行分层,并将它们显示为单个目录。这些目录称为 层,统一过程称为联合挂载。OverlayFS 将下层目录称为 `lowerdir`,将上层目录称为 `upperdir`。统一视图通过其自己的目录(称为 `merged`)公开。 + +`overlay2` 驱动程序原生支持多达 128 个较低的 OverlayFS 层。此功能为与层相关的 Docker 命令(如 `docker build` 和 `docker commit`)提供了更好的性能,并且占用的后备文件系统上的 inode 更少。 + +### 磁盘上的映像和容器层 +使用 `docker pull ubuntu` 下载五层镜像后,您可以在 `/var/lib/docker/overlay2` 下看到六个目录。 +:::warning 警告 +不要直接操作 `/var/lib/docker/` 中。这些文件和目录由 Docker 管理。 +::: +```bash +ls -l /var/lib/docker/overlay2 + +total 24 +drwx------ 5 root root 4096 Jun 20 07:36 223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7 +drwx------ 3 root root 4096 Jun 20 07:36 3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b +drwx------ 5 root root 4096 Jun 20 07:36 4e9fa83caff3e8f4cc83693fa407a4a9fac9573deaf481506c102d484dd1e6a1 +drwx------ 5 root root 4096 Jun 20 07:36 e8876a226237217ec61c4baf238a32992291d059fdac95ed6303bdff3f59cff5 +drwx------ 5 root root 4096 Jun 20 07:36 eca1e4e1694283e001f200a667bb3cb40853cf2d1b12c29feda7422fed78afed +drwx------ 2 root root 4096 Jun 20 07:36 l +``` + +新的 `l`(小写 `L`)目录包含作为符号链接的缩短图层标识符。这些标识符用于避免触及 `mount` 命令参数的页面大小限制。 + +```bash +ls -l /var/lib/docker/overlay2/l + +total 20 +lrwxrwxrwx 1 root root 72 Jun 20 07:36 6Y5IM2XC7TSNIJZZFLJCS6I4I4 -> ../3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/diff +lrwxrwxrwx 1 root root 72 Jun 20 07:36 B3WWEFKBG3PLLV737KZFIASSW7 -> ../4e9fa83caff3e8f4cc83693fa407a4a9fac9573deaf481506c102d484dd1e6a1/diff +lrwxrwxrwx 1 root root 72 Jun 20 07:36 JEYMODZYFCZFYSDABYXD5MF6YO -> ../eca1e4e1694283e001f200a667bb3cb40853cf2d1b12c29feda7422fed78afed/diff +lrwxrwxrwx 1 root root 72 Jun 20 07:36 NFYKDW6APBCCUCTOUSYDH4DXAT -> ../223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/diff +lrwxrwxrwx 1 root root 72 Jun 20 07:36 UL2MW33MSE3Q5VYIKBRN4ZAGQP -> ../e8876a226237217ec61c4baf238a32992291d059fdac95ed6303bdff3f59cff5/diff +``` + +最低层包含一个名为 `link` 的文件,其中包含缩短标识符的名称,以及一个名为 `diff` 的目录,其中包含该层的内容。 +```bash +ls /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/ + +diff link + +cat /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/link + +6Y5IM2XC7TSNIJZZFLJCS6I4I4 + +ls /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/diff + +bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var +``` +第二低的层和每个较高的层都包含一个名为 `lower` 的文件,该文件表示其父级,以及一个名为 `diff` 的目录,其中包含其内容。它还包含一个合并目录,该目录包含其父层和自身的统一内容,以及一个由 OverlayFS 内部使用的`work`(工作)目录。 +```bash +ls /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7 + +diff link lower merged work + +cat /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/lower + +l/6Y5IM2XC7TSNIJZZFLJCS6I4I4 + +ls /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/diff/ + +etc sbin usr var +``` + +要查看在 Docker 中使用 `overlay` (覆盖) 存储驱动程序时存在的挂载,请使用 `mount` 命令。为了提高可读性,下面的输出被截断。 +```bash +mount | grep overlay + +overlay on /var/lib/docker/overlay2/9186877cdf386d0a3b016149cf30c208f326dca307529e646afce5b3f83f5304/merged +type overlay (rw,relatime, +lowerdir=l/DJA75GUWHWG7EWICFYX54FIOVT:l/B3WWEFKBG3PLLV737KZFIASSW7:l/JEYMODZYFCZFYSDABYXD5MF6YO:l/UL2MW33MSE3Q5VYIKBRN4ZAGQP:l/NFYKDW6APBCCUCTOUSYDH4DXAT:l/6Y5IM2XC7TSNIJZZFLJCS6I4I4, +upperdir=9186877cdf386d0a3b016149cf30c208f326dca307529e646afce5b3f83f5304/diff, +workdir=9186877cdf386d0a3b016149cf30c208f326dca307529e646afce5b3f83f5304/work) +``` + +第二行上的` rw `显示`overlay`(覆盖)挂载是读写的。 + +下图显示了 Docker 映像和 Docker 容器的分层方式。image 层是 `lowerdir`,容器层是 `upperdir` 的 URL 中。如果图像具有多个图层,则使用多个 `lowerdir` 目录。统一视图通过一个名为 `merged` 的目录公开,该目录实际上是容器挂载点。 + +![overlay_constructs](./overlay_constructs.webp) + +如果图像层和容器层包含相同的文件,则容器层 (`upperdir`) 优先并掩盖图像层中存在相同文件。 + +要创建容器,`overlay2` 驱动程序将表示映像顶层的目录与容器的新目录组合在一起。图像的图层是叠加中的 `lowerdirs`,并且是只读的。容器的新目录是 `upperdir` 并且是可写的。 + +### 磁盘上的映像和容器层 +以下 `docker pull` 命令显示了一个 Docker 主机正在下载一个包含五个层的 Docker 镜像。 +```bash +docker pull ubuntu + +Using default tag: latest +latest: Pulling from library/ubuntu + +5ba4f30e5bea: Pull complete +9d7d19c9dc56: Pull complete +ac6ad7efd0f9: Pull complete +e7491a747824: Pull complete +a3ed95caeb02: Pull complete +Digest: sha256:46fb5d001b88ad904c5c732b086b596b92cfb4a4840a3abd0e35dbb6870585e4 +Status: Downloaded newer image for ubuntu:latest +``` + +### 图像图层 +每个映像层在 `/var/lib/docker/overlay/` 中都有自己的目录,其中包含其内容,如以下示例所示。映像层 ID 与目录 ID 不对应。 +:::warning 注意 +不要直接操作 `/var/lib/docker/` 中。这些文件和目录由 Docker 管理。 +::: + +```bash +ls -l /var/lib/docker/overlay/ + +total 20 +drwx------ 3 root root 4096 Jun 20 16:11 38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8 +drwx------ 3 root root 4096 Jun 20 16:11 55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358 +drwx------ 3 root root 4096 Jun 20 16:11 824c8a961a4f5e8fe4f4243dab57c5be798e7fd195f6d88ab06aea92ba931654 +drwx------ 3 root root 4096 Jun 20 16:11 ad0fe55125ebf599da124da175174a4b8c1878afe6907bf7c78570341f308461 +drwx------ 3 root root 4096 Jun 20 16:11 edab9b5e5bf73f2997524eebeac1de4cf9c8b904fa8ad3ec43b3504196aa3801 +``` + +图像图层目录包含该图层独有的文件以及与较低图层共享的数据的硬链接。这允许有效地使用磁盘空间。 + +```bash +ls -i /var/lib/docker/overlay2/38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8/root/bin/ls + +19793696 /var/lib/docker/overlay2/38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8/root/bin/ls + +ls -i /var/lib/docker/overlay2/55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358/root/bin/ls + +19793696 /var/lib/docker/overlay2/55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358/root/bin/ls +``` + +#### 容器层 +容器也存在于 Docker 主机的文件系统中的磁盘上,位于 `/var/lib/docker/overlay/` 中。如果使用 `ls -l` 命令列出正在运行的容器的子目录,则存在三个目录和一个文件: +```bash +ls -l /var/lib/docker/overlay2/ + +total 16 +-rw-r--r-- 1 root root 64 Jun 20 16:39 lower-id +drwxr-xr-x 1 root root 4096 Jun 20 16:39 merged +drwxr-xr-x 4 root root 4096 Jun 20 16:39 upper +drwx------ 3 root root 4096 Jun 20 16:39 work +``` + +`lower-id` 文件包含容器所基于的映像顶层的 ID,即 OverlayFS `lowerdir`。 + +```bash +cat /var/lib/docker/overlay2/ec444863a55a9f1ca2df72223d459c5d940a721b2288ff86a3f27be28b53be6c/lower-id + +55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358 +``` + +`upper` 目录包含容器的读写层的内容,对应于 OverlayFS `upperdir`。 + +`merged` (合并)的目录是 `lowerdir` 和 `upperdirs` 的联合挂载,它包含正在运行的容器中的文件系统视图。 + +`work` (工作)目录是 OverlayFS 的内部目录。 + +要查看将 `overlay2` 存储驱动程序与 Docker 一起使用时存在的挂载,请使用 `mount` 命令。为了提高可读性,以下输出被截断。 + +```bash +mount | grep overlay + +overlay on /var/lib/docker/overlay2/l/ec444863a55a.../merged +type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/55f1e14c361b.../root, +upperdir=/var/lib/docker/overlay2/l/ec444863a55a.../upper, +workdir=/var/lib/docker/overlay2/l/ec444863a55a.../work) +``` + +第二行上的 `rw` 显示`overlay`(覆盖)挂载是读写的。 + +## 容器读取和写入如何与 `overlay2` 配合使用 +### 读取文件 +考虑三种情况,其中容器打开文件以进行 overlay 读取访问。 +#### 文件在容器层中不存在 +如果容器打开一个文件进行读取访问,并且该文件在容器中尚不存在 (`upperdir`),则会从映像 (`lowerdir`) 中读取该文件。这会产生非常小的性能开销。 +#### 该文件仅存在于容器层中 +如果容器打开一个文件进行读取访问,并且该文件存在于容器 (`upperdir`) 中,而不是在映像 (`lowerdir`) 中,则直接从容器中读取该文件。 +#### 该文件同时存在于容器层和图像层中 +如果容器打开文件进行读取访问,并且该文件存在于映像层和容器层中,则会读取该文件在容器层中的版本。容器层 (`upperdir`) 中的文件会遮挡图像层 (`lowerdir`) 中具有相同名称的文件。 + +### 修改文件或目录 +请考虑修改容器中文件的一些情况。 +#### 首次写入文件 +容器第一次写入现有文件时,该文件在容器中不存在 (`upperdir`)。`overlay2` 驱动程序执行 `copy_up`将文件从镜像 (`lowerdir`) 复制到容器 (`upperdir`) 的操作。然后,容器将更改写入容器层中文件的新副本。 + +但是,OverlayFS 在文件级别而不是块级别工作。这意味着所有 OverlayFS `copy_up`操作都会复制整个文件,即使文件很大并且只修改了一小部分。这可能会对容器写入性能产生明显影响。但是,有两件事值得注意: + +- `copy_up` 操作仅在首次写入给定文件时发生。对同一文件的后续写入将针对已复制到容器的文件副本进行操作。 +- OverlayFS 适用于多个图层。这意味着在具有多个图层的图像中搜索文件时,性能可能会受到影响。 + +#### 删除文件和目录 +- 在容器中删除文件时,将在容器中创建一个 *whiteout* 文件 (`upperdir`)。图像层中的文件版本 (`lowerdir`) 不会被删除(因为 `lowerdir` 是只读的)。但是,whiteout 文件会阻止它对容器可用。 +- 在容器中删除*目录*时,将在容器内创建一个不透明目录 (`upperdir`)。这与 whiteout 文件的工作方式相同,可以有效地防止访问该目录,即使它仍然存在于映像中 (`lowerdir`)。 + +#### 重命名目录 +只有当源路径和目标路径都位于顶层时,才允许为目录调用 `rename(2)`。否则,它将返回 `EXDEV` 错误(“cross-device link not permitted”)。您的应用程序需要设计为处理 `EXDEV` 并回退到“复制和取消链接”策略。 + +## OverlayFS 和 Docker 性能 +`overlay2` 的性能可能比 `Btrfs` 好。但是,请注意以下详细信息: + +### 页面缓存 +OverlayFS 支持页面缓存共享。访问同一文件的多个容器共享该文件的单个页面缓存条目。这会使 `overlay2` 驱动程序对内存高效,是高密度用例的不错选择,例如 作为 PaaS。 +### 复制 +与其他写入时复制文件系统一样,每当容器首次写入文件时,OverlayFS 都会执行复制操作。这可能会增加写入操作的延迟,尤其是对于大型文件。但是,一旦文件被复制,对该文件的所有后续写入都将在上层进行,而无需进一步的复制操作。 +### 性能最佳实践 +以下通用性能最佳实践适用于 OverlayFS。 + +#### 使用快速存储 +固态驱动器 (SSD) 的读取和写入速度比旋转磁盘更快。 +#### 将卷用于写入密集型工作负载 +卷为写入密集型工作负载提供最佳且最可预测的性能。这是因为它们绕过了存储驱动程序,并且不会产生精简配置和写入时复制引入的任何潜在开销。卷还有其他好处,例如允许您在容器之间共享数据,以及即使没有正在运行的容器正在使用数据也可以保留数据。 + +## OverlayFS 兼容性限制 +总结 OverlayFS 与其他文件系统不兼容的方面: + +### [`open(2)`](https://linux.die.net/man/2/open) +OverlayFS 仅实现 POSIX 标准的子集。 这可能会导致某些 OverlayFS 操作违反 POSIX 标准。一 此类操作称为复制操作。假设您的应用程序调用 `fd1=open(“foo”, O_RDONLY)`,然后是 `fd2=open(“foo”, O_RDWR)`。在这种情况下,您的应用程序希望 `fd1` 和 `fd2` 引用同一个文件。但是,由于在第二次调用 `open(2)` 之后发生了复制操作,因此 Descriptors 引用不同的文件。`fd1` 继续引用映像中的文件 (`lowerdir`),而 fd2 引用容器中的文件 (`upperdir`)。解决方法是触摸文件,这会导致发生复制操作。所有后续的 `open(2)` 操作,无论只读还是读写访问模式,都会引用容器中的文件 (`upperdir`)。 + +除非安装了 `yum-plugin-ovl` 软件包,否则已知 `yum` 会受到影响。如果您的发行版(例如 6.8 或 7.2 之前的 RHEL/CentOS)中没有 `yum-plugin-ovl` 软件包,您可能需要执行 `touch /var/lib/rpm/*` 在运行 `yum install` 之前。此软件包实现了上面提到的 `yum` 的`touch`(触摸)解决方法。 + +### [`rename(2)`](https://linux.die.net/man/2/rename) +OverlayFS 不完全支持 `rename(2`) 系统调用。您的应用程序需要检测其故障并回退到“复制和取消链接”策略。 + + +[rootless-doc]:https://docs.docker.com/engine/security/rootless/ diff --git a/docs/storage/drivers/select-storage-driver.md b/docs/storage/drivers/select-storage-driver.md index 27edd45..dd49bf9 100644 --- a/docs/storage/drivers/select-storage-driver.md +++ b/docs/storage/drivers/select-storage-driver.md @@ -5,4 +5,114 @@ outline: [2, 5] # 选择存储驱动程序 理想情况下,写入容器的可写层的数据非常少,您可以使用 Docker 卷写入数据。但是,某些工作负载要求您能够写入容器的可写层。这就是存储驱动程序的用武之地。 -Docker 使用可插拔架构支持多个存储驱动程序。这 存储驱动程序控制映像和容器在 Docker 主机。阅读完 [Storage Driver Overview](https://docs.docker.com/engine/storage/drivers/),下一步是为您的工作负载选择最佳存储驱动程序。在最常见的场景中,使用整体性能和稳定性最佳的存储驱动程序。 \ No newline at end of file +Docker 使用可插拔架构支持多个存储驱动程序。这 存储驱动程序控制映像和容器在 Docker 主机。阅读完 [Storage Driver Overview](https://docs.docker.com/engine/storage/drivers/),下一步是为您的工作负载选择最佳存储驱动程序。在最常见的场景中,使用整体性能和稳定性最佳的存储驱动程序。 + +:::warning 注意 +本页讨论 Linux 上 Docker Engine 的存储驱动程序。如果你是 以 Windows 作为主机操作系统运行 Docker 守护程序,这是唯一支持的 存储驱动程序是 WindowsFilter。有关更多信息,请参阅 [windows过滤器](https://docs.docker.com/engine/storage/drivers/windowsfilter-driver/)。 +::: + +Docker Engine 在 Linux 上提供以下存储驱动程序: +Driver | 描述 +| - | - | +`overlay2` | `overlay2` 是当前支持的所有 Linux 发行版的首选存储驱动程序,不需要额外配置。 +`fuse-overlayfs` | `fuse-overlayfs` 仅用于在不支持无根 `overlay2` 的旧主机上运行无根 Docker。从 Linux 内核 5.11 开始,不需要使用 `fuse-overlayfs` 驱动程序,即使在无根模式下,`overlay2` 也可以工作。请参阅 [rootless 模式文档](https://docs.docker.com/engine/security/rootless/)。 +`btrfs` 和 `zfs` | `btrfs` 和 `zfs` 存储驱动程序允许使用高级选项,例如创建 “快照”,但需要更多的维护和设置。这些都依赖于正确配置的后备文件系统。 +`vfs` | `vfs` 存储驱动程序用于测试目的,以及不能使用写入时复制文件系统的情况。此存储驱动程序的性能很差,通常不建议用于生产用途。 + +如果没有,Docker 引擎有一个要使用的存储驱动程序的优先级列表 存储驱动程序,假设存储驱动程序满足 先决条件,并自动选择兼容的存储驱动程序。你 可以在 [Docker Engine 27.4.0 的源代码](https://github.com/moby/moby/blob/v27.4.0/daemon/graphdriver/driver_linux.go#L52-L53)。 + +某些存储驱动程序要求您对后备文件系统使用特定格式。 如果您有使用特定后备文件系统的外部要求,这可能会 限制您的选择。看 [支持的后备文件系统](https://docs.docker.com/engine/storage/drivers/select-storage-driver/#supported-backing-filesystems)。 + +缩小可以选择的存储驱动程序的范围后,您的选择 由工作负载的特征和稳定性级别决定 你需要。看 [有助于](https://docs.docker.com/engine/storage/drivers/select-storage-driver/#other-considerations)做出最终决定的其他注意事项。 + +## 每个 Linux 发行版支持的存储驱动程序 + +:::info 注意 +Docker Desktop 不支持通过编辑守护程序配置文件来修改存储驱动程序。只有默认的 overlay2 驱动程序或 [containerd 存储](https://docs.docker.com/desktop/features/containerd/)。这 下表也不适用于无根中的 Docker 引擎 模式。有关在 rootless 模式下可用的驱动程序,请参阅 [无根模式文档](https://docs.docker.com/engine/security/rootless/)。 +::: + +您的操作系统和内核可能不支持每个存储驱动程序。例如,仅当系统使用 `btrfs` 作为存储时,才支持 `btrfs`。通常,以下配置适用于最新版本的 Linux 发行版: + +Linux 发行版 | 推荐的存储驱动程序 | 其他驱动程序 +| - | - | - | +Ubuntu | `overlay2` | `zfs`, `vfs` +Debian | `overlay2` | `vfs` +CentOS | `overlay2` | `zfs`, `vfs` +Fedora | `overlay2` | `zfs`, `vfs` +SLES 15 | `overlay2` | `vfs` +RHEL | `overlay2` | `vfs` + +如有疑问,最好的全能配置是使用具有支持 `overlay2` 存储驱动程序的内核的现代 Linux 发行版,并将 Docker 卷用于写入密集型工作负载,而不是依赖将数据写入容器的可写层。 + +`vfs` 存储驱动程序通常不是最佳选择,主要用于在不支持其他存储驱动程序的情况下进行调试。在使用 `vfs` 存储驱动程序之前,请务必阅读 [其性能和存储特性和限制](https://docs.docker.com/engine/storage/drivers/vfs-driver/)。 + +众所周知,上表中的建议适用于大量用户。如果您使用推荐的配置并发现可重现的问题,则可能会很快得到修复。如果根据此表不推荐您要使用的驱动程序,您可以自行承担运行该驱动程序的风险。您可以而且仍然应该报告您遇到的任何问题。但是,此类问题的优先级低于使用推荐配置时遇到的问题。 + +根据您的 Linux 发行版,其他存储驱动程序(如 `btrfs`)可能可用。这些存储驱动程序对于特定用例可能具有优势,但可能需要额外的设置或维护,因此不建议将其用于常见场景。有关详细信息,请参阅这些存储驱动程序的文档。 + +## 支持的后备文件系统 +对于 Docker,后备文件系统是其中 `/var/lib/docker/` 的位置。某些存储驱动程序仅适用于特定的后备文件系统。 + +存储驱动程序 | 支持的后备文件系统 +| - | - | +`overlay2` | `xfs` with ftype=1, `ext4` +`fuse-overlayfs` | 任何文件系统 +`btrfs` | `btrfs` +`zfs` | `zfs` +`vfs` | 任何文件系统 + +## 其他注意事项 +### 适合您的工作负载 +此外,每个存储驱动程序都有自己的性能特征,使其或多或少适合不同的工作负载。考虑以下概括: +- `overlay2` 在文件级别而不是块级别运行。这样可以更有效地使用内存,但在写入密集型工作负载中,容器的可写层可能会变得相当大。 +- 块级存储驱动程序(如 `btrfs` 和 `zfs`)对于写入密集型工作负载(尽管不如 Docker 卷)性能更好。 +- `btrfs` 和 `zfs` 需要大量内存。 +- `zfs` 是 PaaS 等高密度工作负载的不错选择。 + +有关性能、适用性和最佳实践的更多信息,请参阅每个存储驱动程序的文档。 + +### 共享存储系统和存储驱动程序 +如果您使用 SAN、NAS、硬件 RAID 或其他共享存储系统,这些系统可能会提供高可用性、更高的性能、精简配置、重复数据删除和压缩。在许多情况下,Docker 可以在这些存储系统之上工作,但 Docker 并未与它们紧密集成。 + +每个 Docker 存储驱动程序都基于 Linux 文件系统或卷管理器。请务必遵循现有的最佳实践,在共享存储系统上运行存储驱动程序(文件系统或卷管理器)。例如,如果在共享存储系统上使用 ZFS 存储驱动程序,请确保遵循在该特定共享存储系统上运行 ZFS 文件系统的最佳实践。 + +### 稳定性 +对于一些用户来说,稳定性比性能更重要。尽管 Docker 认为此处提到的所有存储驱动程序都是稳定的,但有些驱动程序较新,仍在积极开发中。通常,`overlay2` 提供最高的稳定性。 + +### 使用您自己的工作负载进行测试 +您可以在不同的存储驱动程序上运行自己的工作负载时测试 Docker 的性能。确保使用等效的硬件和工作负载来匹配生产条件,以便您可以查看哪个存储驱动程序提供最佳的整体性能。 + +## 检查您当前的存储驱动程序 +每个存储驱动程序的详细文档详细介绍了使用给定存储驱动程序的所有设置步骤。 + +要查看 Docker 当前正在使用的存储驱动程序,请使用 `docker info` 并查找 `Storage Driver` 行: + +```bash +docker info + +Containers: 0 +Images: 0 +Storage Driver: overlay2 + Backing Filesystem: xfs +<...> +``` + +要更改存储驱动程序,请参阅新存储驱动程序的具体说明。某些驱动程序需要额外的配置,包括对 Docker 主机上的物理或逻辑磁盘的配置。 + +:::danger 重要 +更改存储驱动程序时,任何现有映像和容器都将变得不可访问。这是因为新的存储驱动程序无法使用它们的层。如果您还原更改,则可以再次访问旧映像和容器,但使用新驱动程序提取或创建的任何映像和容器都将无法访问。 +::: + +## 相关信息 +- [存储驱动程序][1] +- [`overlay2` 存储驱动程序][2] +- [`btrfs` 存储驱动程序][3] +- [`zfs` 存储驱动程序][4] +- [`WindowsFilter` 存储驱动程序][5] + +[1]:https://baidu.com +[2]:https://baidu.com +[3]:https://baidu.com +[4]:https://baidu.com +[5]:https://baidu.com +[6]:https://baidu.com \ No newline at end of file diff --git a/docs/storage/drivers/two_dm_container.webp b/docs/storage/drivers/two_dm_container.webp new file mode 100644 index 0000000..52b58f4 Binary files /dev/null and b/docs/storage/drivers/two_dm_container.webp differ