Docker 使用Device Mapper存储驱动程序

Device Mapper是一个基于内核的框架,它支持Linux上的许多高级卷管理技术。Docker的devicemapper存储驱动程序利用此框架的精简配置和快照功能进行映像和容器管理。本文将Device Mapper存储驱动程序称为Device Mapper devicemapper,将内核框架称为Device Mapper。

对于支持它的系统,devicemapperLinux内核中包含支持。但是,需要特定配置才能将其与Docker一起使用。

该devicemapper驱动程序使用专用于多克尔块设备和在块级,而不是文件级别运行。可以通过向Docker主机添加物理存储来扩展这些设备,并且它们比在操作系统(OS)级别使用文件系统更好。

先决条件
devicemapper存储驱动程序是许多OS分发版上Docker EE支持的存储驱动程序。有关详细信息,请参阅 产品兼容性列

devicemapper 在CentOS,Fedora,Ubuntu或Debian上运行的Docker CE上也支持。

更改存储驱动程序会使您已创建的任何容器在本地系统上无法访问。使用docker save保存的容器,并推动现有图像多克尔集线器或私人仓库,这样你就不会需要稍后重新创建。

使用devicemapper存储驱动程序配置Docker
在执行这些过程之前,必须首先满足所有 先决条件。

配置loop-lvm测试模式
此配置仅适用于测试。环回设备速度慢且占用大量资源,它们要求您以特定大小在磁盘上创建文件。他们还可以引入竞争条件。它们可用于测试,因为设置更容易。

对于生产系统,请参阅 配置direct-lvm模式以进行生产。

停止Docker。

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

{
  "storage-driver": "devicemapper"
}

查看每个存储驱动程序的所有存储选项:

稳定
边缘
如果daemon.json文件包含格式错误的JSON,则Docker无法启动。

启动Docker。

$ sudo systemctl start docker
验证守护程序是否正在使用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)
<output truncated>

此主机以loop-lvm模式运行,生产系统不支持此模式。这表示Data loop file a和a Metadata loop file位于文件下 /var/lib/docker/devicemapper。这些是环回安装的稀疏文件。对于生产系统,请参阅 配置direct-lvm模式以进行生产。

为生产配置direct-lvm模式
使用devicemapper存储驱动程序的生产主机必须使用direct-lvm 模式。此模式使用块设备创建精简池。这比使用环回设备更快,更有效地使用系统资源,并且阻止设备可以根据需要增长。但是,需要比loop-lvm 模式更多的设置。

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

警告:更改存储驱动程序会使您已创建的任何容器在本地系统上无法访问。使用docker save保存的容器,并推动现有图像多克尔集线器或私人仓库,这样你就不会需要稍后重新创建。

允许DOCKER配置DIRECT-LVM模式
使用Docker 17.06和更高版本,Docker可以为您管理块设备,简化direct-lvm模式配置。这仅适用于新鲜的Docker设置。您只能使用单个块设备。如果需要使用多个块设备,请手动配置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并且存在文件系统,则会记录错误并保持文件系统不变。 没有 dm.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为您准备块设备后更改这些值并导致错误。

您仍需要执行定期维护任务。

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

标识要使用的块设备。设备位于/dev/(例如/dev/xvdf)下方 ,需要足够的可用空间来存储主机运行的工作负载的映像和容器层。固态硬盘非常理想。

停止Docker。

$ sudo systemctl stop docker
安装以下包:

RHEL / CentOS的:device-mapper-persistent-data,lvm2,和所有的依赖

Ubuntu的/ Debian的:thin-provisioning-tools,lvm2,和所有的依赖

使用该pvcreate命令从步骤1在块设备上创建物理卷 。替换您的设备名称/dev/xvdf。

警告:接下来的几个步骤是破坏性的,所以请确保您指定了正确的设备!

$ sudo pvcreate /dev/xvdf

Physical volume "/dev/xvdf" successfully created.
docker使用该vgcreate 命令在同一设备上创建卷组。

$ sudo vgcreate docker /dev/xvdf

Volume group "docker" successfully created
创建两个命名thinpool并thinpoolmeta使用该 lvcreate命令的逻辑卷。最后一个参数指定允许在空间不足时自动扩展数据或元数据的可用空间量,作为临时间隙。这些是推荐值。

$ 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.
使用该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.

通过lvm配置文件配置精简池的自动扩展。

$ sudo vi /etc/lvm/profile/docker-thinpool.profile
指定thin_pool_autoextend_threshold和thin_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
}

保存文件。

使用该lvchange命令应用LVM配置文件。

$ sudo lvchange --metadataprofile docker-thinpool docker/thinpool

Logical volume docker/thinpool changed.
启用对主机上逻辑卷的监视。如果没有此步骤,即使存在LVM配置文件,也不会发生自动扩展。

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

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

$ mkdir /var/lib/docker.bk
$ mv /var/lib/docker/* /var/lib/docker.bk

如果以下任何步骤失败并且您需要还原,则可以删除 /var/lib/docker并替换它/var/lib/docker.bk。

编辑/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"
    ]
}

启动Docker。

systemd:

$ sudo systemctl start docker
服务:

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

$ 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)
<output truncated>

如果正确配置了Docker Data file,Metadata file则为空,并且池名称为docker-thinpool。

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

$ rm -rf /var/lib/docker.bk
管理devicemapper
监视精简池
不要单独依赖LVM自动扩展。卷组自动扩展,但卷仍然可以填满。您可以使用lvs或监视卷上的可用空间lvs -a。考虑在操作系统级别使用监控工具,例如Nagios。

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

$ journalctl -fu dm-event.service
如果您遇到精简池的重复问题,可以将存储选项 dm.min_free_space设置为值(表示百分比) /etc/docker.daemon.json。例如,将其设置为10确保当可用空间处于或接近10%时操作失败并显示警告。请参阅Engine守护程序参考中的 存储驱动程序选项。

增加正在运行的设备的容量
您可以在正在运行的精简池设备上增加池的容量。如果数据的逻辑卷已满并且卷组处于满容量状态,则此选项非常有用。具体过程取决于您使用的是 loop-lvm精简池还是 直接lvm​​精简池。

调整LOOP-LVM精简池的大小
调整loop-lvm精简池大小的最简单方法是 使用device_tool实用程序,但您可以使用操作系统实用程序 。

使用device_tool实用程序
moby / moby Github存储库中device_tool.go提供了 一个社区提供的脚本。您可以使用此工具调整精简池的大小,避免上面的漫长过程。此工具不保证可以正常工作,但您应该只在非生产系统上使用。loop-lvmloop-lvm

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

要使用该工具,请克隆Github存储库,更改为 contrib/docker-device-tool,并按照README.md 编译工具中的说明进行操作。

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

$ ./device_tool resize 200GB
使用操作系统实用程序
如果您不想使用设备工具实用程序,则可以loop-lvm使用以下过程手动调整精简池的大小。

在loop-lvm模式中,回送设备用于存储数据,而另一个用于存储元数据。loop-lvm模式仅支持测试,因为它具有显着的性能和稳定性缺点。

如果您正在使用loop-lvm模式,则docker info显示文件路径的输出Data loop file和Metadata 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。

列出设备的大小。

$ 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

data使用truncate命令将文件大小增加到200 G,该命令用于增大或减小文件大小。请注意,减小尺寸是一种破坏性操作。

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

$ 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

环回文件在磁盘上已更改,但在内存中未更改。列出内存中环回设备的大小,以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
重新加载devicemapper精简池。

一个。首先获取池名称。池名称是第一个字段,由`:`分隔。该命令将其解压缩。

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

    docker-8:1-123141-pool
湾 转储精简池的设备映射表。

    $ 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精简池,替换块设备和其他参数以适合您的情况。

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

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

$ sudo pvdisplay |grep 'VG Name'

PV Name               /dev/xvdf
VG Name               docker

在以下步骤中,根据需要替换块设备或卷组名称。

使用 上一步中的vgextend命令VG Name以及新块设备的名称扩展卷组。

$ sudo vgextend docker /dev/xvdg

Physical volume "/dev/xvdg" successfully created.
Volume group "docker" successfully extended

扩展docker/thinpool逻辑卷。此命令立即使用100%的音量,无需自动扩展。要改为扩展元数据thinpool,请使用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.

使用Data Space Available输出中的字段验证新的精简池大小docker info。如果您扩展了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
<output truncated>

devicemapper重启后激活
如果重新启动主机并发现docker服务无法启动,请查找错误“非现有设备”。您需要使用以下命令重新激活逻辑卷:

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/devicemapper/mnt/目录包含存在的每个图像和容器层的安装点。图像层安装点为空,但容器的安装点显示容器的文件系统,因为它显示在容器内。

图像分层和共享
该devicemapper存储驱动程序使用专用的块设备,而不是格式化的文件系统,并在写入时复制(全体)操作上以获得最大性能的块级的文件进行操作。

快照
另一个特性devicemapper是使用快照(有时也称为 精简设备或虚拟设备),它将每个层中引入的差异存储为非常小的轻量级精简池。快照提供了许多好处:

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

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

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

可以使用标准操作系统级备份实用程序备份快照。只需复制一份/var/lib/docker/devicemapper/。

DEVICEMAPPER工作流程
使用devicemapper存储驱动程序启动Docker时,将存储与映像和容器层相关的所有对象,这些对象 /var/lib/docker/devicemapper/由一个或多个块级设备(环回设备(仅测试)或物理磁盘)支持。

所述基部设备是最低级的对象。这是精简池本身。你可以用它来检查它docker info。它包含一个文件系统。此基本设备是每个图像和容器层的起点。基本设备是Device Mapper实现细节,而不是Docker层。

有关基本设备和每个图像或容器层的元数据/var/lib/docker/devicemapper/metadata/以JSON格式存储 。这些图层是写时复制快照,这意味着它们是空的,直到它们与父图层分离。

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

每个图像层都是其下方图层的快照。每个映像的最低层是池中存在的基本设备的快照。运行容器时,它是容器所基于的映像的快照。以下示例显示了具有两个正在运行的容器的Docker主机。第一个是ubuntu 容器,第二个是busybox容器。

ubuntu和busybox图像层

容器读写如何工作 devicemapper

读文件

随着devicemapper,读取发生在块级别。下图显示了0x44f在示例容器中读取单个块()的高级过程。

使用devicemapper读取块

应用程序0x44f在容器中对块进行读取请求。因为容器是图像的精简快照,所以它没有块,但它有一个指向最近的父图像上块的指针,它存在,并从那里读取块。该块现在存在于容器的内存中。

写文件

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

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

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

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

Device Mapper和Docker性能

  • allocate-on demand绩效影响

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

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

性能最佳实践

在使用devicemapper 存储驱动程序时,请记住这些以最大限度地提高性能。

  • 使用direct-lvm:该loop-lvm模式不具备性能,不应在生产中使用。

  • 使用快速存储:固态驱动器(SSD)提供比旋转磁盘更快的读取和写入。

  • 内存使用情况devicemapper使用的内存比其他一些存储驱动程序多。每个已启动的容器将其文件的一个或多个副本加载到内存中,具体取决于同时修改同一文件的块数。由于内存压力,devicemapper存储驱动程序可能不是高密度用例中某些工作负载的正确选择。

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

猜你喜欢

转载自blog.csdn.net/Richardlygo/article/details/82812591
今日推荐