應用背景:
Docker最先就是跑在Ubuntu和Debian上的,使用的就是aufs存儲器.因為docker越來越流行,許多公司希望在rhel上使用,但是上游內核中並沒有包括aufs,所以rhel不能使用aufs. 最終,開發者們開發了一個新的后端存儲引擎devicemapper,基於已有的Device Mapper技術,並且使docker 支持可插拔,現在全世界有很多真實案例在生產環境中使用devicemapper.
因為上述的原因,對於centos/rhel這類沒有相關驅動的系統,一般使用devicemapper驅動利用LVM的一些機制來模擬分層存儲。這樣的做法除了性能比較差之外,穩定性一般也不好,而且配置相對復雜。Docker安裝在CentOS/RHEL 上后,會默認選擇 devicemapper,但是為了簡化配置,其 devicemapper 是跑在一個稀疏文件模擬的塊設備上,也被稱為 loop-lvm。這樣的選擇是因為不需要額外配置就可以運行 Docker,這是自動配置唯一能做到的事情。但是 loop-lvm 的做法非常不好,其穩定性、性能更差,無論是日志還是 docker info 中都會看到警告信息。官方文檔有明確的文章講解了如何配置塊設備給 devicemapper 驅動做存儲層的做法,這類做法也被稱為配置 direct-lvm。
除了前面說到的問題外,devicemapper + loop-lvm 還有一個缺陷,因為它是稀疏文件,所以它會不斷增長。用戶在使用過程中會注意到 /var/lib/docker/devicemapper/devicemapper/data 不斷增長,而且無法控制。很多人會希望刪除鏡像或者可以解決這個問題,結果發現效果並不明顯。原因就是這個稀疏文件的空間釋放后基本不進行垃圾回收的問題。因此往往會出現即使刪除了文件內容,空間卻無法回收,隨着使用這個稀疏文件一直在不斷增長。
所以,
對於 CentOS/RHEL 的用戶來說,在沒有辦法使用 UnionFS 的情況下,一定要配置 direct-lvm 給 devicemapper,無論是為了性能、穩定性還是空間利用率。
配置環境:
centos 7
docker 1.12
配置步驟:
1.停止 docker daemon(root)
#>
systemctl stop docker
2.創建相關邏輯卷以及 thinpool(root)
(1).分配磁盤
分配磁盤予服務器,利用 fdisk 進行分區。
(2).創建 PV
例如:已分配磁盤 /dev/sdb1
#>
pvcreate /dev/sdb1
(3).創建 VG
#>
vgcreate dockervg /dev/sdb1
(4).創建 thinpool 邏輯卷
#>
lvcreate --wipesignatures y -n thinpool -l 50%VG dockervg
lvcreate --wipesignatures y -n thinpoolmeta -l 1%VG dockervg
可通過如下命令檢驗
#> lvscan

(5).轉換成 thinpool
#> lvconvert -y --zero n -c 512K --thinpool dockervg/thinpool --poolmetadata dockervg/thinpoolmeta
輸出結果類似如下。

可以通過如下命令查看 thinpool 狀態
#>
lvs -o lv_name,data_percent,metadata_percent,lv_size,lv_metadata_size,data_lv,metadata_lv
輸出結果類似如下。

注意:其中
LSize 即為 Data 的空間大小,
Msize 即為 MetaData 的空間大小,
Data 為 Data 對應邏輯卷,
Meta 為 MetaData 對應邏輯卷。
(6).擴展 thinpool(選做)
該步驟選做,用於 MetaData 或 Data 空間不足時的擴容。
例如:MetaData 對應邏輯卷路徑為 /dev/mapper/dockervg-thinpool_tmeta,則擴容命令如下。
#>
lvresize -L +1G /dev/mapper/dockervg-thinpool_tmeta
例如:thinpool 整體對應邏輯卷路徑為 dockervg-thinpool,則擴容命令如下。
#>
lvresize -L +5G /dev/mapper/dockervg-thinpool
3.備份並刪除 Docker 存儲目錄(root)
(1).備份
#>
mkdir /var/lib/docker.bk
mv /var/lib/docker/* /var/lib/docker.bk
(2).刪除原存儲目錄
#>
rm -rf /var/lib/docker/*
4.修改 Docker 啟動參數並啟動(root)
修改 daemon.json 配置文件
#> vi /etc/docker/daemon.json
修改為如下內容。
{
"storage-driver": "devicemapper",
"storage-opts": [
"dm.thinpooldev=/dev/mapper/dockervg-thinpool",
"dm.use_deferred_removal=true",
"dm.use_deferred_deletion=true",
"dm.basesize=25G"
]
}
]
}
注意:dm.basesize 指定了 images 以及 container 可以擴展到的
最大空間。
5.重啟 Docker 服務(root)
#>
systemctl daemon-reload
systemctl start docker
6.驗證(root)
a.docker info 檢查#> docker info結果類似如下。
其中,方框內信息表明以使用了 direct_lvm 的 Docker 存儲模式,同時 images 以及 container 可以擴展到的 最大空間已修改所需大小。b.試運行 hello-world#> docker pull hello-worlddocker run hello-world結果類似如下,即表明運行正常。![]()
參考資料:
https://docs.docker.com/engine/userguide/storagedriver/device-mapper-driver/#configure-direct-lvm-mode-for-production