轉載於博客園:http://www.cnblogs.com/Andrew-XinFei/p/6245330.html
前言
Docker現在在后端是那么的火熱..尤其當筆者了解了docker是什么、能做什么之后,真的是感覺特別的exciting,便迫不及待的去實踐部署一下. 但是在實際部署中,因為筆者使用的是阿里雲ecs服務器,centos7系統,因為centos7與ubuntu的差異性,所以,需要自己把后端存儲引擎devicemapper從loop_lvm模式配置為direct_lvm模式。在這其中又遇到了坑,所以覺得很有必要記錄下來,做個備忘.
為什么要配置devicemapper
幾點原因:
ubuntu與contos的差異: 在Ubuntu/Debian上有UnionFS可以使用,如aufs或者overlay2,而CentOS和RHEL的內核中沒有相關驅動。
Docker的背景: Docker最先就是跑在Ubuntu和Debian上的,使用的就是aufs存儲器.因為docker越來越流行,許多公司希望在rhel上使用,但是上游內核中並沒有包括aufs,所以rhel不能使用aufs. 最終,開發者們開發了一個新的后端存儲引擎devicemapper,基於已有的Device Mapper技術,並且使docker 支持可插拔,現在全世界有很多真實案例在生產環境中使用devicemapper.
loop_lvm和direct_lvm區別:
因為上述的原因,對於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 中存在被 backports 回來的 overlay
驅動,不過 CentOS 里的這個驅動達不到生產環境使用的穩定程度,所以不推薦使用。
(參考自:Docker--從入門到實踐)
安裝及運行docker
比較easy,自己參考Docker--從入門到實踐,在其中講的有具體步驟,很詳細了。本文的重點是direct_lvm模式的配置,這里就不再細說。
為生產環境配置direct_lvm模式
生產環境下應該使用direct_lvm,如果之前有鏡像在loop_lvm模式下創建,需要切換,則需要把鏡像做備份(push到hub或者私有registry).所以最好的做法,還是: 在剛剛給centos服務器安裝docker的時候,直接做好配置.
1.停止docker daemon
[root@srv00 ~]# systemctl stop docker
2.創建相關的邏輯卷和thinpool
檢查磁盤
[root@iZ28uvczcf6Z mapper]# fdisk -l <==檢查下磁盤
Disk /dev/xvda: 107.4 GB, 107374182400 bytes, 209715200 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
Disk label type: dos
Disk identifier: 0x635e6c7d
Device Boot Start End Blocks Id System
/dev/xvda1 * 2048 209713151 104855552 8e Linux LVM
Disk /dev/xvdb: 21.5 GB, 21474836480 bytes, 41943040 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
Disk label type: dos
Disk identifier: 0x021dd279
Device Boot Start End Blocks Id System
/dev/xvdb1 2048 41943039 20970496 8e Linux LVM
創建pv
[root@srv00 ~]# pvcreate /dev/xvdb1
Physical volume "/dev/xvdb" successfully created
注意: pvcreate 指令后面配置的硬盤(此處為"xvdb1")必須為獨立的掛載硬盤,而不能是系統盤,否則會報錯,創建失敗.
(關於掛載新硬盤后,如何對硬盤進行"初始化"、"分區" ,在本文最后會單獨講解。(比如在本代碼中,把Disk "/dev/xvdb"初始化成一塊分區 "/dev/xvdb1",大小等同於磁盤大小(約20G)。)
創建vg
[root@srv00 ~]# vgcreate vgdocker /dev/xvdb1
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存儲目錄(是否備份,根據自己需求)
備份
$ mkdir /var/lib/docker.bk
$ mv /var/lib/docker/* /var/lib/docker.bk
刪除原存儲目錄
[root@srv00 ~]# rm -rf /var/lib/docker/*
"注意備份重要鏡像等"
4.修改啟動參數並啟動
我們通過systemd的drop-in方式修改,也是官方推薦的
編輯config文件
[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/dockerd
"ExecStart=
第一行是空.否則啟動會報錯; "
實際啟動時,是需要一些參數的,我們把它配置在daemon.json文件中。文件的位置是/etc/docker/daemon.json 通過vi指令編輯、保存,即可. daemon.json文件內容如下:
{
"storage-driver": "devicemapper",
"storage-opts": [
"dm.thinpooldev=/dev/mapper/vgdocker-thinpool",
"dm.use_deferred_removal=true",
"dm.use_deferred_deletion=true"
]
}
重新reload
[root@srv00 ~]# systemctl daemon-reload
[root@srv00 ~]# systemctl start docker
"修改daemon參數需要reload"
5.檢查確認
可以看到,direct_lvm模式已經配置成功.
注: 因為筆者機器已經配置完畢,無法重新配置前面的步驟,所以前面的一些代碼,均是從一篇他人的博客(點擊訪問)中粘貼過來的,並進行了一些整理。 不過差別只是硬盤名稱不一樣,流程和輸入指令完全可以直接照搬.
[root@iZ28uvczcf6Z mapper]# docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 1
Server Version: 1.12.5
Storage Driver: devicemapper
Pool Name: vgdocker-thinpool
Pool Blocksize: 524.3 kB
Base Device Size: 10.74 GB
Backing Filesystem: xfs
Data file:
Metadata file:
Data Space Used: 990.4 MB
Data Space Total: 20.4 GB
Data Space Available: 19.41 GB
Metadata Space Used: 233.5 kB
Metadata Space Total: 213.9 MB
Metadata Space Available: 213.7 MB
Thin Pool Minimum Free Space: 2.039 GB
Udev Sync Supported: true
Deferred Removal Enabled: true
Deferred Deletion Enabled: true
Deferred Deleted Device Count: 0
Library Version: 1.02.135-RHEL7 (2016-09-28)
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: null host bridge overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Security Options: seccomp
Kernel Version: 3.10.0-514.2.2.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 991.2 MiB
Name: iZ28uvczcf6Z
ID: KJ44:XNL6:W5KM:VYDQ:WN4C:FDPF:U52P:27SJ:MCWA:Q6JA:D76Z:JXVC
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
WARNING: bridge-nf-call-iptables is disabled
Insecure Registries:
127.0.0.0/8
[root@iZ28uvczcf6Z mapper]#
有哪些坑?
硬盤掛載
一定不能是系統盤
"Docker 1.12 on CentOS no longer uses socket activation"
因為Docker 1.12的一些新變化,基於網上的一些博客、文章,在配置時,就要有一些改變,否則你可能會遇到錯誤:"no sockets found via socket activation: make sure the service was started by systemd"。這個錯誤的解決方式,感興趣的可以自行查看此鏈接: "docker daemon -H fd://" fails with message "No sockets found" under Ubuntu 15.10 #22847
掛載硬盤的初始化和分區方式
$ fdisk /dev/xvdb
Command(m for help): n n之后,根據自己需要配置,也可以連着3次enter就可以完成配置,初始化為一塊分區,分區大小=硬盤大小
Command (m for help): t t是個改類型的指令
Partition number (1-3,default 3):
Partition type (type L to list all types): 8e 最好是給配置為支持LVM的8e類型
Command ( m for help): w 保存
partprobe 用partprobe可以使kernel重新讀取分區信息,從而避免重啟
//以下的指令非必須,僅做一個備錄
pvcreate /dev/sda3
vgextend vg00 /dev/sda3
vgdisplay
lvextend -L +80G /dev/vg00/lv_root
lvdisplay
resize2fs /dev/vg00/lv_root
df -h
后言
站在前人的肩膀上
筆者學習時也是參考了一些博客、文章, 在它們的基礎上,做了整理,並修改掉過時的配置信息. 其中一些筆者自己覺得說的挺清晰的,羅列在下面,方便參考:
Docker官方教程 : 官方教程,不用多說,只是英文閱讀起來費些力氣
Docker--從入門到實踐 :gitbook書籍,講的很詳細
以及幾篇不錯的文章:
http://www.linuxtechi.com/thin-provisioned-logical-volumes-centos-7-rhel-7/
一種簡單的方式,配置direct_lvm模式
本文主要講的是自己手動配置direct_lvm模式的方式,還有一種簡單些的配置方式.如 Docker Device Mapper 使用direct_lvm,文章提到了一個工具: docker-storage-setup,貌似基於這個腳本可以比較便捷的進行配置,但是感覺文中內容,筆者看的不是很明白,所以就沒有繼續了. docker-storage-setup的github網址,筆者也已經找到了:projectatomic/docker-storage-setup 。如果你感興趣,研究有結果之后,歡迎回來在下方分享給筆者^_^。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利;