• devicemapper存储驱动下镜像的存储


    docker配置devicemapper存储驱动

    #查看当前使用的存储驱动,默认为overlay
    docker info | grep -i storage
    
    #停止docker
    systemctl stop docker
    #移除原存储配置文件 rm /etc/sysconfig/docker-storage #使用vdb磁盘创建pv pvcreate /dev/vdb #使用vdb磁盘创建dockercg vgcreate dockervg /dev/vdb #配置docker pool为dockervg cat <<EOF > /etc/sysconfig/docker-storage-setup VG=dockervg EOF #配置存储 docker-storage-setup #重启docker systemctl restart docker

    devicemapper存储驱动下镜像的存储

    docker数据存储的目录为/var/lib/docker,可以通过docker info | grep -i "Docker Root Dir" 查看

    以下通过构建一个镜像来观察镜像的存储方式,Dockerfile如下

    #创建测试目录
    mkdir  -p /tmp/docker-test && cd /tmp/docker-test
    
    #创建Dockerfile和测试文件
    echo <<EOF > Dockerfile
    FROM docker.io/resouer/guestbook:v1 (该镜像已存在节点)
    COPY 1 /tmp/1.txt
    COPY 2 /tmp/2.txt
    COPY 3 /tmp/3.txt
    EOF
    echo 111 > 1
    echo 222 > 2
    echo 333 > 3

    #构建镜像前/var/lib/docker/devicemapper两个目录文件数量如下

    #构建镜像

    docker build -t docker-test01 . --no-cache

    #构建镜像后/var/lib/docker/devicemapper两个目录文件数量如下

     #通过ls -lrt在metadate目录查看最新生成的文件,如图新增了3个文件与Dockerfile中的3个COPY层对应

    #每层分别有一个device_id,如下图

    使用device_id创建dm设备并挂载到文件系统

    如上,每个镜像层都会对应一个device_id

    #查看docker为其管理的容器所创建的dm设备
    dmsetup ls
    dmsetup table
    其中dmsetup table输出结果的格式如下
    logical_start_sector num_sectors target_type target_args
    开始扇区             扇区数      设备类型    设备参数
    
    如docker-253:1-1447237-b4b4ee02b3171ce0d9c9c39012b87dfe69c72fee4ab2a004bf03983ea00b612c: 0 20971520 thin 252:2 141
    
    docker-253:1-1447237-b4b4ee02b3171ce0d9c9c39012b87dfe69c72fee4ab2a004bf03983ea00b612c为在/dm设备名称
    0为起始扇区
    20971520 为扇区数,一个扇区大小为512kb,总共为10g
    thin为{未知,dm设备所使用的存储块按需分配?}
    252:2为dockervg-docker--pool的dm编号,可通过dmsetup ls查看
    141为device_id

    #为每个镜像层依次创建dm设备
    dmsetup create myimage-dm1 --table "0 20971520 thin 252:2 186"
    dmsetup create myimage-dm2 --table "0 20971520 thin 252:2 189"
    dmsetup create myimage-dm3 --table "0 20971520 thin 252:2 192"
    #查看/dev/mapper目录,发现新增了3个链接文件,链接到不同dm设备

    #创建测试挂载点,并挂载dm设备

    mkdir -p /tmp/mp1

    mkdir -p /tmp/mp2

    mkdir -p /tmp/mp3

    mount /dev/dm-19 /tmp/mp1/

    查看/tmp/mp1中的rootfs/tmp目录,如下,tmp目录只有一个1.txt文件,与Dockerfile中的第一个COPY层吻合

    继续通过mount /dev/dm-20 /tmp/mp2/  mount /dev/dm-21 /tmp/mp3/挂载第二层和第三层,均报Filesystem has duplicate UUID 040571c8-2123-4c9b-ab15-a77f69626835 - can't mount,如下

    #卸载dm-19,再挂载dm-20,可以看到tmp目录下对应Dockerfile中的第一个COPY和第二个COPY的内容

    umount /dev/dm-19 && mount /dev/dm-20 /tmp/mp2

    #再次dm-20,再挂载dm-21,可以发现tmp目录是对应的全部的三个测试文件

    以上说明,镜像的每一个层是根据Dockerfile中的顺序依次叠加的

    应用

    每个镜像层是上一个镜像层的一个快照,容器层则是顶层镜像的快照,每一个容器也会对应一个DeviceId。当容器死掉之后,docker会默认移除这个容器对应的dm设备,那么这个死掉的容器的rootfs就没有挂载到文件系统上,可以通过docker inspect {containerId} | grep -i deviceid获取到DeviceId之后,使用上文提到的方法创建dm设备并挂载到文件系统,这样就可以取出死掉的容器中的内容。

    参考:

    https://www.cnblogs.com/xuxinkun/p/10643840.html

    https://blog.csdn.net/felix_yujing/article/details/54344251

    摘抄至上述链接:

    关于读
    官网上读操作的说明图如下:

    1)应用请求读取容器中的0x44f块区
    因为容器是镜像的一个简单快照,并没有数据只有一个指针,指向镜像层存储数据的地方。
    2)存储驱动根据指针,到镜像快照的a005e镜像层寻找0xf33块区
    3)devicemapper从镜像快照拷贝0xf33的内容到容器的内存中
    4)存储驱动最后将数据返回给请求的应用

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

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

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

    关于devicemapper的性能
    allocate-on-demand的性能影响
    每当应用有新数据要写入容器时,都要从pool中去定位空的块区并映射给容器。因为所有块区都是64KB的,小于64KB的数据也会分配一个块区;大于64B的数据则会分配多个块区。所以,特别是当发生很多小的写操作时,就会比较影响容器的性能。

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

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

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

  • 相关阅读:
    mysql存储过程的优点
    MySQL复制
    优化数据库的方法
    MySQL表分区
    Http请求
    memcache和redis的区别
    触发器实现原理
    PHP常见数组函数与实例
    git 打包指定提交过的代码
    发送HTTP请求方法
  • 原文地址:https://www.cnblogs.com/orchidzjl/p/11733601.html
Copyright © 2020-2023  润新知