docs.dockoro.cn/docs/storage/drivers/device-mapper-driver.md
2024-12-26 19:37:19 +08:00

528 lines
27 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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