devicemapper 最佳實踐

devicemapper 最佳實踐

docker 最早是跑在ubuntu和debian上的,使用aufs存儲器. 因爲docker愈來愈流行,許多公司但願在RHEL上使用,可是上游內核中沒有包括aufs,因此rhel不能使用aufs. 最終開發者們開發了一個新的後端存儲引擎devicemapper,基於已有的Device Mapper技術,而且使docker支持可插拔,如今全世界有不少真實案例在生產環境使用devicemapper.docker

鏡像層與共享

devicemapper存儲每一個鏡像和容器在本身的虛擬設備上,也就是說這些設備是按需分配(copy-on-write snapshot devices),Device Mapper技術是工做在block級別的而不是文件級別的.ubuntu

devicemapper建立鏡像的方式是:後端

  1. devicemapper基於塊設備或loop mounted sparse files來建立一個虛擬池.
  2. 而後在上面建立一個有文件系統的基礎設備(base device).
  3. 每一個鏡像層就是基於這個基礎設備的COW快照(snapshot),也就是說這些快照初始化時是空的,只有數據寫入時纔會佔用池中的空間.

圖示:centos

base_device

容器就是在鏡像上再建立一個快照app

devicemapper的讀操做

例圖:oop

dm_container

  1. 容器中的應用請求塊0x44f,由於容器層也是個虛擬的快照,不存數據,只有指針.經過指針找到存放數據的鏡像層.
  2. 根據指針找到a005e層的0xf33.
  3. devicemapper copy其中的數據到容器內存中.
  4. 存儲驅動器返回數據給請求的應用.

devicemapper的寫操做

devicemapper寫操做是經過allocate-on-demand(按需分配)的方式.更新數據是經過COW方式. 由於devicemapper是一種基於塊的技術,因此就算修改一個大文件,也不會copy整個文件過來.只會copy對應要修改的塊.性能

寫新數據

寫56k的數據到容器中:this

  1. 應用請求寫56k的數據到容器
  2. 按需分配一個新的64k大小的塊在容器層.(超過64k,則分配多個)
  3. 數據寫入新分配的塊中

修改數據

  1. 應用請求修改容器中數據
  2. cow操做定位到要更新的塊
  3. 分配新的塊在容器層並將數據copy過來
  4. 對數據進行修改

配置docker使用devicemapper

基於rhel的分支默認使用的devicemapper,而且默認配置成loop-lvm模式運行.這種模式使用文件來做爲虛擬池(thin pool)構建鏡像和容器的層. 可是生產環境不因該使用這種模式.spa

經過docker info命令來檢查指針

[root@srv00 ~]# docker info 
 WARNING: Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.
...
 Data loop file: /var/lib/docker/devicemapper/devicemapper/data
 Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata
 Library Version: 1.02.107-RHEL7 (2015-12-01)
 ...

Data loop file,Metadata loop file指示了docker運行在loop-lvm模式下,而且還有個WARNING.

爲生產環境配置direct-lvm模式

生產環境下因該使用direct-lvm,若是以前有鏡像在loop-lvm模式下建立,須要切換,則因該將鏡像作備份.(push到hub或私有registry)

我給虛擬機分配個30G磁盤

1.中止docker daemon

[root@srv00 ~]# systemctl stop docker

2.建立相關的邏輯卷和thinpool

建立pv

[root@srv00 ~]# fdisk -l <==檢查下磁盤
...
Disk /dev/xvdb: 32.2 GB, 32212254720 bytes, 62914560 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

[root@srv00 ~]# pvcreate /dev/xvdb
  Physical volume "/dev/xvdb" successfully created

建立vg

[root@srv00 ~]# vgcreate vgdocker /dev/xvdb
  Volume group "vgdocker" successfully created

建立一個thin pool,名字叫thinpool,先來建立邏輯卷

[root@srv00 ~]# lvcreate --wipesignatures y -n thinpool -l 95%VG vgdocker
  Logical volume "thinpool" created.
[root@srv00 ~]# lvcreate --wipesignatures y -n thinpoolmeta -l 1%VG vgdocker  
  Logical volume "thinpoolmeta" created.
[root@srv00 ~]# lvscan
  ACTIVE            '/dev/centos/swap' [4.00 GiB] inherit
  ACTIVE            '/dev/centos/root' [35.47 GiB] inherit
  ACTIVE            '/dev/vgdocker/thinpool' [28.50 GiB] inherit
  ACTIVE            '/dev/vgdocker/thinpoolmeta' [304.00 MiB] inherit

剩餘的4%留給它們自動擴展

轉換成thin pool

[root@srv00 ~]# lvconvert -y --zero n -c 512K --thinpool vgdocker/thinpool --poolmetadata vgdocker/thinpoolmeta
  WARNING: Converting logical volume vgdocker/thinpool and vgdocker/thinpoolmeta to pool's data and metadata volumes.
  THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.)
  Converted vgdocker/thinpool to thin pool.

設置thinpool的自動擴展參數,並應用此profile

[root@srv00 ~]# vi /etc/lvm/profile/docker-thinpool.profile
activation {
    thin_pool_autoextend_threshold=80
    thin_pool_autoextend_percent=20
}
[root@srv00 ~]# lvchange --metadataprofile docker-thinpool vgdocker/thinpool
  Logical volume "thinpool" changed.

當空間大於80%時進行擴展.擴展的大小是空閒空間的20%

查看thinpool是不是已監視狀態

[root@srv00 ~]# lvs -o+seg_monitor
  LV       VG        Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert Monitor  
  root     centos    -wi-ao---- 35.47g                                                              
  swap     centos    -wi-ao----  4.00g                                                              
  thinpool vgdocker twi-a-t--- 28.50g             0.00   0.02                             monitored

3.刪除docker存儲目錄

[root@srv00 ~]# rm -rf /var/lib/docker/*

注意備份重要鏡像等

4.修改啓動參數並啓動

咱們經過systemd的drop-in方式修改,也是官方推薦的

[root@srv00 ~]# mkdir /etc/systemd/system/docker.service.d
[root@srv00 ~]# vi /etc/systemd/system/docker.service.d/daemon.conf
[Service]
ExecStart=
ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=devicemapper --storage-opt=dm.thinpooldev=/dev/mapper/vgdocker-thinpool --storage-opt dm.use_deferred_removal=true
[root@srv00 ~]# systemctl daemon-reload
[root@srv00 ~]# systemctl start docker

ExecStart= 第一行是空.不然啓動會報錯,而且修改daemon參數須要reload

5.檢查確認

[root@srv00 docker]# docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 0
Server Version: 1.11.1
Storage Driver: devicemapper
 Pool Name: vgdocker-thinpool
 Pool Blocksize: 524.3 kB
 Base Device Size: 10.74 GB
 Backing Filesystem: xfs
 ...
 [root@srv00 docker]# lvs -a
  LV               VG       Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root             centos   -wi-ao----  35.47g                                                    
  swap             centos   -wi-ao----   4.00g                                                    
  [lvol0_pmspare]  vgdocker ewi------- 304.00m                                                    
  thinpool         vgdocker twi-a-t---  28.50g             0.07   0.02                            
  [thinpool_tdata] vgdocker Twi-ao----  28.50g                                                    
  [thinpool_tmeta] vgdocker ewi-ao---- 304.00m                                                    
[root@srv00 docker]# lsblk
NAME                      MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sr0                        11:0    1 114.4M  0 rom  
xvda                      202:0    0    40G  0 disk 
├─xvda1                   202:1    0   500M  0 part /boot
└─xvda2                   202:2    0  39.5G  0 part 
  ├─centos-root           253:0    0  35.5G  0 lvm  /
  └─centos-swap           253:1    0     4G  0 lvm  [SWAP]
xvdb                      202:16   0    30G  0 disk 
├─vgdocker-thinpool_tmeta 253:2    0   304M  0 lvm  
│ └─vgdocker-thinpool     253:5    0  28.5G  0 lvm  
└─vgdocker-thinpool_tdata 253:3    0  28.5G  0 lvm  
  └─vgdocker-thinpool     253:5    0  28.5G  0 lvm

而後就能夠正常的docker run 了

devicemapper的性能影響

  • Allocate-on-demand性能影響

以前講說,若是容器中要寫數據,則會在容器層分配新的塊,每一個快64k,若是要寫的數據大於64k,則會分配多個塊. 若是容器中有許多小文件的寫操做..則會影響性能.

  • Copy-on-write 性能影響

容器中第一次更新一個已有數據時,就會進行cow操做,若是更新大文件的某一部分,則只會copy相應的數據快,這個性能提高很大. 若是更新大量小文件(<=64k),devicemapper的性能就比AUFS差.

  • 其餘

    • loop-lvm模式的性能不好,不推薦使用在生產環境.生產環境使用direct-lvm模式,它是直接操做raw設備.
    • 使用ssd的話提高更明顯
    • devicemapper內存使用不是最有效的.運行n個容器會加載n次相同文件到內存.因此不是運行pass平臺和高密度容器最好的選擇.
  • 固然容器中寫操做多的話要儘可能使用data volume,它是繞過storage driver,性能有保證

//END

相關文章
相關標籤/搜索