1. 程式人生 > >理解docker映象,容器和儲存驅動

理解docker映象,容器和儲存驅動

理解docker映象,容器和儲存驅動

201695

14:40

映象

映象作為docker中最基本的概念,有以下幾個特性:

  1. 分層,每個映象都由一個或多個映象層組成
  2. 可通過在某個映象加上一定的映象層得到新映象(此過程可通過編寫dockerfile或在容器中commit實現)
  3. 每個都分層擁有唯一ID
  4. 映象在儲存和使用時共享相同的映象層(根據ID),所以在pull映象時,已有的映象層會自動跳過下載
  5. 每個映象層都是隻讀,即使啟動成容器,也無法對其真正的修改,修改只會作用於最上層的容器層

映象 vs容器

  • 映象加上一層可讀寫層(容器層)組成該映象對應容器的檔案系統
  • 在容器中通過commit
    可將最上層的可寫層固化成映象層,形成新映象。此時,生成的新映象與舊映象共享底層映象層,所以在宿主機上只不過是多了個新的映象層

計算機生成了可選文字:Thin R/W layer 91e54dfb1179 d74508fb6632 c22013c84729 d3a1f33e8a5a ubuntu:15.04 Container 0B 1.895 KB 194.5 KB 188.1 MB Container layer Image layers (R/O)

.  Copy-On-Write,COW

寫時拷貝,多個程式共享同一份檔案,讀操作時對這份檔案無影響,當程式需要進行寫操作時才把要寫的部分拷貝一份給對應程式。COW只是一種策略,有多種方法去實現。根據這種思想可以大大減少儲存冗餘。docker實現了COW策略,所以容器會共享相同的映象層,如下圖(同一個映象啟動成多個容器時)

計算機生成了可選文字:„nury 91e54dfb1179 d74508fb6632 c22013c84729 d3a1f33e&5a _Ț)iT_ R/W_lęyęȚ_ OB 1.895 KB 194.5 KB 188.1 MB ubuntu:15.04 Image

生成新映象的方法有,從容器中commit,或者使用dockerfiledockerfile其實本質是也是啟動容器去commit

,只是這些操作都是docker自動化去完成。

dockerfile中每一個命令就對應生成一個映象,即每個命令對應一個映象層,如下圖

計算機生成了可選文字:[ root 訕 ogon 、 ] # docker history registry.wae.hap1at.net/base/centos:6 1M 厶 〔 乇 07d52ebb288d 叻 8e724c5def 4886b bbeb3 e8f7e3de7b63 曲 56620gggC9 Cd5474e548C8 65ffa2f5c6ea 604 ( 2d6e1a Oa83 b655ff If21ea712fae 53530 01d 10 /bin/sh -c #(nop) 00 ["/bin/bash"l 72703a052 7 Id 曲 f8fb53e6 /bin/sh -C #(nop) e78888 8cfa 6a7b54515 1 47d44Cb6f252 CÆATED 4 weeks 4 weeks 4 weeks 4 weeks 4 weeks 5 weeks 5 weeks 5 weeks 5 weeks 5 weeks 5 weeks ago ago ago ago ago ago ago ago ago ago ago 12 months ago 12 months ago 12 months ago 12 months ago 12 months ago CÆATED BY /bin/sh -c #(nop) ENTRYPOINT &{["exec"]} /bin/sh -c ( Od 0777 /us r/bin/exec /bin/sh -c #(nop) C 、 ' dir : a61bcde1fb7e3dc 17a /bin/sh -C #(nop) C 、 ' file : 4b2808 fd 傭 b7d /bin/sh -c m . rf /us r/local/bin/ repo rt /bin/sh -c cd /tmp curl -L . 0 -s http : /bin/sh -C #(nop) ENV PATH=/usr/IocaI/wsmsage /bin/sh -C #(nop) ENV WAE DOCKER ENV=true /bin/sh -C *(nop) ENV LANG=en_US.UTF-8 /bin/sh -c cp -f /usr/share/zoneinfo/Asia/Sha /bin/sh -c yum -Y update yum install LABEL License=æLv2 /bin/sh -C *(nop) LABEL Vendo r=CentOS /bin/sh -C #(nop) ADD file : 91f92b 62a2a 573 /bin/sh -C #(nop) MAINTAIr•ER The CentOS Proje SIZE 4g6 B 2 . 431 kB 4g6 8 0 8 & g38 0 B 0 8 427 8 288 彐 《 祀 0 8 19 飢 6 鋁 0 8

為什麼要這麼細粒度的劃分層是因為,細粒度的映象層被共用到的機率越大。舉個極端的例子,如果把基於一個ubuntu映象上所做的操作都歸到一層的話,那麼這一層共用到的機率幾乎為零,因為定製化程度太高,每個人所需的環境不同。

.  docker storage driver

docker將容器的一些底層執行環境進行抽象,從複雜的實現中分離出了driver元件,讓使用者得以專注於業務相關的容器使用。使用者可以通過選定不同的driver元件來對docker中容器大環境的定製,具體的實現操作則交由

driver去進行。

          driver分為三類:

  1. exec-driver,實現對容器執行環境的隔離和資源的限制,可選方案:lxcnative(libcontainer);
  2. network-driver,實現容器網路相關的操作;
  3. graph-driver,實現映象儲存相關操作,可選方案:devicemapper,aufs,btrfs,zfs等。

storage driverdocker中的一個元件,也稱graphdriver

功能:

  1. 映象的儲存管理,包括從hubpull的映象和通過dockerfile生成的新映象等;
  2. 容器啟動時,為容器準備檔案系統

對於graphdriver選擇何種方案去實現,並不影響docker功能方面的使用。每種方案都能實現映象的分層結構和COW策略,但不同的方案對於docker的儲存速度和穩定性是有影響的。目前相對比較成熟的有,aufsdevicemapperWAE使用中)

下圖為各個方案的特點:

計算機生成了可選文字:stable production-readv good memory use smooth Cacker experience high write activity PaaS-type work smooth exaer•ence container churn build pools oroduction oerformance lab testing PaaS-type work Devicemapper (direct-Ivm) in mainline kernel high write activity good memory use ZFS native (ZOL) In mal nline kernel container churn lab testing ZFS FUSE production

.  devicemapper

基於linux核心中的DeviceMapper框架實現,該框架實現了物理儲存裝置與虛擬儲存裝置的對映,或虛擬裝置與虛擬裝置之間的對映。這使得使用者能夠用該框架來實現磁碟的自由、動態的劃分。LVM2,software RAIDsdm-cryptdisk encryption等都是基於該框架的實現。更為重要的是,Device Mapper框架中提供兩個功能,thin-provisioningsnapshot

  thin-provisioning,類似於虛擬記憶體,提供給使用者的空間只有在使用者進行寫操作時才真正進行分配。假設使用者有一塊100gthin塊裝置,使用了20g,實際系統提供的大小就是20g,只有當使用者進行儲存操作時才分配更多的空間,直到100g

snapshot,快照,是一種COW策略的實現,假設從A裝置做快照得到B裝置時,並未對A進行完整拷貝,而是當對B裝置進行寫操作時,才將需要改變的那部分做屬於B裝置的拷貝。

         devicemapper利用了該框架中的thin-provisioningsnapshot實現了映象的分層結構和儲存優化。在用devicemapper作為graphdriverdocker中,每個映象和容器都對應一個裝置,通過對映象做snapshot操作得到容器,所以容器中擁有映象的內容且操作這些內容不影響映象本身,因為容器和映象對應不同的裝置。

       devicemapper有兩種模式可選,loop-lvmdirect-lvmdevicemapper的大致思路是,先通過虛擬化技術得到一個thin-pool裝置(可理解成一個資源池),接著在thin-pool上建立一個基礎裝置,此後docker上所有映象和容器都是基於此裝置的snapshot。兩個模式的區別就在與建立thin-pool的方法不同。

loop-lvm

  1. 建立兩個稀疏檔案datametadata
  2. 將這兩個檔案對映成兩個塊裝置(loopback塊裝置)
  3. 將兩個裝置通過核心中Device Mapper對映成thin-pool

注意!該模式不推薦用於生產環境,因為該模式在宿主機跑高密度容器數量的話,效能下降急劇,生產環境中一臺宿主機不可能只跑單個容器

direct-lvm

(利用了基於Device MapperLVM

  1. 將空餘塊裝置(可以是分割槽)建立成physical volumepv
  2. 在由這些PV組成volume groupvg
  3. vg中建立兩個logical volumelv),datamatedata
  4. datamatedata對映成thin-pool

*這些步驟可由已有指令碼docker-storage-setup自動執行,docker啟動前會自動執行該指令碼,指令碼位置/usr/bin/docker-storage-setup,只要在對應配置檔案中提供用於建立VGPV(對應配置檔案中DEVS),或者提供已有的VG,便可讓指令碼自動執行上述步驟。具體可通過service docker-storage-setup status檢視,對應執行指令碼內有使用說明。也可手動建立(Configure direct-lvm mode forproduction)

以下通過一些命令區別兩種模式:

loop-lvm:

docker詳情

計算機生成了可選文字:[root@wae-25 / docker info Containers: 36 Ima es: 117 orage Driver: devicanapper Pool Name: docker-8:3-1611g4g114-pool oc size: Backin Files stan: xfs Data file: /dev/loop€ Metadata file: /dev/loopl aa pace se . Data space Total: 1€7.4 6B Data Space Available: 161.7 6B Metadata Space Used: 16.6 MB Metadata Space Total: 2.147 6B Metadata Space Available: 2.137 6B Udev Sync Supported: true Deferred Ranoval Enabled: false ata loop file: /var/lib/docker/devicanapper/devicanapper/data etadata loop file: /var/lib/docker/devicanapper/devicanapper/metadata Execution Driver: native-€.2 Logging Driver: json-file Kernel version: 3.1€.€-327.e17.x86 64 Operating Systan: Centos Linux 7 (Core) CPUs: 24 Total Manory: 47 GiB Name: wae-25 ID: WARNING: bridge-nf-caU-ip6tab1es is disabled

列出塊裝置

計算機生成了可選文字:sda dal da3 sdb L_sdbl sdc L_sdcl loop€ Ldocker-8. docker- docker- docker- ocker- loopl Ldocker-8. ocker- docker- ocker- ocker- [root@wae-25 MAJ:MIN RN 8:32 € dm € dm € dm € dm € dm € dm € dm € dm € dm € dm Isblk •3-1611949114-pool 8: 3-1611949114-3b3gf8c96gef69466a6d6ad2b413ge1231a25eef167693529c9b8dc3c€48cb7€ •3-1611949114-pool 8:16 8:17 8:33 253:€ 253:3 253: 4 253:5 253: 6 253:€ 253:3 253: 4 253:5 253: 6 SIZE € 447. IG 200M 86 4396 € 931.56 € 931.56 931.56 931.56 26 RO TYPE disk part part part disk part disk part loop loop MOUNTPOINT 'boot [SWAP] /cachel /cache2 8: 3-1611949114-3b3gf8c96gef69466a6d6ad2b413ge1231a25eef167693529c9b8dc3c€48cb7€

direct-lvm模式:

 docker詳情

計算機生成了可選文字:[root@bogon docker info Containers: 2 Images: 36 o rage river: evlcanapper Pool Name: docker-thin 001 Pool Blocksize: 524.3 kB Backin Files stan: xfs Data file: Data space Used: 1.713 6B Data space Total: 19.8 6B Data Space Available: 18.68 6B Metadata Space Used: 684 kB Metadata Space Total: 265.5 MB Metadata Space Available: 264.8 MB Udev Sync Supported: true Deferred Ranoval Enabled: true Library version: 1.€2.1€7-RHEL7 (2€16-@6-€9) Execution Driver: native-€.2 Logging Driver: json-file Kernel version: 3.1€.€-327.22.2.e17.x86 64 Operating Systan: Centos Linux 7 (Core) CPUs: 1 Total Manory: 977.9 MiB Name: bogon ID: WRUNG: bridge-nf-caU-iptables is disabled WRUNG: bridge-nf-caU-ip6tables is disabled

列出塊裝置

計算機生成了可選文字:[root@bogon Isblk MAJ:MIN RN sdal sda2 sda3 da4 da5 docker-8:2-6788wø€-f1a€4d3537edd5741f3gff262277362b35bbf17776fcafa31e67412f97e4d9fg 253:3 Ldocker-8:2-6788wø€-f1a€4d3537edd5741f3gff262277362b35bbf17776fcafa31e67412f97e4d9fg 253:3 253:€ 253:2 253:1 253:2 SIZE 500M 19.46 196M 18.46 18.4G 18.4G 4G RO TYPE disk part part part € part € part € dm € rom MOUNTPOINT /boot [SWAP] thin-provisioning, docker-thinpool tmeta Ldocker-thin 001 ocker- Inpoo Ldocker-thinpool

列出所有logical volume的資訊

計算機生成了可選文字:[root@bogon LSize Attr thinpool docker twi-aot--- 18.44g Pool Origin Data* 8.66 Meta* €.33 Move Log Cpy%Sync Convert

目錄相關

宿主機上容器、映象等儲存相關的主目錄:/var/lib/docker

[[email protected] docker]# tree ./

./

├── containers                              <---容器相關

│   ├──f1a04d3537edd5741f39ff262277362b35bbf17776fcafa31e67412f97e4d9f9

│   │   ├── config.json

│   │   ├──f1a04d3537edd5741f39ff262277362b35bbf17776fcafa31e67412f97e4d9f9-json.log

│   │   ├── hostconfig.json

│   │   ├── hostname

│   │   ├── hosts

│   │   ├── resolv.conf

│   │   ├── resolv.conf.hash

│   │   └── secrets

├── devicemapper                       <---儲存驅動相關

│   ├── metadata                          <---映象、容器對應塊裝置的元資料

│   │   ├──0288ae931294ce04f5d69c60146faca7d9be8de4004421d650f4227fa60bd92b

│   │   ├──05c2ea2d81bceeddc2881beb63d2ee26537593de9f47b4613c0d5afb1353f7df

│   │   ├──f1a04d3537edd5741f39ff262277362b35bbf17776fcafa31e67412f97e4d9f9

│   │   ├──f1a04d3537edd5741f39ff262277362b35bbf17776fcafa31e67412f97e4d9f9-init

│   │   ├──f6d195bba85ba6b9c075186ee62fe56f5d3b27e29ad9a31da8753820f3e2586b

│   │   ├──f6d195bba85ba6b9c075186ee62fe56f5d3b27e29ad9a31da8753820f3e2586b-init

│   │   ├── base

│   │   ├── deviceset-metadata

│   │   └── transaction-metadata

│   └── mnt                              <---容器對應裝置的掛載目錄,docker會自動mountumount,所以手動開啟為空,可自行mount,對應裝置在/dev/mapper/

│       ├──0288ae931294ce04f5d69c60146faca7d9be8de4004421d650f4227fa60bd92b

│       ├──05c2ea2d81bceeddc2881beb63d2ee26537593de9f47b4613c0d5afb1353f7df

├── graph                                 <---映象目錄,儲存映象層元資料

│   ├──0288ae931294ce04f5d69c60146faca7d9be8de4004421d650f4227fa60bd92b

│   │  ├── checksum                       <---映象校驗和,用於判斷映象是否損壞

│   │  ├── json                                   <---描述映象基礎資訊

│   │  ├── layersize                          <---映象層大小

│   │  └── tar-data.json.gz           <---描述映象層內檔案在磁碟中的位置

│   ├──05c2ea2d81bceeddc2881beb63d2ee26537593de9f47b4613c0d5afb1353f7df

│   │   ├── checksum

│   │   ├── json

│   │   ├── layersize

│   │   └── tar-data.json.gz

│   └── _tmp

├── linkgraph.db

├── repositories-devicemapper

├── tmp

├── trust

└── volumes