设备映射器存储驱动(已弃用)

已弃用

设备映射器驱动程序 已被弃用, 并在 Docker Engine v25.0 中移除。如果您正在使用设备映射器, 您必须在升级到 Docker Engine v25.0 之前迁移到受支持的存储驱动程序。请阅读 Docker 存储驱动程序 页面以了解受支持的存储驱动程序。

设备映射器(Device Mapper)是一个基于内核的框架,支撑着Linux上许多高级卷管理技术。Docker的devicemapper存储驱动程序利用该框架的瘦配置和快照功能进行镜像和容器管理。本文将设备映射器存储驱动程序称为devicemapper,而将内核框架称为设备映射器

对于支持的系统,devicemapper 支持包含在 Linux 内核中。然而,需要特定的配置才能与 Docker 一起使用。

devicemapper 驱动程序使用专用于 Docker 的块设备,并在块级别而不是文件级别操作。这些设备可以通过向 Docker 主机添加物理存储来扩展,并且它们的性能优于在操作系统(OS)级别使用文件系统。

先决条件

  • devicemapper 在运行于 CentOS、Fedora、SLES 15、Ubuntu、Debian 或 RHEL 上的 Docker Engine - Community 中受支持。
  • devicemapper 需要安装 lvm2device-mapper-persistent-data 包。
  • 更改存储驱动程序会使您已在本地系统上创建的任何容器无法访问。使用docker save保存容器,并将现有镜像推送到Docker Hub或私有仓库,这样您以后就不需要重新创建它们。

使用devicemapper存储驱动配置Docker

在遵循这些步骤之前,您必须首先满足所有的 先决条件

配置 loop-lvm 模式进行测试

此配置仅适用于测试。loop-lvm 模式使用了一种“回环”机制,允许从本地磁盘上的文件读取和写入,就像它们是实际的物理磁盘或块设备一样。 然而,回环机制的添加以及与操作系统文件系统层的交互意味着IO操作可能会很慢且资源密集。 使用回环设备还可能引入竞争条件。 然而,设置loop-lvm模式可以帮助在尝试启用direct-lvm模式所需的更复杂设置之前识别基本问题(例如缺少用户空间包、内核驱动程序等)。 因此,loop-lvm模式应仅用于在配置direct-lvm之前执行基本测试。

对于生产系统,请参阅 为生产环境配置直接LVM模式

  1. 停止Docker。

    $ sudo systemctl stop docker
    
  2. 编辑 /etc/docker/daemon.json。如果文件尚不存在,请创建它。假设文件为空,添加以下内容。

    {
      "storage-driver": "devicemapper"
    }

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

    如果daemon.json文件包含格式错误的JSON,Docker将无法启动。

  3. 启动 Docker。

    $ sudo systemctl start docker
    
  4. 验证守护进程是否正在使用devicemapper存储驱动。使用docker info命令并查找Storage Driver

    $ 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 fileMetadata loop file位于/var/lib/docker/devicemapper下的文件所指示。这些是回环挂载的稀疏文件。对于生产系统,请参阅配置生产环境的直接lvm模式

为生产配置直接LVM模式

使用devicemapper存储驱动的生产主机必须使用direct-lvm模式。此模式使用块设备创建精简池。这比使用回环设备更快,更高效地使用系统资源,并且块设备可以根据需要增长。然而,与loop-lvm模式相比,需要更多的设置。

在满足 先决条件后,按照以下步骤 配置 Docker 以在 direct-lvm 模式下使用 devicemapper 存储驱动。

警告

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

允许Docker配置直接LVM模式

Docker 可以为您管理块设备,简化 direct-lvm 模式的配置。这仅适用于全新的 Docker 设置。 您只能使用单个块设备。如果需要使用多个块设备,请改为手动配置 direct-lvm 模式。以下是可用的新配置选项:

OptionDescriptionRequired?DefaultExample
dm.directlvm_deviceThe path to the block device to configure for direct-lvm.Yesdm.directlvm_device="/dev/xvdf"
dm.thinp_percentThe percentage of space to use for storage from the passed in block device.No95dm.thinp_percent=95
dm.thinp_metapercentThe percentage of space to use for metadata storage from the passed-in block device.No1dm.thinp_metapercent=1
dm.thinp_autoextend_thresholdThe threshold for when lvm should automatically extend the thin pool as a percentage of the total storage space.No80dm.thinp_autoextend_threshold=80
dm.thinp_autoextend_percentThe percentage to increase the thin pool by when an autoextend is triggered.No20dm.thinp_autoextend_percent=20
dm.directlvm_device_forceWhether to format the block device even if a filesystem already exists on it. If set to false and a filesystem is present, an error is logged and the filesystem is left intact.Nofalsedm.directlvm_device_force=true

编辑daemon.json文件并设置适当的选项,然后重新启动Docker以使更改生效。以下daemon.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"
  ]
}

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

重启Docker以使更改生效。Docker会调用命令为您配置块设备。

警告

在Docker为您准备好块设备后更改这些值是不支持的,会导致错误。

你仍然需要 执行定期维护任务

手动配置直接LVM模式

以下过程创建一个配置为精简池的逻辑卷,用作存储池的后备。它假设您在/dev/xvdf有一个空闲的块设备,并且有足够的空闲空间来完成此任务。设备标识符和卷大小在您的环境中可能不同,您应该在整个过程中替换为您自己的值。该过程还假设Docker守护程序处于stopped状态。

  1. 确定您想要使用的块设备。该设备位于/dev/下(例如/dev/xvdf),并且需要有足够的空闲空间来存储该主机运行的镜像和容器层。固态硬盘是理想的选择。

  2. 停止Docker。

    $ sudo systemctl stop docker
    
  3. 安装以下包:

    • RHEL / CentOS: device-mapper-persistent-data, lvm2, 以及所有依赖项

    • Ubuntu / Debian / SLES 15: thin-provisioning-tools, lvm2, 以及所有依赖项

  4. 在第一步中的块设备上创建一个物理卷,使用pvcreate命令。将/dev/xvdf替换为你的设备名称。

    警告

    接下来的几个步骤是破坏性的,所以请确保你已经指定了正确的设备。

    $ sudo pvcreate /dev/xvdf
    
    Physical volume "/dev/xvdf" successfully created.
    
  5. 在同一设备上创建一个docker卷组,使用vgcreate命令。

    $ sudo vgcreate docker /dev/xvdf
    
    Volume group "docker" successfully created
    
  6. 使用lvcreate命令创建两个名为thinpoolthinpoolmeta的逻辑卷。最后一个参数指定了在空间不足时允许自动扩展数据或元数据的空闲空间量,作为临时的应急措施。这些是推荐的值。

    $ 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命令将卷转换为精简池和用于精简池元数据的存储位置。

    $ 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配置文件配置精简池的自动扩展。

    $ sudo vi /etc/lvm/profile/docker-thinpool.profile
    
  9. 指定thin_pool_autoextend_thresholdthin_pool_autoextend_percent的值。

    thin_pool_autoextend_threshold 是在 lvm 尝试自动扩展可用空间之前使用的空间百分比(100 = 禁用,不推荐)。

    thin_pool_autoextend_percent 是在自动扩展时添加到设备的空间量(0 = 禁用)。

    下面的示例在磁盘使用率达到80%时增加20%的容量。

    activation {
      thin_pool_autoextend_threshold=80
      thin_pool_autoextend_percent=20
    }

    保存文件。

  10. 应用LVM配置文件,使用lvchange命令。

    $ sudo lvchange --metadataprofile docker-thinpool docker/thinpool
    
    Logical volume docker/thinpool changed.
    
  11. 确保启用了逻辑卷的监控。

    $ 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,则需要显式启用监控。如果没有此步骤,无论应用的配置文件中有什么设置,逻辑卷的自动扩展都不会发生。

    $ sudo lvchange --monitor y docker/thinpool
    

    再次运行sudo lvs -o+seg_monitor命令,以确认监控功能已启用。Monitor列现在应该报告逻辑卷正在被monitored

  12. 如果您之前在此主机上运行过Docker,或者如果/var/lib/docker/存在,请将其移开,以便Docker可以使用新的LVM池来存储镜像和容器的内容。

    $ 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 存储驱动所需的选项。如果文件之前是空的,现在应该包含以下内容:

    {
        "storage-driver": "devicemapper",
        "storage-opts": [
        "dm.thinpooldev=/dev/mapper/docker-thinpool",
        "dm.use_deferred_removal=true",
        "dm.use_deferred_deletion=true"
        ]
    }
  14. 启动 Docker。

    systemd:

    $ sudo systemctl start docker
    

    服务:

    $ sudo service docker start
    
  15. 使用docker info验证Docker是否正在使用新配置。

    $ 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 fileMetadata file 是空白的,池名称为 docker-thinpool

  16. 在您确认配置正确后,您可以删除包含先前配置的/var/lib/docker.bk目录。

    $ sudo rm -rf /var/lib/docker.bk
    

管理 devicemapper

监控瘦池

不要仅仅依赖LVM的自动扩展。卷组会自动扩展,但卷仍然可能被填满。你可以使用lvslvs -a来监控卷上的可用空间。考虑在操作系统级别使用监控工具,例如Nagios。

要查看LVM日志,您可以使用journalctl

$ sudo journalctl -fu dm-event.service

如果您在thin pool上遇到重复的问题,您可以在/etc/docker/daemon.json中设置存储选项dm.min_free_space为一个值(代表百分比)。例如,将其设置为10可以确保当可用空间达到或接近10%时,操作会失败并发出警告。请参阅引擎守护程序参考中的存储驱动选项

在运行的设备上增加容量

您可以在运行的thin-pool设备上增加池的容量。这在数据的逻辑卷已满且卷组已达到最大容量时非常有用。具体步骤取决于您使用的是loop-lvm thin pool还是direct-lvm thin pool

调整loop-lvm精简池的大小

调整loop-lvm精简池大小的最简单方法是 使用device_tool工具, 但你也可以 使用操作系统工具 来代替。

使用 device_tool 工具

一个社区贡献的脚本名为device_tool.go可在 moby/moby Github 仓库中找到。你可以使用这个工具来调整loop-lvm瘦池的大小, 避免上述的冗长过程。这个工具不能保证一定有效,但你 应该只在非生产系统上使用loop-lvm

如果您不想使用device_tool,您可以 手动调整精简池的大小

  1. 要使用该工具,请克隆Github仓库,切换到contrib/docker-device-tool目录,并按照README.md中的说明编译该工具。

  2. 使用该工具。以下示例将精简池的大小调整为200GB。

    $ ./device_tool resize 200GB
    
使用操作系统工具

如果您不想 使用device-tool工具, 您可以按照以下步骤手动调整loop-lvm精简池的大小。

loop-lvm模式下,使用一个回环设备来存储数据,另一个来存储元数据。loop-lvm模式仅支持测试,因为它存在显著的性能和稳定性缺陷。

如果您正在使用loop-lvm模式,docker info的输出将显示Data loop fileMetadata loop file的文件路径:

$ 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. 列出设备的大小。

    $ 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,该命令用于增加减少文件的大小。请注意,减少大小是一个破坏性操作。

    $ sudo truncate -s 200G /var/lib/docker/devicemapper/data
    
  3. 验证文件大小是否已更改。

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

    $ 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. 首先获取池名称。池名称是第一个字段,由:分隔。此命令提取它。

    $ sudo dmsetup status | grep ' thin-pool ' | awk -F ': ' {'print $1'}
    docker-8:1-123141-pool
    

    b. 转储设备映射器的精简池表。

    $ 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命令重新加载带有新扇区号的精简池。

    $ 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
    

调整直接LVM精简池的大小

要扩展direct-lvm精简池,首先需要将一个新的块设备附加到Docker主机,并记下内核分配给它的名称。在这个例子中,新的块设备是/dev/xvdg

按照此过程扩展direct-lvm精简池,替换您的块设备和其他参数以适应您的情况。

  1. 收集有关您的卷组的信息。

    使用pvdisplay命令查找当前由您的精简池使用的物理块设备,以及卷组的名称。

    $ sudo pvdisplay |grep 'VG Name'
    
    PV Name               /dev/xvdf
    VG Name               docker
    

    在以下步骤中,请根据实际情况替换您的块设备或卷组名称。

  2. 使用vgextend命令扩展卷组,使用上一步中的VG Name和你的块设备名称。

    $ sudo vgextend docker /dev/xvdg
    
    Physical volume "/dev/xvdg" successfully created.
    Volume group "docker" successfully extended
    
  3. 扩展docker/thinpool逻辑卷。此命令立即使用100%的卷,而不进行自动扩展。要扩展元数据薄池,请使用docker/thinpool_tmeta

    $ 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

    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”。您需要使用以下命令重新激活逻辑卷:

$ sudo lvchange -ay docker/thinpool

devicemapper 存储驱动的工作原理

警告

不要直接操作/var/lib/docker/中的任何文件或目录。这些文件和目录由Docker管理。

使用 lsblk 命令从操作系统的角度查看设备及其池:

$ 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 使用的挂载点:

$ 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 的另一个特性是它使用快照(有时也称为瘦设备虚拟设备),这些快照将每一层中引入的差异存储为非常小且轻量级的瘦池。快照提供了许多好处:

  • 容器之间共享的层仅在磁盘上存储一次,除非它们是可写的。例如,如果您有10个不同的镜像,它们都基于alpine,那么alpine镜像及其所有父镜像在磁盘上仅存储一次。

  • 快照是写时复制(CoW)策略的一种实现。这意味着只有当容器修改或删除某个文件或目录时,该文件或目录才会被复制到容器的可写层。

  • 因为 devicemapper 在块级别操作,所以可写层中的多个块可以同时被修改。

  • 可以使用标准的操作系统级备份工具来备份快照。只需复制/var/lib/docker/devicemapper/

Devicemapper 工作流程

当你使用devicemapper存储驱动启动Docker时,所有与镜像和容器层相关的对象都存储在/var/lib/docker/devicemapper/中,该目录由一个或多个块级设备支持,这些设备可以是回环设备(仅用于测试)或物理磁盘。

  • 基础设备是最低层次的对象。这是精简池本身。 你可以使用docker info来检查它。它包含一个文件系统。这个基础 设备是每个镜像和容器层的起点。基础 设备是设备映射器的一个实现细节,而不是Docker层。

  • 关于基础设备和每个镜像或容器层的元数据以JSON格式存储在/var/lib/docker/devicemapper/metadata/中。这些层是写时复制快照,这意味着它们在从父层分离之前是空的。

  • 每个容器的可写层都挂载在/var/lib/docker/devicemapper/mnt/中的一个挂载点上。每个只读镜像层和每个已停止的容器都有一个空目录存在。

每个镜像层都是其下面层的快照。每个镜像的最底层是池中存在的基础设备的快照。当你运行一个容器时,它是基于该容器的镜像的快照。以下示例显示了一个运行两个容器的Docker主机。第一个是ubuntu容器,第二个是busybox容器。

Ubuntu and busybox image layers

容器读写如何与devicemapper一起工作

读取文件

使用devicemapper时,读取操作发生在块级别。下图展示了在一个示例容器中读取单个块(0x44f)的高级过程。

Reading a block with devicemapper

应用程序对容器中的块0x44f发出读取请求。因为容器是镜像的薄快照,它没有这个块,但它有一个指向最近父镜像中存在该块的指针,并从那里读取该块。现在该块存在于容器的内存中。

写入文件

写入新文件:使用devicemapper驱动程序时,将新数据写入容器是通过按需分配操作完成的。新文件的每个块都在容器的可写层中分配,并且块被写入那里。

更新现有文件:从存在该文件的最近层读取相关块。当容器写入文件时,只有修改过的块会被写入容器的可写层。

删除文件或目录:当你在容器的可写层中删除一个文件或目录,或者当镜像层删除其父层中存在的文件时,devicemapper存储驱动程序会拦截对该文件或目录的进一步读取尝试,并响应文件或目录不存在。

写入然后删除文件:如果容器写入文件然后删除文件,所有这些操作都发生在容器的可写层中。在这种情况下,如果您使用direct-lvm,块将被释放。如果您使用loop-lvm,块可能不会被释放。这是不在生产中使用loop-lvm的另一个原因。

设备映射器与Docker性能

  • allocate-on demand 性能影响:

    devicemapper 存储驱动程序使用 allocate-on-demand 操作从精简池中分配新块到容器的可写层。每个块大小为64KB,因此这是用于写入的最小空间量。

  • 写时复制的性能影响:容器第一次修改特定块时,该块会被写入容器的可写层。由于这些写入发生在块级别而不是文件级别,因此性能影响被最小化。然而,写入大量块仍然可能对性能产生负面影响,在这种情况下,devicemapper存储驱动程序的性能可能实际上比其他存储驱动程序更差。对于写密集型工作负载,您应该使用数据卷,这样可以完全绕过存储驱动程序。

性能最佳实践

使用devicemapper存储驱动时,请记住以下几点以最大化性能。

  • 使用 direct-lvmloop-lvm 模式性能不佳,绝不应在生产环境中使用。

  • 使用快速存储: 固态硬盘(SSDs)比旋转磁盘提供更快的读取和写入速度。

  • 内存使用devicemapper 比其他一些存储驱动程序使用更多的内存。每个启动的容器都会将其文件的一个或多个副本加载到内存中,具体取决于同时修改同一文件的块数。由于内存压力,devicemapper 存储驱动程序可能不适合高密度使用场景中的某些工作负载。

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

    注意

    当使用devicemapperjson-file日志驱动时,容器生成的日志文件仍然存储在Docker的数据根目录中,默认为/var/lib/docker。如果您的容器生成大量日志消息,这可能会导致磁盘使用量增加或由于磁盘满而无法管理系统。您可以配置一个 日志驱动来将容器日志存储在外部。