使用DeviceMapper存储驱动
Device Mapper是一个基于内核的框架,支持Linux上的许多高级卷管理技术。Docker的 devicemapper 存储驱动利用此框架的精简配置和快照功能进行及你想和容器的管理。本文将Device Mapper存储驱动称为 devicemapper, 并将内核框架称为 Device Mapper.
对于支持它的系统,devicemapper已经被包含在Linux内核中。但是,还需要一些特殊配置才能用于Docker。比如,在RHEL或者CentOS的常规安装中,docker默认设置为overlay,而且不是一个被支持的配置。
devicemapper驱动使用专用于Docker的块设备,并在块级别而不是文件级别运行。这些设备可以通过在你的Docker宿主机添加屋里存储设备来扩展,而且在操作系统级别比使用文件系统表现更好。
一、前言
- devicemapper 存储驱动是Docker EE以及RHEL、CentOS和Oracle Linux支持的商业版Docker引擎(CS-Engine))唯一支持的存储驱动。参考Product compatibility matrix。
- devicemapper 还支持CentOs、Fedora、Ubuntu和Debian上跑的Docker CE。
- 在你本地系统上改变存储驱动,将导致你已经创建的容器无法访问。使用docker save来保存容器,并将你的镜像推到Docker Hub或者私有仓库,不然就要重新制做这些容器和镜像了。
二、为Docker配置 devicemapper存储驱动
在下面步骤之前,一定要先阅读前言
2.1 测试环境下配置loop-lvm
这种配置只能用于线下测试环境,回环设备效率低下并且更耗费资源,并且要求你在磁盘创建合适大小的文件。他们还能引入竞争条件。因设置简单,经常用于测试环境。生产环境的配置参考下节dirct-lvm
- stop Docker
$ sudo systemctl stop docker
- 编辑/etc/docker/daemon.json 。确保文件为空,并添加下面内容:
{
"storage-driver": "devicemapper"
}
- start docker
$ sudo systemctl start docker
- 核查docker daemon使用了devicemapper存储驱动。使用docker info命令并查看Storage Driver。
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 17.03.2-ce
Storage Driver: devicemapper
Pool Name: docker-253:1-264951-pool
Pool Blocksize: 65.54 kB
Base Device Size: 21.47 GB
Backing Filesystem: xfs
Data file: /dev/loop0
Metadata file: /dev/loop1
Data Space Used: 22.53 GB
Data Space Total: 107.4 GB
Data Space Available: 8.399 GB
Metadata Space Used: 37.46 MB
Metadata Space Total: 2.147 GB
Metadata Space Available: 2.11 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/devicemapper/data
Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata
Library Version: 1.02.135-RHEL7 (2016-11-16)
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 4ab9917febca54791c5f071a9d1f404867857fcc
runc version: 54296cf40ad8143b62dbcaa1d90e520a2136ddfe
init version: 949e6fa
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-514.26.2.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 31.26 GiB
Name: inf-wpc03.iwm.name
ID: F67X:HSDI:FN2N:M3LM:TQYF:BRCQ:UQRT:RM2M:7AS6:Q4ZY:A4EP:TV47
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://2q6zc99h.mirror.aliyuncs.com
Live Restore Enabled: false
WARNING: devicemapper: usage of loopback devices is strongly discouraged for production use.
Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.
宿主机使用loop-lvm模式,并不能用于生产环境的系统中。事实上Data loop file和一个Metadata loop file都在 /var/lib/docker/devicemapper文件夹下。他们是回环安装的稀疏文件。生产环境中还是要使用下节中的dirct-lvm。
2.2 在生产环境配置dirct-lvm
生产环境的主机使用devicemapper存储驱动时,必须采用dirct-lvm模式。这种模式使用块设备创建精简池。它比回环设备更快,更高效的使用系统资源,而且块设备还可按需增长。但是配置比loop-lvm复杂许多。
如果你对前言中的条件没有意见,按照下面步骤配置即可在dirct-lvm模式下使用devicemapper。
⚠️警告:更改存储驱动将使你在本地的容器破坏掉。使用docker save来保存容器,并把镜像推到Docker Hub或者你的私有仓库,以便恢复。
2.2.1 允许Docker配置dirct-lvm模式
在Docker 17.06或更高版本中,Docker能为你管理块设备,简化direct-lvm模式的配置。这仅适用于新版Docker配置中。你只能使用一个块设备,如果想使用多个,可以按照2.2.2节的步骤配置。已经增加了下面的新配置项:
选项 | 描述 | 必选? | 默认值 | 举例 |
---|---|---|---|---|
dm.directlvm_device | 为direct-lvm配置的块设备路径 | Yes | dm.directlvm_device="/dev/xvdf" | |
dm.thinp_percent | The percentage of space to use for storage from the passed in block device. | No | 95 | dm.thinp_percent=95 |
dm.thinp_metapercent | The percentage of space to for metadata storage from the passed-in block device. | No | 1 | dm.thinp_metapercent=1 |
dm.thinp_autoextend_threshold | The threshold for when lvm should automatically extend the thin pool as a percentage of the total storage space. | No | 80 | dm.thinp_autoextend_threshold=80 |
dm.thinp_autoextend_percent | The percentage to increase the thin pool by when an autoextend is triggered. | No | 20 | dm.thinp_autoextend_percent=20 |
dm.directlvm_device_force | Whether 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. | No | false | dm.directlvm_device_force=true |
编辑daemon.json 文件,设置合适的配置项,重启Docker才能生效。下面是使用了全部配置项的例子:
{
"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为你准备好块设备之后改变这些值是不被支持的,并且会导致一些错误。
你仍然需要执行定期维护任务(3.1节)。
2.2.2 手动配置dirct-lvm模式
以下过程将创建配置为精简池的逻辑卷,以用作存储池的备份。它假定您有一个备用块设备/dev/xvdf,并且有足够的空间来完成任务。你环境的设备标识符和卷大小可能不同,在下面步骤中需要你需要替换成你自己的变量。下面步骤需要确保docker已经停止了。
- 确定要使用的块设备。该设备将位于/dev/(如/dev/xvdf)下,并且需要足够的可用空间来存储主机将运行的工作负载的映像和容器层。固态硬盘是最理想的选择。
- stop docker
$ sudo systemctl stop docker
- 安装下面套装
- RHEL / CentOS: device-mapper-persistent-data, lvm2, and all dependencies
- Ubuntu / Debian: thin-provisioning-tools, lvm2, and all dependencies
- 根据第一步在你的块设备上创建物理卷。使用pvcreate命令
⚠️ 警告:这一步的操作是毁灭性的,请百分之百确保你选的是正确的设备。
$ sudo pvcreate /dev/xvdf
Physical volume "/dev/xvdf" successfully created.
- 在上面设备创建 docker 卷组。
$ sudo vgcreate docker /dev/xvdf
Volume group "docker" successfully created
- 使用lvcreate命令创建两个名为thinpool和thinpoolmeta的逻辑卷。最后一个参数指定可用空间的大小,以便在空间不足时自动扩展数据或元数据,作为临时性措施。下面是推荐值:
$ 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 =disabled,不推荐)
- thin_pool_autoextend_percent 是自动扩展时添加到设备的空间总量(0=disabled)。当磁盘使用率达到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
- 编辑/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"
]
}
- start docker
#systemd:
$ sudo systemctl start docker
#service:
$ sudo service docker start
- 使用docker info 确认新的配置
$ docker info
Containers: 53
Running: 50
Paused: 0
Stopped: 3
Images: 206
Server Version: 17.03.2-ce
Storage Driver: devicemapper
Pool Name: docker-thinpool
Pool Blocksize: 524.3 kB
Base Device Size: 21.47 GB
Backing Filesystem: xfs
Data file:
Metadata file:
Data Space Used: 38.18 GB
Data Space Total: 247 GB
Data Space Available: 208.8 GB
Metadata Space Used: 18.11 MB
Metadata Space Total: 5.365 GB
Metadata Space Available: 5.346 GB
Thin Pool Minimum Free Space: 24.7 GB
Udev Sync Supported: true
Deferred Removal Enabled: true
Deferred Deletion Enabled: true
Deferred Deleted Device Count: 0
Library Version: 1.02.146-RHEL7 (2018-01-22)
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 4ab9917febca54791c5f071a9d1f404867857fcc
runc version: 54296cf40ad8143b62dbcaa1d90e520a2136ddfe
init version: 949e6fa
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-514.26.2.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 31.26 GiB
Name: inf-wpc05.iwm.name
ID: 5QUS:EUJY:URZR:ZUYB:K2Q2:DYBA:BDKK:NDN7:W2K5:LLNS:XIUI:VZJW
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://2q6zc99h.mirror.aliyuncs.com
Live Restore Enabled: false
如果你的docker配置正确,那么Data file和Metadata file是空的,而且pool ame是 docker-thinpool
- 确认完配置正确之后,你可以移除掉/var/lib/backer.bk
$ rm -rf /var/lib/docker.bk
三、管理devicemapper
3.1 管理精简池
不要仅仅依赖于LVM的自动扩展。卷组可以自动扩展,但是卷仍能写满。你可以使用lvs 或者 lvs -a来管理卷的空余空间。注意使用OS级别的监控工具,比如Nagios。
你可以使用journalctl 来查看LVM的日志。
$ journalctl -fu dm-event.service
如果你在精简池中再三遇到错误,可以在/etc/docker/daemon.json中 dm.min_free_space 设置一个值(一个百分比)。实例中,将它设置为 10 确保空余空间接近10%时,操作错误会发出告警。参考 storage driver options in the Engine daemon reference。
3.2 为running状态的设备扩容
你可以为running状态的精简池设备扩容,这对于数据逻辑卷或者卷组满了非常有用。但是操作方法取决于你用了 loop-lvm 还是 direct-lvm 精简池。
3.2.1 更改一个loop-lvm精简池容量
这个是测试环境下的应用,略过。 点击查看原文。
3.2.2 更改一个dirct-lvm精简池容量
为了扩展一个dirct-lvm精简池,首先需要将一个新的块设备添加到Docker宿主机,并记下内核给它分的名字。这个例子中新块设备是 /dev/xvdg。
- 收集卷组信息
使用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%的卷空间,并不自动扩展。使用 docker/thinpool_tmeta 来扩展元数据精简池(metadata thinpool)。
$ 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.
- 使用 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
<output truncated>
3.3 重启后激活devicemapper
如果你重启了主机,发现 docker 没启动,查看错误发现"Non existing device" 。你需要使用下面命令重新激活逻辑卷。
sudo lvchange -ay docker/thinpool
四、devicemapper存储驱动是怎么工作的
⚠️警告:不要直接操作/var/lib/docker/的目录和文件。这些文件和目录是被Docker控制的。
在操作系统视角,使用 lsblk 命令来查看设备和其他pools:
$ 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)存储镜像和镜像层(layer)内容,并通过将他们挂在到 /var/lib/docker/devicemapper/ 的子目录来对容器开放。