Device Mapper是一个基于kernel的框架,它增强了很多Linux上的高级卷管理技术。Docker的devicemapper驱动在镜像和容器管理上,利用了该框架的超配和快照功能。为了区别,本文使用Device Mapper指驱动中的框架,而devicemapper指Docker的存储驱动。
  注意:商业支持的Docker Engine(CS-Engine)建议在RHEL和CentOS上使用devicemapper存储驱动。

AUFS之外的另一种选择

  Docker最初运行在Ubuntu和Devian上,并且使用AUFS作为存储后端。当Docker变得流行后,很多想使用它的公司正在使用RHEL。不幸的是,因为Linux主线kernel并不包含AUFS,所以RHEL并没有支持AUFS。
  为了改变这种情况,Red Hat开发者研究将AUFS包含进kernel主线。最后,他们认为开发一种新的存储后端是更好的主意。此外,他们打算使用已经存在的Device Mapper技术作为新存储后端的基础。
  Red Hat与Docker公司合作贡献这个新驱动。因为这次合作,Docker Engine被重新设计为存储驱动插件化。因此devicemapper成为Docker支持的第二个存储驱动。
  Device Mapper在2.6.9之后就被何如Linux kernel主线,也是RHEL家族发布包的核心部分。这意味着devicemapper存储驱动基于稳定的代码,有着大量的工作产品和极强的社区支持。

镜像分层和共享

  devicemapper驱动把每个镜像和容器都存储在它自己的虚拟设备中,这些设备是超配的copy-on-write快照设备。Device Mapper技术工作在块级别而不是文件级别,也就是说devicemapper存储驱动的超配和copy-on-write操作直接操作块,而不是整个文件。
  注意:快照也是使用的thin设备或者虚拟设备。
  使用devicemapper时,Docker如下创建镜像:
    devicemapper存储驱动创建一个thin池。
    这个池是在块设备或者loop mounted sparse file上创建的。
    然后创建一个基础设备。
    该基础设备是一个带文件系统的thin设备。可以通过docker info命令中的Backing filesystem值,来查看后端使用的是哪种文件系统。
    每个新的镜像(和镜像层)都是该基础设备的快照。
    这些都是超配的copy-on-write快照。也就是说它们初始化的时候是空的,只有在有数据写向它们时,才会从池中消耗空间。
  使用devicemapper,容器层是基于镜像的快照。和镜像一样,容器快照也是超配的copy-on-write快照。容器快照保存了容器的所有更新,当向容器写数据时,devicemapper按需从池中分配空间给容器层。
  下图展示了一个thin池、基础设备和两个镜像。
  
  如果你仔细观察图片,你会发现每个镜像层都是它下层的快照,镜像的最底层是池中基础设备的快照。这个基础设备是Device Mapper产生的,并不是一个Docker镜像层。
  而容器又是镜像的一个快照,下图展示了两个容器在整个存储驱动的层次。
  

devicemapper的读操作

  下图显示了在一个容器中读取一个块(地址是0x44f)的过程。
  
    应用在容器中请求访问块0x44f。
    因为容器是镜像的一个thin快照,它没有实际的数据。但它有指针,指向镜像栈中数据所在的镜像快照。
    存储驱动根据指针找到对应镜像层a005的快照块0xf33。
    devicemapper拷贝镜像快照中块0xf33的数据到容器内存中。
    容器驱动将数据返回给请求应用。

写操作

   使用devicemapper驱动,写数据到容器是通过一个按需分配操作来完成的。更新已有的数据使用了copy-on-write操作。不过Device Mapper是基于块存储的技术,所以这些操作都发生在块的级别。
   例如,要对容器中的一个大文件作小的修改,devicemapper驱动不拷贝整个文件,它只拷贝要修改的内容对应的块,每个块大小为64KB。

写数据

  向容器写55KB的数据:
    应用向容器发起写56KB数据的请求;
    按需分配操作给容器快照分配了一个新的64KB的块。
    如果写的数据大于64KB,就需要分配多个块给容器快照。
    数据写向新分配的块。

覆写已有数据

  第一次修改已有的数据:
    应用向容器发起修改数据的请求;
    copy-on-write操作定位到需要更新的块;
    分配新的块给容器快照,并拷贝数据到这些块中;
    修改的数据写向新分配的这些块。
  容器中的应用并不会感知到这些按需分配和copy-on-write操作。然而,这些操作还是可能会对应用的读写带来一些延迟。

Docker中配置devicemapper

  devicemapper是部分Linux发行版的默认Docker存储驱动,这其中就包括RHEL和它的分支。当前,以前发行版支持该驱动:
   ●RHEL/CentOS/Fedora
   ●Ubuntu
   ●Debian
   ●Arch Linux
  Docker host使用loop-lvm的配置模式来运行devicemapper。该模式使用系数文件来创建thin池,这些池用于镜像和容器快照。并且这些模式是开箱即用的,无需额外配置。不过,不建议在产品部署中使用loop-lvm模式。
  可以通过docker info命令来查看是否使用了该模式。

$ sudo docker infoContainers: 0Images: 0Storage Driver: devicemapperPool Name: docker-202:2-25220302-poolPool Blocksize: 65.54 kBBacking Filesystem: xfs[...]Data loop file: /var/lib/docker/devicemapper/devicemapper/dataMetadata loop file: /var/lib/docker/devicemapper/devicemapper/metadataLibrary Version: 1.02.93-RHEL7 (2015-01-28)[...]

  通过上面输出可得出,Docker host使用devicemapper存储驱动。并且,还使用了loop-lvm模式,因为/var/lib/docker/devicemapper/devicemapper下有Data loop file和Metadata loop file这两个文件。这些都是loopback映射的稀疏文件。

在产品中配置direct-lvm模式

  产品部署中应该使用direct-lvm模式,该模式使用块设备来创建thin池。下面的步骤描述了如何在Docker host使用direct-lvm模式得devicemapper存储驱动。
  注意:如果你已经在Docker host上运行了Docker daemon,并且有一些想保存的镜像,那么在执行以下步骤之前,把它们push到Docker Hub,或者你的私有Docker Registry。
  以下步骤会创建一个逻辑卷,配置为thin池,用作后端的存储池。假设你有一个稀疏块设备/dev/xvdf,并且该设备有足够的空间来完成这个任务。在你的环境中,设备标识符和卷的大小可能不同,在你执行下面过程时,你应该替换为适合你环境的值。另外,以下的步骤应该在Docker Daemon停止的时候来执行。
   1) 进入Docker host,并停止Docker daemon;
   2) 安装LVM2和thin-provisioning-tools安装包;
   LVM2安装包提供了用户空间的工具,用于管理逻辑卷。
   thin-provisioning-tools用于激活和管理池。

# on Ubuntu$ sudo apt -y install lvm2# On CentOS$ sudo yum install -y lvm2

   3) 创建一个物理卷/dev/xvdf来替换块设备;

$ pvcreate /dev/xvdf

   4) 创建卷组docker;

$ vgcreate docker /dev/xvdf

   5) 创建名为thinpool和thinpoolmeta的虚拟卷;
   在该示例中,数据大小是docker卷组大小的95%,留下这些空闲空间,是用于数据或元数据的自动扩容。

$ lvcreate --wipesignatures y -n thinpool docker -l 95%VG$ lvcreate --wipesignatures y -n thinpoolmeta docker -l 1%VG

   6) 把池转换为thin池;

$ lvconvert -y --zero n -c 512K --thinpool docker/thinpool --poolmetadata docker/thinpoolmeta

   7) 通过lvm文件来配置thin池的自动扩容;

$ vi /etc/lvm/profile/docker-thinpool.profile

   8) 指定thin_pool_autoextend_threshold值;
   该值是lvm尝试扩容到可用空间时,当前已空间使用量的百分比(100=禁止)。

thin_pool_autoextend_threshold = 80

   9) 修改thin_pool_autoextend_percent;
   该值是thin池要扩容的百分比(100=禁止)。

thin_pool_autoextend_percent = 20

   10) 检查上面的步骤,你的docker-thinpool.profile文件应该是类似下面的内容:
   一个/etc/lvm/profile/docker-thinpool.profile示例文件:

activation {
thin_pool_autoextend_threshold=80
thin_pool_autoextend_percent=20
}

   11) 应用新的lvm profile文件;

$ lvchange --metadataprofile docker-thinpool docker/thinpool

   12) 确认lv是否被修改;

$ lvs -o+seg_monitor

   13) 如果之前Docker daemon被启动过,那么需要将之前的graph driver目录给挪走;
   移动graph driver会删除所有的镜像容器和卷。下面的命令将/var/lib/docker的内容移动到另一个目录中。

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

   14) 使用特殊的devicemapper选项来配置Docker daemon;
   有两种方法来配置Docker daemon的devicemapper存储驱动。你可以运行daemon时加上以下参数:

--storage-driver=devicemapper \--storage-opt=dm.thinpooldev=/dev/mapper/docker-thinpool \--storage-opt=dm.use_deferred_removal=true \--storage-opt=dm.use_deferred_deletion=true

   也可以在daemon配置文件中配置,如默认的配置文件/etc/docker/daemon.json中,可如下配置:

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

   注意:总是使用dm.use_deferred_removal=true和dm.use_deferred_deletion=true选项,以防止无意地泄露映射资源信息。
   15) (可选的)如果使用了systemd,并且修改了daemon配置文件,需要重载systemd信息;

$ systemctl daemon-reload

   16) 重启Docker daemon。

$ systemctl start docker

  当你启动Docker daemon后,确保一直监控者thin池和卷组的可用空间。当卷组自动扩容时,可能会占满所有空间。可以使用lvs或lvs -a命令来监控逻辑卷,可以查看到数据和元数据的大小。另外,还可以使用vgs命令来监控卷组的可用空间。
  当到达阈值后,日志会显示thin池的自动扩容信息,可使用以下命令来查看日志:

$ journalctl -fu dm-event.service

  当你确认你的配置文件无误时,就可以删除之前的备份目录了。

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

  你还可以使用dm.min_free_space参数。该值保证党可用空间到达或者接近最小值时,操作失败会有提示。可以查看更多的驱动选项。

检查devicemapper结构体

  可以通过lsblk命令查看devicemapper存储驱动创建的pool相关的设备文件。

$ sudo lsblkNAME               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda               202:0    0    G  0 disk
└─xvda1            202:1    0    G  0 part /
xvdf               202:80   0   0G  0 disk
├─vg--docker-data          253:0    0   0G  0 lvm
│ └─docker-202:1-1032-pool 253:2    0   0G  0 dm
└─vg--docker-metadata      253:1    0    G  0 lvm└─docker-202:1-1032-pool 253:2    0   0G  0 dm

  下图显示了上面示例的镜像信息。
  
  图中,pool的名称叫做Docker-202:1-1032-pool,横跨data和metadata两个设备。devicemapper的pool名称格式为:

Docker-MAJ:MIN-INO-pool

  MAJ,MIN和INFO分别表示major、minor设备号,和inode号。
  有两个主要的目录。/var/lib/docker/devicemapper/mnt目录包含镜像和容器层的映射点。/var/lib/docker/devicemapper/metadata目录为每个镜像层和容器快照都对应了一个文件,文件以JSON格式保存每个快照的元数据。

Device Mapper和Docker性能

  理解按需分配和copy-on-write可以让你对容器性能有个整体的了解。

按需分配性能影响

  devicemapper存储驱动在按需分配操作时会给容器分配一个新的块。也就是说每次应用向容器某个位置写数据时,一个或多个块就会从池里面分配,并且映射给容器。
  所有的块都是64KB大小,一个小于64KB的写请求也会导致分配64KB的块,大于64KB的写请求就要求多个64KB的块。这会影响容器的性能,尤其容器有很多小的写请求时。然而,一旦一个块分配给容器后,后续的读写都会直接操作这个新分配的块。

Copy-on-write性能影响

  每次容器第一次更新已有数据时,devicemapper存储驱动都会执行copy-on-write操作,该操作会将数据从镜像快照拷贝到容器快照。这在容器性能上有着明显的影响。
  所有的copy-on-write操作都有64KB的粒度。因此,要修改1GB文件的32KB内容时,只需要拷贝64KB大小的块到容器即可。如果要拷贝整个大文件到容器层时,该特性较于文件层的copy-on-write操作有着明显的性能优势。
  然而,实际中,如果容器执行大量的小的写请求时(<64KB),devicemapper性能差于AUFS。

其他device mapper性能注意事项

  还有一些点会影响devicemapper存储驱动的性能。
   模式。Docker运行devicemapper存储驱动的默认模式是loop-lvm。该模式使用稀疏文件,并且性能堪忧。在产品中不建议使用该模式,产品环境中建议使用direct-lvm,这样存储驱动就可以直接写向块设备。
   高速存储。为了更好的性能,可以将Data文件和Metadata文件放在高速存储(如SSD)上。当然,也可以直接连接到SAN或NAS array上。
   内存使用。devicemapper不是内存最高效的Docker存储驱动。启动同一个容器的n份拷贝需要将其文件大小的n份拷贝加载到内存中,这对于Docker host的内存有一定影响。因此,devicemapper存储驱动可能不是Pass或其他高密度用例的最优方案。
  最后一点,数据卷提供了更好和可预测的性能。因此,应该将负载高的写请求写到数据卷中。

转载于:https://blog.51cto.com/welcomeweb/1921289

DOCKER存储驱动之DEVICE MAPPER简介相关推荐

  1. Docker存储驱动

    Docker Storage Driver 每个 Docker 容器都有一个本地存储空间,用于保存层叠的镜像层(Image Layer)以及挂载的容器文件系统. 默认情况下,容器的所有读写操作都发生在 ...

  2. Docker存储驱动之OverlayFS简介

    简介 OverlayFS是一种和AUFS很类似的文件系统,与AUFS相比,OverlayFS有以下特性: 1) 更简单地设计: 2) 从3.18开始,就进入了Linux内核主线: 3) 可能更快一些. ...

  3. Device Mapper 简介

    docker Device Mapper 简介 文章目录 docker Device Mapper 简介 1. 简介 2. 用户空间和内核空间 3. Device Mapper 技术分析 4. Doc ...

  4. Docker——docker存储驱动原理

    摘要 Docker 主要是基于 Namespace.cgroups 和联合文件系统这三大核心技术实现的.联合文件系统(Union File System,Unionfs)是一种分层的轻量级文件系统,它 ...

  5. Docker存储驱动devicemapper介绍和配置

    一.devicemapper介绍 1 2 3 4 5 6 7 8 9 Device Mapper是Linux系统中基于内核的高级卷管理技术框架.Docker的devicemapper存储驱动就是基于该 ...

  6. docker存储驱动模式之direct-lvm配置

    最近在虚拟机上玩docker,但是发现默认安装使用的是loop-lvm的模式做后端存储,这个肯对对后面的实验会造成影响,而且docker官方也不建议在生产环境下使用loop-lvm,下图为docker ...

  7. docker 存储驱动之overlay

    overlay OverlayFS是一个类似于AUFS 的现代联合文件系统,但更快,实现更简单.Docker为OverlayFS提供了一个存储驱动程序. * 注:OverlayFS是内核提供的文件系统 ...

  8. docker 存储驱动之overlay2

    overlay2 overlay2原生支持128层,这提供docker build和docker commit更好的性能支持 在执行完docker pull ubuntu后,可以看到 $ ls -l ...

  9. Docker 存储选型,这些年我们遇到的坑

    戳蓝字"CSDN云计算"关注我们哦! 技术头条:干货.简洁.多维全面.更多云计算精华知识尽在眼前,get要点.solve难题,统统不在话下! 随着Docker 容器技术的不断发展和 ...

最新文章

  1. 【第22周复盘】可以查成绩了!
  2. centos6.5安装zabbix3.4
  3. [已解决] InnoDB: preallocating bytes for file ./ibdata1 failed with error
  4. c#读取Sybase中文乱码的解决办法
  5. dos下批量卸载apk文件
  6. 【python】数据结构与算法—哈希表
  7. obs多推流地址_抖音obs推流直播怎么操作,抖音直播推流地址如何获取?
  8. 计算机网络原码反码补码,计算机的原码和反码及补码到底是什么
  9. java程序开发步骤
  10. LeetCode - Maximum Subarray
  11. 微信小程序种利用轮播图实现tab栏切换
  12. 北大毕业 15 年经验架构师,重磅解读 5G 时代的计算平台
  13. java 28181协议_WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的网络视频平台
  14. 【python】多进程返回值比较
  15. JDK动态代理执行过程分析
  16. dodaf体系结构建模与分析系统软件
  17. 【计算机图形学02】b-spline(b-样条曲线)
  18. 博科Brocade 300光纤交换机配置zone教程
  19. 当python撞上echarts时 add各个图形参数
  20. Javascript阻止事件冒泡和浏览器默认行为

热门文章

  1. GitHub 最受欢迎的Top 20 JavaScript 项目
  2. 拿下京东榜单第五首战告捷,看联想手机如何上演王者归来
  3. 只让输入数字、字母、中文的输入框
  4. hihoCoder 1257 Snake Carpet(很简单的构造方法)
  5. Linux命令之tree
  6. 使用Nagios监控esx、esxi、vcenter
  7. Hibernate type 与java 和 数据库类型对应
  8. (转)Android基础类之BaseAdapter
  9. mysql数据库商业版与社区版的区别
  10. UI自动化web端框架path.py代码