程序员人生 网站导航

docker的devicemapper存储驱动

栏目:服务器时间:2017-02-04 08:54:27

最近在官网上看了下devicemapper的说明文档,这里扼要总结1下。

1 诞生的背景

期初docker是运行在Debian和Ubuntu系统上的,使用的是AUFS方式的存储。后来很多企业希望在Redhat系linux上运行docker,并决定基于现有的Device Mapper技术开发1个新的存储方案,这就是devicemapper。

2 镜像的分层和同享

Device Mapper技术不是依照文件级别(file level),而是按块级别(block level)工作的,所以devicemapper也属于块级存储方案,有着thin provisioning和copy-on-write的特点。

  • thin provisioning
    这个不知道该怎样翻译,网上叫自动精简配置的比较多(与此相对的传统的存储配置模型被称为厚存储配置FP),简单的说就是在需要的时候分配所需的最小空间(与此相对,传统的存储空间的分配都是超过目前的需求的,从而致使的1个问题就是存储利用率低下)。
  • copy-on-write
    简单的理解就是,在内容产生变化的时候才进行内容复制。

devicemapper存储方式下的镜像

使用devicemapper存储生成镜像大致依照下面的流程:
首先,devicemapper驱动从块装备创建1个小的存储池(a thin pool)
然后,创建1个带有文件系统,如extfs等,的基础装备(base device)
以后,每一个新的镜像(或镜像层)都是base device的1个快照(snapshot)

devicemapper存储方式下的容器

devicemapper存储方式下,容器层都是从镜像生成的快照,快照里存储着所有对容器的更新。当数据被写入容器的时候,devicemapper按需从池中分配空间。

下面是官方文档中的1个说明图:
这里写图片描述
从上图可以看出,每一个镜像层都是它下面1层的快照。每一个镜像的最下面1层的镜像则是池中base device的快照。需要注意的是,base device属于Device Mapper的1部份,其实不是docker的镜像层。

3 devicemapper下的读写

关于读

官网上读操作的说明图以下:
这里写图片描述
1)利用要求读取容器中的0x44f块区
由于容器是镜像的1个简单快照,并没有数据只有1个指针,指向镜像层存储数据的地方。
2)存储驱动根据指针,到镜像快照的a005e镜像层寻觅0xf33块区
3)devicemapper从镜像快照拷贝0xf33的内容到容器的内存中
4)存储驱动最后将数据返回给要求的利用

关于写

当对容器中的大文件做1个小的改动的时候,devicemapper不会复制这全部文件,而是只拷贝被修改的块区。每一个块区的大小为64KB。

  • 写新数据的情况
    例如,写56KB大小的新数据到1个容器:
    1)利用发出1个要写56KB的新数据到容器的要求
    2)根据按需分配,将分配1个新的64KB的块区给容器的快照
    如果写操作的数据大于64KB的话,将分配多个块区
    3)以后,数据将被写入到新分配的块区中

  • 覆写已有的数据
    每当容器第1次更新已有的数据时:
    1)利用发出1个修改容器中数据的要求
    2)copy-on-write操作将定位到需要更新的块区
    3)然后分配新的空块区给容器快照,并复制数据到新分配的块区
    4)接着,在有复制数据的新块区中进行数据修改
    容器中的利用对产生的allocate-on-demand操作和copy-on-write操作是无感的

4 关于devicemapper的配置

Redhat系的linux发行版都采取devicemapper作为docker的默许存储驱动。目前,Debian,Ubuntu和Arch Linux也支持devicemapper。

devicemapper默许使用的是loop-lvm模式,这个模式使用sparse files来创建供镜像和容器快照使用的thin pool。但是,生产环境不要使用loop-lvm模式,官方建议使用direct-lvm模式。direct-lvm模式使用块装备(block devices)来创建thin pool。

假定/dev/mapper/docker-thinpool是已建好的lvm的逻辑卷,可以配置docker 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

官方说设置dm.use_deferred_removal=true和dm.use_deferred_deletion=true选项可以避免unintentionally leaking mount points(没太明白甚么意思,总之配了比不配好吧)。

devicemapper在主机上的结构

使用lsblk命令可以查看装备文件和devicemapper在装备文件上创建的pool:
这里写图片描述
对应上面接口的层次图以下:
这里写图片描述
可以看出,名为Docker⑵02:1⑴032-pool的pool横跨在data和metadata装备之上。pool的命名规则为:

Docker-主装备号:2级装备号-inode号-pool

docker 1.10和以后的版本,在/var/lib/docker目录下不在采取镜像层ID来关联目录名了,有另外两个比较重要的目录:
/var/lib/docker/devicemapper/mnt 包括镜像和容器层的挂载目录;
/var/lib/docker/devicemapper/metadata 目录包括每一个镜像层和容器快照的json格式的文件。

另外,当数据的逻辑卷要满的时候,可以给pool进行扩容,具体操作看官网。

5 关于devicemapper的性能

allocate-on-demand的性能影响

每当利用有新数据要写入容器时,都要从pool中去定位空的块区并映照给容器。由于所有块区都是64KB的,小于64KB的数据也会分配1个块区;大于64B的数据则会分配多个块区。所以,特别是当产生很多小的写操作时,就会比较影响容器的性能。

copy-on-write的性能影响

每当容器第1次更新已有的数据时,devicemapper存储驱动都要履行copy-on-write操作。这个操作是从镜像快照复制数据到容器快照,这对容器性能还是有比较明显的性能影响的。当容器产生很多小64KB的写操作时,devicemapper的性能会比AUFS要差。

其它方面

1)所使用的mode
默许情况下,devicemapper使用的是loop-lvm模式,这类模式使用的是sparse files,性能比较低。生产环境建议使用direct-lvm模式,这类模式存储驱动直接写数据到块装备。
2)使用高速存储
如果希望更好的性能,可以将Data file和Metadata file放到SSD这样的高速存储上。
3)内存使用
devicemapper其实不是1个有效使用内存的存储驱动。当1个容器运行n个时,它的文件也会被拷贝n份到内存中,这对docker宿主机的内存使用会造成明显影响。因此,devicemapper存储驱动可能其实不是PaaS和其它高密度使用型的最好选择。

对写操作较大的,可以采取挂载data volumes。使用data volumes可以绕过存储驱动,从而不受thin provisioning和copy-on-write产生的负责影响。

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐