Device Mapper系列基础教程:Thin Provisioning 实践


Thin Provisioning Snapshot 演练

Device Mapper系列基础教程:Thin Provisioning 实践

Thin Provisioning Snapshot 演练

  • Kubernetes 知识图谱
  • 云原生导航
  • 谷歌搜索
  • Raft 协议动画演示
  • 搬瓦工

    1. Thin Provisioning Snapshot 演示


    上一篇我们介绍了 Device Mapper 框架的技术原理及其核心概念,下面,我们用一系列的命令来演示一下 Device Mapper 的 Thin Provisioning Snapshot 是怎么玩的。

    首先,我们需要先建两个文件,一个是data.img,一个是meta.data.img:

    $ dd if=/dev/zero of=/tmp/data.img bs=1K count=1 seek=10M
    
    1+0 records in
    1+0 records out
    1024 bytes (1.0 kB) copied, 0.000621428 s, 1.6 MB/s
    
    $ dd if=/dev/zero of=/tmp/meta.data.img bs=1K count=1 seek=1G
    
    1+0 records in
    1+0 records out
    1024 bytes (1.0 kB) copied, 0.000140858 s, 7.3 MB/s
    

    注意命令中 seek 选项,其表示为略过 of 选项指定的输出文件的前 10G 个 output 的 bloksize 的空间后再写入内容。

    因为 bs 是 1 个字节,所以也就是 10G 的尺寸,但其实在硬盘上是没有占有空间的,占有空间只有 1k 的内容。当向其写入内容时,才会在硬盘上为其分配空间。

    我们可以用 ls 命令看一下,实际分配了 12K 和 4K。

    $ ls -lsh /tmp/data.img
    
    12K -rw-r--r--. 1 root root 11G Aug 25 23:01 /tmp/data.img
    
    $ ls -slh /tmp/meta.data.img
    
    4.0K -rw-r--r--. 1 root root 101M Aug 25 23:17 /tmp/meta.data.img
    

    然后,我们为这个文件创建一个 loopback 设备。(loop2015 和 loop2016 是我乱取的两个名字)

    $ losetup /dev/loop2015 /tmp/data.img
    $ losetup /dev/loop2016 /tmp/meta.data.img
    
    $ losetup -a
    
    /dev/loop2015: [64768]:103991768 (/tmp/data.img)
    /dev/loop2016: [64768]:103991765 (/tmp/meta.data.img)
    

    现在,我们为这个设备建一个 Thin Provisioning 的 Pool,用 dmsetup 命令:

    $ dmsetup create hchen-thin-pool \
      --table "0 20971522 thin-pool /dev/loop2016 /dev/loop2015 \
      128 65536 1 skip_block_zeroing"
    

    其中的参数解释如下(更多信息可参看 Thin Provisioning 的 man page):

    • dmsetup create 是用来创建 thin pool 的命令
    • hchen-thin-pool 是自定义的一个 pool 名,不冲突就好。
    • –-table 是这个 pool 的参数设置
      • 0 代表起的 sector 位置
      • 20971522 代表结尾的 sector 号,前面说过,一个 sector 是 512 字节,所以,20971522 个正好是 10GB
      • /dev/loop2016 是 meta 文件的设备(前面我们建好了)
      • /dev/loop2015 是 data 文件的设备
      • 128 是最小的可分配的 sector 数
      • 65536 是最少可用 sector 的 water mark,也就是一个 threshold
      • 1 代表有一个附加参数
      • skip_block_zeroing 是个附加参数,表示略过用 0 填充的块

    然后,我们就可以看到一个 Device Mapper 的设备了:

    $ ll /dev/mapper/hchen-thin-pool
    
    lrwxrwxrwx. 1 root root 7 Aug 25 23:24 /dev/mapper/hchen-thin-pool -> ../dm-4
    

    接下来,我们的初始还没有完成,还要创建一个 Thin Provisioning 的 Volume:

    $ dmsetup message /dev/mapper/hchen-thin-pool 0 "create_thin 0"
    
    $ dmsetup create hchen-thin-volumn-001 \
      --table "0 2097152 thin /dev/mapper/hchen-thin-pool 0"
    

    其中:

    • 第一个命令中的 create_thin 是关键字,后面的 0 表示这个 Volume 的 device 的 id。
    • 第二个命令,是真正的为这个 Volumn 创建一个可以 mount 的设备,名字叫 hchen-thin-volumn-0012097152 只有 1GB。

    好了,在 mount 前,我们还要格式化一下:

    $ mkfs.ext4 /dev/mapper/hchen-thin-volumn-001
    
    mke2fs 1.42.9 (28-Dec-2013)
    Discarding device blocks: done
    Filesystem label=
    OS type: Linux
    Block size=4096 (log=2)
    Fragment size=4096 (log=2)
    Stride=16 blocks, Stripe width=16 blocks
    65536 inodes, 262144 blocks
    13107 blocks (5.00%) reserved for the super user
    First data block=0
    Maximum filesystem blocks=268435456
    8 block groups
    32768 blocks per group, 32768 fragments per group
    8192 inodes per group
    Superblock backups stored on blocks:
    32768, 98304, 163840, 229376
     
    Allocating group tables: done
    Writing inode tables: done
    Creating journal (8192 blocks): done
    Writing superblocks and filesystem accounting information: done
    

    好了,我们可以 mount 了(下面的命令中,我还创建了一个文件)

    $ mkdir -p /mnt/base
    
    $ mount /dev/mapper/hchen-thin-volumn-001 /mnt/base
    
    $ echo "hello world, I am a base" > /mnt/base/id.txt
    
    $ cat /mnt/base/id.txt
    
    hello world, I am a base
    

    接下来,我们来看看 snapshot 怎么搞:

    $ dmsetup message /dev/mapper/hchen-thin-pool 0 "create_snap 1 0"
    
    $ dmsetup create mysnap1 \
      --table "0 2097152 thin /dev/mapper/hchen-thin-pool 1"
      
    $ ll /dev/mapper/mysnap1
    
    lrwxrwxrwx. 1 root root 7 Aug 25 23:49 /dev/mapper/mysnap1 -> ../dm-5
    

    上面的命令中:

    • 第一条命令是向 hchen-thin-pool 发一个 create_snap 的消息,后面跟两个 id,第一个是新的 dev id,第二个是要从哪个已有的 dev id 上做 snapshot(0 这个 dev id 是我们前面就创建了了)
    • 第二条命令是创建一个 mysnap1 的 device,并可以被 mount。

    下面我们来看看:

    $ mkdir -p /mnt/mysnap1
    
    $ mount /dev/mapper/mysnap1 /mnt/mysnap1
    
    $ ll /mnt/mysnap1/
    
    total 20
    -rw-r--r--. 1 root root 25 Aug 25 23:46 id.txt
    drwx------. 2 root root 16384 Aug 25 23:43 lost+found
    
    $ cat /mnt/mysnap1/id.txt
    
    hello world, I am a base
    

    我们来修改一下 /mnt/mysnap1/id.txt,并加上一个 snap1.txt 的文件:

    $ echo "I am snap1" >> /mnt/mysnap1/id.txt
    
    $ echo "I am snap1" > /mnt/mysnap1/snap1.txt
    
    $ cat /mnt/mysnap1/id.txt
    
    hello world, I am a base
    I am snap1
    
    $ cat /mnt/mysnap1/snap1.txt
    
    I am snap1
    

    我们再看一下 /mnt/base,你会发现没有什么变化:

    $ ls /mnt/base
    
    id.txt      lost+found
    
    $ cat /mnt/base/id.txt
    
    hello world, I am a base
    

    好了,我相信你看到了分层镜像的样子了。

    2. Docker 的 devicemapper


    上面基本上就是 Docker 的玩法了,我们可以看一下 docker 的 loopback 设备:

    $ losetup -a
    
    /dev/loop0: [64768]:38050288 (/var/lib/docker/devicemapper/devicemapper/data)
    /dev/loop1: [64768]:38050289 (/var/lib/docker/devicemapper/devicemapper/metadata)
    

    其中 data 100GB,metadata 2.0GB

    $ ls -alsh /var/lib/docker/devicemapper/devicemapper
    
    506M -rw-------. 1 root root 100G Sep 10 20:15 data
    1.1M -rw-------. 1 root root 2.0G Sep 10 20:15 metadata
    

    下面是相关的 thin-pool。其中,有个当一大串 hash 串的 device 是正在启动的容器:

    $ ll /dev/mapper/dock*
    
    lrwxrwxrwx. 1 root root 7 Aug 25 07:57 /dev/mapper/docker-253:0-104108535-pool -> ../dm-2
    lrwxrwxrwx. 1 root root 7 Aug 25 11:13 /dev/mapper/docker-253:0-104108535-deefcd630a60aa5ad3e69249f58a68e717324be4258296653406ff062f605edf -> ../dm-3
    

    我们可以看一下它的 device id(Docker 都把它们记下来了):

    $ cat /var/lib/docker/devicemapper/metadata/deefcd630a60aa5ad3e69249f58a68e717324be4258296653406ff062f605edf
    

    device_id 是 24,size 是 10737418240,除以 512,就是 20971520sector

    我们用这些信息来做个 snapshot 看看(注:我用了一个比较大的 dev id – 1024):

    $ dmsetup message "/dev/mapper/docker-253:0-104108535-pool" 0 \
      "create_snap 1024 24"
      
    $ dmsetup create dockersnap --table \
      "0 20971520 thin /dev/mapper/docker-253:0-104108535-pool 1024"
      
    $ mkdir /mnt/docker
    
    $ mount /dev/mapper/dockersnap /mnt/docker/
    
    $ ls /mnt/docker/
    
    id lost+found rootfs
    
    $ ls /mnt/docker/rootfs/
    
    bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
    

    我们在 docker 的容器里用 findmnt 命令也可以看到相关的 mount 的情况(因为太长,下面只是摘要):

    $ findmnt
    
    TARGET                SOURCE               
    /                 /dev/mapper/docker-253:0-104108535-deefcd630a60[/rootfs]
    /etc/resolv.conf  /dev/mapper/centos-root[/var/lib/docker/containers/deefcd630a60/resolv.conf]
    /etc/hostname     /dev/mapper/centos-root[/var/lib/docker/containers/deefcd630a60/hostname]
    /etc/hosts        /dev/mapper/centos-root[/var/lib/docker/containers/deefcd630a60/hosts]
    

    -------他日江湖相逢 再当杯酒言欢-------

    「真诚赞赏,手留余香」

    米开朗基杨

    真诚赞赏,手留余香

    使用微信扫描二维码完成支付


    相关推荐