Device Mapper 簡(jiǎn)介
DeviceMapper自Linux 2.6被引入成為了Linux最重要的一個(gè)技術(shù)。它在內(nèi)核中支持邏輯卷管理的通用設(shè)備映射機(jī)制樟遣,它為實(shí)現(xiàn)用于存儲(chǔ)資源管理的塊設(shè)備驅(qū)動(dòng)提供了一個(gè)高度模塊化的內(nèi)核架構(gòu)而叼,它包含三個(gè)重要的對(duì)象概念,Mapped Device豹悬、Mapping Table葵陵、Target device。
Mapped Device 是一個(gè)邏輯抽象瞻佛,可以理解成為內(nèi)核向外提供的邏輯設(shè)備埃难,它通過(guò)Mapping Table描述的映射關(guān)系和 Target Device 建立映射。Target device 表示的是 Mapped Device 所映射的物理空間段涤久,對(duì) Mapped Device 所表示的邏輯設(shè)備來(lái)說(shuō)涡尘,就是該邏輯設(shè)備映射到的一個(gè)物理設(shè)備。
Mapping Table里有 Mapped Device 邏輯的起始地址响迂、范圍考抄、和表示在 Target Device 所在物理設(shè)備的地址偏移量以及Target 類(lèi)型等信息(注:這些地址和偏移量都是以磁盤(pán)的扇區(qū)為單位的,即 512 個(gè)字節(jié)大小蔗彤,所以川梅,當(dāng)你看到128的時(shí)候,其實(shí)表示的是128*512=64K)然遏。
DeviceMapper 中的邏輯設(shè)備Mapped Device不但可以映射一個(gè)或多個(gè)物理設(shè)備Target Device贫途,還可以映射另一個(gè)Mapped Device,于是待侵,就是構(gòu)成了一個(gè)迭代或遞歸的情況丢早,就像文件系統(tǒng)中的目錄里除了文件還可以有目錄,理論上可以無(wú)限嵌套下去秧倾。
DeviceMapper在內(nèi)核中通過(guò)一個(gè)一個(gè)模塊化的 Target Driver 插件實(shí)現(xiàn)對(duì) IO 請(qǐng)求的過(guò)濾或者重新定向等工作怨酝,當(dāng)前已經(jīng)實(shí)現(xiàn)的插件包括軟 Raid、加密那先、多路徑农猬、鏡像、快照等售淡,這體現(xiàn)了在 Linux 內(nèi)核設(shè)計(jì)中策略和機(jī)制分離的原則斤葱。如下圖所示慷垮。從圖中,我們可以看到DeviceMapper只是一個(gè)框架揍堕,在這個(gè)框架上料身,我們可以插入各種各樣的策略(讓我不自然地想到了面向?qū)ο笾械牟呗阅J剑谶@諸多“插件”中鹤啡,有一個(gè)東西叫Thin Provisioning Snapshot惯驼,這是Docker使用DeviceMapper中最重要的模塊。
Thin Provisioning 簡(jiǎn)介
Thin Provisioning要怎么翻譯成中文递瑰,真是一件令人頭痛的事祟牲,我就不翻譯了。這個(gè)技術(shù)是虛擬化技術(shù)中的一種抖部。它是什么意思呢说贝?你可以聯(lián)想一下我們計(jì)算機(jī)中的內(nèi)存管理中用到的——“虛擬內(nèi)存技術(shù)”——操作系統(tǒng)給每個(gè)進(jìn)程N(yùn)多N多用不完的內(nèi)址地址(32位下,每個(gè)進(jìn)程可以有最多2GB的內(nèi)存空間)慎颗,但是呢乡恕,我們知道,物理內(nèi)存是沒(méi)有那么多的俯萎,如果按照進(jìn)程內(nèi)存和物理內(nèi)存一一映射來(lái)玩的話傲宜,那么,我們得要多少的物理內(nèi)存啊夫啊。所以函卒,操作系統(tǒng)引入了虛擬內(nèi)存的設(shè)計(jì),意思是撇眯,我邏輯上給你無(wú)限多的內(nèi)存报嵌,但是實(shí)際上是實(shí)報(bào)實(shí)銷(xiāo),因?yàn)槲抑滥阋欢ㄓ貌涣四敲炊嘈荛唬谑敲_(dá)到了內(nèi)存使用率提高的效果。(今天云計(jì)算中很多所謂的虛擬化其實(shí)完全都是在用和“虛擬內(nèi)存”相似的Thin Provisioning的技術(shù)玄坦,所謂的超配血筑,或是超賣(mài))
好了,話題拉回來(lái)营搅,我們這里說(shuō)的是存儲(chǔ)云挟。看下面兩個(gè)圖转质,第一Fat Provisioning,第二個(gè)是Thin Provisioning帖世,其很好的說(shuō)明了是個(gè)怎么一回事(和虛擬內(nèi)存是一個(gè)概念)
那么休蟹,Docker是怎么使用Thin Provisioning這個(gè)技術(shù)做到像UnionFS那樣的分層鏡像的呢沸枯?答案是,Docker使用了Thin Provisioning的Snapshot的技術(shù)赂弓。下面我們來(lái)介紹一下Thin Provisioning的Snapshot绑榴。
Thin Provisioning Snapshot 演示
下面,我們用一系列的命令來(lái)演示一下Device Mapper的Thin Provisioning Snapshot是怎么玩的盈魁。
首先翔怎,我們需要先建兩個(gè)文件,一個(gè)是data.img杨耙,一個(gè)是meta.data.img:
~hchen$ sudo 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
~hchen$ sudo 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選項(xiàng)赤套,其表示為略過(guò)of選項(xiàng)指定的輸出文件的前10G個(gè) output的 bloksize 的空間后再寫(xiě)入內(nèi)容。因?yàn)閎s是1個(gè)字節(jié)珊膜,所以也就是10G的尺寸容握,但其實(shí)在硬盤(pán)上是沒(méi)有占有空間的,占有空間只有1k的內(nèi)容车柠。當(dāng)向其寫(xiě)入內(nèi)容時(shí)剔氏,才會(huì)在硬盤(pán)上為其分配空間。我們可以用ls命令看一下竹祷,實(shí)際分配了12K和4K谈跛。
~hchen$ sudo ls -lsh /tmp/data.img
12K -rw-r--r--. 1 root root 11G Aug 25 23:01 /tmp/data.img
~hchen$ sudo ls -slh /tmp/meta.data.img
4.0K -rw-r--r--. 1 root root 101M Aug 25 23:17 /tmp/meta.data.img
然后,我們?yōu)檫@個(gè)文件創(chuàng)建一個(gè)loopback設(shè)備塑陵。(loop2015和loop2016是我亂取的兩個(gè)名字)
~hchen$ sudo losetup /dev/loop2015 /tmp/data.img
~hchen$ sudo losetup /dev/loop2016 /tmp/meta.data.img
~hchen$ sudo losetup -a
/dev/loop2015: [64768]:103991768 (/tmp/data.img)
/dev/loop2016: [64768]:103991765 (/tmp/meta.data.img)
現(xiàn)在感憾,我們?yōu)檫@個(gè)設(shè)備建一個(gè)Thin Provisioning的Pool,用dmsetup命令:
~hchen$ sudo dmsetup create hchen-thin-pool \
--table "0 20971522 thin-pool /dev/loop2016 /dev/loop2015 \
128 65536 1 skip_block_zeroing"
其中的參數(shù)解釋如下:
- dmsetup create是用來(lái)創(chuàng)建thin pool的命令
- hchen-thin-pool 是自定義的一個(gè)pool名猿妈,不沖突就好吹菱。
- –table是這個(gè)pool的參數(shù)設(shè)置
。0代表起的sector位置
彭则。20971522代碼結(jié)句的sector號(hào)鳍刷,前面說(shuō)過(guò),一個(gè)sector是512字節(jié)俯抖,所以输瓜,20971522個(gè)正好是10GB
。/dev/loop2016是meta文件的設(shè)備(前面我們建好了)
芬萍。/dev/loop2015是data文件的設(shè)備(前面我們建好了)
尤揣。128是最小的可分配的sector數(shù)
。65536是最少可用sector的water mark柬祠,也就是一個(gè)threshold
北戏。1 代表有一個(gè)附加參數(shù)
。skip_block_zeroing是個(gè)附加參數(shù)漫蛔,表示略過(guò)用0填充的塊
然后嗜愈,我們就可以看到一個(gè)Device Mapper的設(shè)備了:
~hchen$ sudo ll /dev/mapper/hchen-thin-pool
lrwxrwxrwx. 1 root root 7 Aug 25 23:24 /dev/mapper/hchen-thin-pool -> ../dm-4
接下來(lái)旧蛾,我們的初始還沒(méi)有完成,還要?jiǎng)?chuàng)建一個(gè)Thin Provisioning 的 Volume:
~hchen$ sudo dmsetup message /dev/mapper/hchen-thin-pool 0 "create_thin 0"
~hchen$ sudo dmsetup create hchen-thin-volumn-001 \
--table "0 2097152 thin /dev/mapper/hchen-thin-pool 0"
其中:
- 第一個(gè)命令中的create_thin是關(guān)鍵字蠕嫁,后面的0表示這個(gè)Volume的device 的 id
- 第二個(gè)命令锨天,是真正的為這個(gè)Volumn創(chuàng)建一個(gè)可以mount的設(shè)備,名字叫hchen-thin-volumn-001剃毒。2097152只有1GB
好了病袄,在mount前,我們還要格式化一下:
~hchen$ sudo 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了(下面的命令中益缠,我還創(chuàng)建了一個(gè)文件):
~hchen$ sudo mkdir -p /mnt/base
~hchen$ sudo mount /dev/mapper/hchen-thin-volumn-001 /mnt/base
~hchen$ sudo echo "hello world, I am a base" > /mnt/base/id.txt
~hchen$ sudo cat /mnt/base/id.txt
hello world, I am a base
好了,接下來(lái)纤壁,我們來(lái)看看snapshot怎么搞:
~hchen$ sudo dmsetup message /dev/mapper/hchen-thin-pool 0 "create_snap 1 0"
~hchen$ sudo dmsetup create mysnap1 \
--table "0 2097152 thin /dev/mapper/hchen-thin-pool 1"
~hchen$ sudo ll /dev/mapper/mysnap1
lrwxrwxrwx. 1 root root 7 Aug 25 23:49 /dev/mapper/mysnap1 -> ../dm-5
上面的命令中:
- 第一條命令是向hchen-thin-pool發(fā)一個(gè)create_snap的消息左刽,后面跟兩個(gè)id,第一個(gè)是新的dev id酌媒,第二個(gè)是要從哪個(gè)已有的dev id上做snapshot(0這個(gè)dev id是我們前面就創(chuàng)建了了)
- 第二條命令是創(chuàng)建一個(gè)mysnap1的device欠痴,并可以被mount。
下面我們來(lái)看看:
~hchen$ sudo mkdir -p /mnt/mysnap1
~hchen$ sudo mount /dev/mapper/mysnap1 /mnt/mysnap1
~hchen$ sudo 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
~hchen$ sudo cat /mnt/mysnap1/id.txt
hello world, I am a base
我們來(lái)修改一下/mnt/mysnap1/id.txt秒咨,并加上一個(gè)snap1.txt的文件:
~hchen$ sudo echo "I am snap1" >> /mnt/mysnap1/id.txt
~hchen$ sudo echo "I am snap1" > /mnt/mysnap1/snap1.txt
~hchen$ sudo cat /mnt/mysnap1/id.txt
hello world, I am a base
I am snap1
~hchen$ sudo cat /mnt/mysnap1/snap1.txt
I am snap1
我們?cè)倏匆幌?mnt/base喇辽,你會(huì)發(fā)現(xiàn)沒(méi)有什么變化:
~hchen$ sudo ls /mnt/base
id.txt lost+found
~hchen$ sudo cat /mnt/base/id.txt
hello world, I am a base
你是不是已經(jīng)看到了分層鏡像的樣子了?
你還要吧繼續(xù)在剛才的snapshot上再建一個(gè)snapshot:
~hchen$ sudo dmsetup message /dev/mapper/hchen-thin-pool 0 "create_snap 2 1"
~hchen$ sudo dmsetup create mysnap2 \
--table "0 2097152 thin /dev/mapper/hchen-thin-pool 2"
~hchen$ sudo ll /dev/mapper/mysnap2
lrwxrwxrwx. 1 root root 7 Aug 25 23:52 /dev/mapper/mysnap1 -> ../dm-7
~hchen$ sudo mkdir -p /mnt/mysnap2
~hchen$ sudo mount /dev/mapper/mysnap2 /mnt/mysnap2
~hchen$ sudo ls /mnt/mysnap2
id.txt lost+found snap1.txt
好了雨席,我相信你看到了分層鏡像的樣子了菩咨。
看完演示,我們?cè)賮?lái)補(bǔ)點(diǎn)理論知識(shí)吧:
- Snapshot來(lái)自LVM(Logic Volumn Manager)陡厘,它可以在不中斷服務(wù)的情況下為某個(gè)device打一個(gè)快照抽米。
- Snapshot是Copy-On-Write的,也就是說(shuō)糙置,只有發(fā)生了修改云茸,才會(huì)對(duì)對(duì)應(yīng)的內(nèi)存進(jìn)行拷貝。
Docker 的 Device Mapper
上面基本上就是Docker的玩法了谤饭,我們可以看一下docker的loopback設(shè)備:
~hchen $ sudo 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
~hchen $ sudo ls -alhs /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
下面是相關(guān)的thin-pool。其中揉抵,有個(gè)當(dāng)一大串hash串的device是正在啟動(dòng)的容器:
~hchen $ sudo 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都把它們記下來(lái)了):
~hchen $ sudo cat /var/lib/docker/devicemapper/metadata/deefcd630a60aa5ad3e69249f58a68e717324be4258296653406ff062f605edf
{"device_id":24,"size":10737418240,"transaction_id":26,"initialized":false}
device_id是24亡容,size是10737418240,除以512冤今,就是20971520 個(gè) sector闺兢,我們用這些信息來(lái)做個(gè)snapshot看看(注:我用了一個(gè)比較大的dev id – 1024):
~hchen$ sudo dmsetup message "/dev/mapper/docker-253:0-104108535-pool" 0 \ "create_snap 1024 24"
~hchen$ sudo dmsetup create dockersnap --table \
"0 20971520 thin /dev/mapper/docker-253:0-104108535-pool 1024"
~hchen$ sudo mkdir /mnt/docker
~hchen$ sudo mount /dev/mapper/dockersnap /mnt/docker/
~hchen$ sudo ls /mnt/docker/
id lost+found rootfs
~hchen$ sudo ls /mnt/docker/rootfs/
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
我們?cè)赿ocker的容器里用findmnt命令也可以看到相關(guān)的mount的情況(因?yàn)樘L(zhǎng),下面只是摘要):
# 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]
Device Mapper 行不行戏罢?
Thin Provisioning的文檔中說(shuō)列敲,這還處理實(shí)驗(yàn)階段阱佛,不要上Production.
There targets are very much still in the EXPERIMENTAL state.Please do not yet rely on them in production.
另外帖汞,Jeff Atwood在Twitter上發(fā)過(guò)這樣的一推:
這個(gè)推指向的這個(gè)討論中戴而,其中指向了這個(gè)code diff,基本上就是說(shuō)翩蘸,DeviceMapper這種東西問(wèn)題太多了所意,我們應(yīng)該把其加入黑名單。Doker的Founder也這樣回復(fù)到:
所以催首,如果你在使用loopback的devicemapper的話扶踊,當(dāng)你的存儲(chǔ)出現(xiàn)了問(wèn)題后,正確的解決方案是:
rm -rf /var/lib/docker
轉(zhuǎn)載
作者:陳皓
來(lái)源:酷殼-coolshell.cn
運(yùn)維自動(dòng)化班 6 期火熱報(bào)名中
課程概述:
理論結(jié)合實(shí)戰(zhàn)郎任,使學(xué)員既可掌握快速?gòu)牧銟?gòu)建一套實(shí)用秧耗、完整、可擴(kuò)展的運(yùn)維自動(dòng)化平臺(tái)舶治。
一
Django 基礎(chǔ)
- Django 類(lèi)視圖
- Django 模型
- Django 權(quán)限
- Django rest framework
- Django視圖綜述及綜合實(shí)戰(zhàn)
二
SQL 自動(dòng)化上線平臺(tái) - 手動(dòng)VS自動(dòng)的現(xiàn)狀對(duì)比
- Mysql分井,Inception,SQLAdvisor 講解
- 用戶權(quán)限設(shè)計(jì)霉猛,執(zhí)行流程梳理尺锚,平臺(tái)登錄雙因子安全認(rèn)證
- 敏感配置加解密實(shí)現(xiàn),人員/數(shù)據(jù)庫(kù)配置設(shè)計(jì)惜浅,整體代碼實(shí)現(xiàn)
三
公有云管理系統(tǒng) - 通過(guò)API對(duì)「Aws瘫辩、阿里云、騰訊云坛悉、青云伐厌、百度云」管理
- 工單系統(tǒng)和云管理平臺(tái)聯(lián)動(dòng)
- 后續(xù)展望:公有云賬單、比價(jià)裸影、資源監(jiān)控
四
任務(wù)管理系統(tǒng) - Ansible 簡(jiǎn)介及常用場(chǎng)景分析
- Ansible API 二次開(kāi)發(fā)入門(mén)
- 基于Ansible Playbook API 快速實(shí)現(xiàn)任務(wù)管理系統(tǒng)
五
運(yùn)維工單系統(tǒng) - 工作中流程規(guī)范的設(shè)計(jì)思路
- 典型工單系統(tǒng)的實(shí)現(xiàn)原理 —— 狀態(tài)機(jī)
六
代碼管理系統(tǒng)及發(fā)布平臺(tái) - 基于 Gitlab + Jenkins + DevOps 平臺(tái)實(shí)現(xiàn) CI/CD 的設(shè)計(jì)思路
- 結(jié)合運(yùn)維平臺(tái)流程規(guī)范實(shí)現(xiàn)持續(xù)集成與交付
- 展望:結(jié)合 ELK 的日志分析平臺(tái)挣轨,實(shí)現(xiàn)代碼上線運(yùn)維無(wú)人值守
七
贈(zèng)送 SaltStack 二次開(kāi)發(fā)視頻 - SaltStack 快速入門(mén)
- SaltStack 數(shù)據(jù)系統(tǒng)
- SaltStack 遠(yuǎn)程執(zhí)行
- SaltStack 配置管理
- SlatStack 管理實(shí)踐
- SaltStack 實(shí)踐案例
- SaltStack 常用 API 使用及源碼剖析
- SaltStack 怎么和發(fā)布平臺(tái)聯(lián)動(dòng)
上課模式:
網(wǎng)絡(luò)直播班 線下面授班
咨詢(xún)報(bào)名:
QQ(1):979950755 小月
WeChat : 1902433859 小月
開(kāi)課時(shí)間:12月24日(周日)
課程大綱