Storage Driver查詢
可以使用docker info命令查看你的Docker使用的storage driver,信息如下:
[root@84 tmp]# docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 6
Server Version: 18.03.0-ce
Storage Driver: overlay2 #使用的storage driver
Backing Filesystem: xfs
Storage對比
可以看到的本機上使用的storage driver
是overlay2
。此外美尸,還有一個Backing Filesystem
它只你本機的文件系統(tǒng)婉烟,我的是extfs
圆米,aufs
是在xfs
之上創(chuàng)建的谐檀。你能夠使用的storage driver
是與你主機上的Backing Filesystem
有關(guān)的环鲤。
Storage driver | 后端文件系統(tǒng) | 不支持的后端文件系統(tǒng) |
---|---|---|
overlay | ext4 xfs | btrfs aufs overlay zfs eCryptfs |
overlay2 | ext4 xfs | btrfs aufs overlay zfs eCryptfs |
aufs | ext4 xfs | btrfs aufs eCryptfs |
btrfs | btrfs only | N/A |
devicemapper | direct-lvm | N/A |
vfs | debugging only | N/A |
zfs | zfs only | N/A |
你可以通過在docker daemon
命令中添加--storage-driver=<name>
標(biāo)識來指定要使用的storage driver
喝检,或者在/etc/default/docker
文件中通過DOCKER_OPTS
指定嗅辣。
選擇的storage driver
對容器中的應(yīng)用是有影響的。
Storage Driver 詳解
AUFS
AUFS是Docker最先使用的storage driver挠说,它技術(shù)很成熟澡谭,社區(qū)支持也很好,它的特性使得它成為storage driver的一個好選擇损俭,使用它作為storage driver蛙奖,Docker會:
- 容器啟動速度很快
- 存儲空間利用很高效
- 內(nèi)存的利用很高效
盡管如此,仍有一些Linux發(fā)行版不支持AUFS杆兵,主要是它沒有被并入Linux內(nèi)核雁仲。
AUFS是一種聯(lián)合文件系統(tǒng),意思是它將同一個主機下的不同目錄堆疊起來(類似于棧)成為一個整體琐脏,對外提供統(tǒng)一的視圖攒砖。AUFS是用聯(lián)合掛載來做到這一點。
AUFS使用單一掛載點將多個目錄掛載到一起日裙,組成一個棧吹艇,對外提供統(tǒng)一的視圖,棧中的每個目錄作為一個分支阅签。棧中的每個目錄包括聯(lián)合掛載點都必須在同一個主機上掐暮。
在Docker中,AUFS實現(xiàn)了鏡像的分層政钟。AUFS中的分支對應(yīng)鏡像中的層路克。
此外樟结,容器啟動時創(chuàng)建的讀寫層也作為AUFS的一個分支掛載在聯(lián)合掛載點上。
AUFS通過寫時復(fù)制策略來實現(xiàn)鏡像鏡像的共享和最小化磁盤開銷精算。AUFS工作在文件的層次上瓢宦,也就是說AUFS對文件的操作需要將整個文件復(fù)制到讀寫層內(nèi),哪怕只是文件的一小部分被改變灰羽,也需要復(fù)制整個文件驮履。這在一定成度上會影響容器的性能,尤其是當(dāng)要復(fù)制的文件很大廉嚼,文件在棧的下面幾層或文件在目錄中很深的位置時玫镐,對性能的影響會很顯著。
例如:當(dāng)要在一個包含很長字符串的文件中追加一個字符串時怠噪,如果這是對這個文件的第一次修改操作恐似,意味著它當(dāng)前不在最頂層的讀寫層。AUFS就會在下面額讀寫層中查找它傍念,查找是自頂向下矫夷,逐層查找的。找到之后憋槐,就把整個文件拷貝到讀寫層双藕,再對它進行修改。文件比較大時阳仔,復(fù)制操作就會很耗時間忧陪。當(dāng)文件在最下面幾層時,查找它的時間開銷也比較大近范。
幸運的是赤嚼,一個文件只需復(fù)制一次,此后對它的操作就在讀寫層進行了顺又。
AUFS在性能方面的特性可以總結(jié)如下:
- 在容器密度比較告的場景下更卒,AUFS是非常好的選擇,因為AUFS的容器間共享鏡像層的特性使其磁盤利用率很高稚照,容器的啟動時間很短蹂空;
- AUFS中容器之間的共享使對系統(tǒng)頁緩存的利用率很高;
- AUFS的寫時復(fù)制策略會帶來很高的性能開銷果录,因為AUFS對文件的第一次更改需要將整個文件復(fù)制帶讀寫層上枕,當(dāng)容器層數(shù)很多或文件所在目錄很深時尤其明顯;
最后弱恒,需要說明的是辨萍,數(shù)據(jù)卷(data volumes)可以帶來很好的性能表現(xiàn),這是因為它繞過storage driver直接將文件卸載宿主機上,不需要使用寫時復(fù)制策略锈玉。正因如此爪飘,當(dāng)需要大量的文件寫操作時最好使用數(shù)據(jù)卷。
Device mapper 詳解
Docker
在Debian拉背,Ubuntu系的系統(tǒng)中默認(rèn)使用aufs师崎,在RedHat系中使用device mapper。device mapper在Linux2.6內(nèi)核中被并入內(nèi)核椅棺,它很穩(wěn)定犁罩,也有很好的社區(qū)支持。
device mapper
將所有的鏡像和容器存儲在它自己的虛擬設(shè)備上两疚,這些虛擬設(shè)備是一些支持寫時復(fù)制策略的快照設(shè)備床估。device mapper工作在塊層次上而不是文件層次上,這意味著它的寫時復(fù)制策略不需要拷貝整個文件诱渤。
device mapper創(chuàng)建鏡像的過程如下:
- 使用device mapper的storge driver創(chuàng)建一個精簡配置池顷窒;精簡配置池由塊設(shè)備或稀疏文件創(chuàng)建。
- 接下來創(chuàng)建一個基礎(chǔ)設(shè)備源哩;
- 每個鏡像和鏡像層都是基礎(chǔ)設(shè)備的快照;這寫快照支持寫時復(fù)制策略鸦做,這意味著它們起始都是空的励烦,當(dāng)有數(shù)據(jù)寫入時才耗費空間。
在device mapper作為storage driver的系統(tǒng)中泼诱,容器層container layer
是它依賴的鏡像的快照坛掠。與鏡像一樣,container layer也支持寫時復(fù)制策略治筒,它保存了所有對容器的更改屉栓。當(dāng)有數(shù)據(jù)需要寫入時,device mapper就為它們在資源池中分配空間耸袜;
下圖展示了資源池友多,基礎(chǔ)設(shè)備和兩個鏡像之間的關(guān)系
device mapper中的讀操作
下圖展示了容器中的某個進程讀取塊號為0x44f的數(shù)據(jù):
- 某個進程發(fā)出讀取文件的請求;由于容器只是鏡像的精簡快照(thin snapshot)堤框,它并沒有這個文件域滥。但它有指向這個文件在下面層中存儲位置的指針。
- device mapper由指針找到在鏡像層號為a005e中的塊號為0xf33的數(shù)據(jù)蜈抓;
- device mapper將這個位置的文件復(fù)制到容器的存儲區(qū)內(nèi)启绰;
- device mapper將數(shù)據(jù)返回給應(yīng)用進程;
device mapper中的寫操作
在device mapper中沟使,對容器的寫操作由“需要時分配”策略完成委可。更新已有數(shù)據(jù)由“寫時復(fù)制”策略完成,這些操作都在塊的層次上完成腊嗡,每個塊的大小為64KB。
向容器寫入56KB的新數(shù)據(jù)的步驟如下:
- 進程向容器發(fā)出寫56KB數(shù)據(jù)的請求秒紧;
- device mapper的“需要時分配”策略分配一個64KB的塊給容器快照(container snapshot)荡陷;如果要寫入的數(shù)據(jù)大于64KB,就分配多個大小為64KB的塊微宝。
- 將數(shù)據(jù)寫入新分配的塊中;
device mapper在Docker中的性能表現(xiàn)
device mapper的性能主要受“需要時分配”策略和“寫時復(fù)制”策略影響虎眨,下面分別介紹:
需要時分配(allocate-on-demand)
device mapperdriver通過allocate-on-demand策略為需要寫入的數(shù)據(jù)分配數(shù)據(jù)塊蟋软。也就是說,每當(dāng)容器中的進程需要向容器寫入數(shù)據(jù)時嗽桩,device mapper就從資源池中分配一些數(shù)據(jù)塊并將其映射到容器岳守。
當(dāng)容器頻繁進行小數(shù)據(jù)的寫操作時,這種機制非常影響影響性能碌冶。
一旦數(shù)據(jù)塊被分配給了容器湿痢,對它進行的讀寫操作都直接對塊進行操作了。
寫時復(fù)制(copy-on-write)
與aufs一樣扑庞,device mapper也支持寫時復(fù)制策略譬重。容器中第一次更新某個文件時,device mapper調(diào)用寫時復(fù)制策略罐氨,將數(shù)據(jù)塊從鏡像快照中復(fù)制到容器快照中臀规。
device mapper的寫時復(fù)制策略以64KB作為粒度,意味著無論是對32KB的文件還是對1GB大小的文件的修改都僅復(fù)制64KB大小的文件栅隐。這相對于在文件層面進行的讀操作具有很明顯的性能優(yōu)勢塔嬉。
但是,如果容器頻繁對小于64KB的文件進行改寫租悄,device mapper的性能是低于aufs的谨究。
存儲空間使用效率
device mapper不是最有效使用存儲空間的storage driver,啟動n個相同的容器就復(fù)制了n份文件在內(nèi)存中泣棋,這對內(nèi)存的影響很大胶哲。所以device mapper并不適合容器密度高的場景。
overlayfs
OverlayFS
與AUFS相似潭辈,也是一種聯(lián)合文件系統(tǒng)(union filesystem)纪吮,與AUFS相比,OverlayFS:
- 設(shè)計更簡單萎胰;
- 被加入Linux3.18版本內(nèi)核
- 可能更快
overlayfs在Docker社區(qū)中獲得了很高的人氣碾盟,被認(rèn)為比AUFS具有很多優(yōu)勢。但它還很年輕技竟,在成產(chǎn)環(huán)境中使用要謹(jǐn)慎冰肴。
overlayfs中鏡像的分層和共享
OverlayFS將一個Linux主機中的兩個目錄組合起來,一個在上,一個在下熙尉,對外提供統(tǒng)一的視圖联逻。這兩個目錄就是層layer
,將兩個層組合在一起的技術(shù)被成為聯(lián)合掛載union mount
检痰。在OverlayFS中包归,上層的目錄被稱作upperdir
,下層的铅歼,目錄被稱作lowerdir
公壤,對外提
供的統(tǒng)一視圖被稱作merged
。
下圖展示了容器和鏡像的層與OverlayFS的upperdir
椎椰,lowerdir
以及merged
之間的對應(yīng)關(guān)系(圖來自Docker官網(wǎng)Docker docs):
由上圖可以看出厦幅,在一個容器中,容器層container layer也就是讀寫層對應(yīng)與OverlayFS的upperdir慨飘,容器使用的對象對應(yīng)于OverlayFS的lowerdir确憨,容器文件系統(tǒng)的掛載點對應(yīng)merged。
注意到瓤的,鏡像層和容器曾可以有相同的文件休弃,這中情況下,upperdir中的文件覆蓋lowerdir中的文件圈膏。
OverlayFS僅有兩層塔猾,也就是說鏡像中的每一層并不對應(yīng)OverlayFS中的層,而是本辐,鏡像中的每一層對應(yīng)/var/lib/docker/overlay中的一個文件夾,文件夾以該層的UUID命名医增。然后使用硬連接將下面層的文件引用到上層慎皱。這在一定程度上節(jié)省了磁盤空間。這樣叶骨,OverlayFS中的lowerdir就對應(yīng)鏡像層的最上層茫多,并且是只讀的。在創(chuàng)建鏡像時忽刽,Docker會新建一個文件夾作為OverlayFS的upperdir天揖,它是可寫的。
overlayfs中鏡像和容器的結(jié)構(gòu)
執(zhí)行docker images -a查看ubuntu鏡像都由哪些層組成:
$ docker images -a
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest 1d073211c498 7 days ago 187.9 MB
<none> <none> 5a4526e952f0 7 days ago 187.9 MB
<none> <none> 99fcaefe76ef 7 days ago 187.9 MB
<none> <none> c63fb41c2213 7 days ago 187.7 MB
然后查看/var/lib/docker/overlay下的文件夾:
$ ls -l /var/lib/docker/overlay/
total 24
drwx------ 3 root root 4096 Oct 28 11:02 1d073211c498fd5022699b46a936b4e4bdacb04f637ad64d3475f558783f5c3e
drwx------ 3 root root 4096 Oct 28 11:02 5a4526e952f0aa24f3fcc1b6971f7744eb5465d572a48d47c492cb6bbf9cbcda
drwx------ 5 root root 4096 Oct 28 11:06 99fcaefe76ef1aa4077b90a413af57fd17d19dce4e50d7964a273aae67055235
drwx------ 3 root root 4096 Oct 28 11:01 c63fb41c2213f511f12f294dd729b9903a64d88f098c20d2350905ac1fdbcbba
可以看出跪帝,鏡像中的每一層在/var/lib/docker/overlay文件夾下都有一個文件夾和它對應(yīng)今膊,文件夾以鏡像層的UUID命名。文件夾存儲了本層獨有的文件和指向它下面各層文件的硬連接伞剑。
使用docker ps命令查看當(dāng)前正在運行的容器的ID:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
73de7176c223 ubuntu "bash" 2 days ago Up 2 days stupefied_nobel
這個容器的數(shù)據(jù)存儲在/var/lib/docker/overlay/73de7176c223...文件夾下斑唬,文件夾以容器的ID命名。執(zhí)行l(wèi)s -a命令查看具體文件:
$ ls -l /var/lib/docker/overlay/73de7176c223a6c82fd46c48c5f152f2c8a7e49ecb795a7197c3bb795c4d879e
total 16
-rw-r--r-- 1 root root 64 Oct 28 11:06 lower-id
drwxr-xr-x 1 root root 4096 Oct 28 11:06 merged
drwxr-xr-x 4 root root 4096 Oct 28 11:06 upper
drwx------ 3 root root 4096 Oct 28 11:06 work
這就是OverlayFS的核心內(nèi)容了。lower-id文件保存了當(dāng)前容器依賴鏡像的最上層的UUID恕刘,并將其作為lowerdir缤谎;upper文件夾就是容器的讀寫層read-write layer,對容器的所有修改都保存在這個文件夾里褐着;merged文件夾就是容器文件系統(tǒng)的掛載點坷澡,容器通過它提供統(tǒng)一的視角。對容器的任何修改都會立即在這個文件夾里得到反應(yīng)含蓉;work文件夾需要OverlayFS來發(fā)揮作用频敛,它用來支持像copy-up這樣的操作。
overlayfs中容器的讀寫操作
讀文件:
- 要讀的文件不在container layer中:那就從lowerdir中讀谴餐,會耗費一點性能姻政;
- 要讀的文件之存在于container layer中:直接從upperdir中讀;
- 要讀的文件在container layer和image layer中都存在:從upperdir中讀文件岂嗓;
修改文件
- 第一次修改一個文件的內(nèi)容:第一次修改時汁展,文件不在container layer(upperdir)中,overlay driver調(diào)用copy-up操作將文件從lowerdir讀到upperdir中厌殉,然后對文件的副本做出修改食绿。
需要說明的是,overlay的copy-up操作工作在文件層面公罕,不是塊層面器紧,這意味著對文件的修改需要將整個文件拷貝到upperdir中。索性下面兩個事實使這一操作的開銷很新ゾ臁: - copy-up操作僅發(fā)生在文件第一次被修改時铲汪,此后對文件的讀寫都直接在upperdir中進行;
- overlayfs中僅有兩層罐柳,這使得文件的查找效率很高(相對于aufs)掌腰。
- 刪除文件和目錄:
- 刪除文件:文件被刪除時,和aufs一樣张吉,相應(yīng)的whiteout文件被創(chuàng)建在upperdir齿梁。并不刪除容器層(lowerdir)中的文件,whiteout文件屏蔽了它的存在肮蛹。
- 刪除文件夾:刪除一個文件夾時勺择,一個“遮擋目錄”(opaque dir)被創(chuàng)建在upperdir中,它的作用與whitout文件一樣伦忠,屏蔽了lowerdir中文件夾的存在省核。
在Docker中使用overlayfs
OverlayFS在Linux3.18版本中被并入內(nèi)核,所以要使用overlayfs昆码,請確保你的系統(tǒng)的內(nèi)核版本大于等于3.18芳撒。overlayfs可以工作在各種Linux文件系統(tǒng)上邓深,但目前比較推薦extfs。
在進行下列操作之前笔刹,如果你本機上有需要保存的鏡像芥备,使用docker push將它們保存到Docker Hub或其他的鏡像庫當(dāng)中。
下面是在Docker中使用overlayfs的步驟:
- 如果docker daemon正在運行舌菜,停止它萌壳;
- 檢查你的內(nèi)核版本和overlay模塊的按裝情況:
$ uname -r
3.19.0-21-generic
$ lsmod | grep overlay
overlay
使用overlaystorage driver啟動docker daemon:
$ docker daemon --storage-driver=overlay &
此外,你可以在/etc/default/docker文件中通過配置DOCKER_OPTS使overlay作為Docker的默認(rèn)storage driver日月。
overlayfs在Docker中的性能表現(xiàn)
總體上袱瓮,overlay要比aufs和device mapper快一點,在某些場景下甚至比btrfs快爱咬。下面是對overlay性能影響較大的幾個方面:
- 頁緩存(page caching):overlayfs支持頁緩存的共享尺借,這意味著多個使用同一文件的容器可以共享同一頁緩存,這使得overlayfs具有很高的內(nèi)存使用效率精拟;
- copy-up操作:overlay的拷貝操作工作在文件層面上燎斩,也就是對文件的第一次修改需要復(fù)制整個文件,這回帶來一些性能開銷蜂绎,在修改大文件時尤其明顯栅表。
但overlay的拷貝操作比aufs還是快一點,因為aufs有很多層师枣,而overlay只有兩層怪瓶,所以overlay在文件的搜索方面相對于aufs具有優(yōu)勢。 - i節(jié)點限制:使用overlay作為storage driver會消耗大量的i節(jié)點践美,隨著鏡像和容器數(shù)量的增長這種消耗尤其顯著洗贰,這在一定程度上限制了overlay的使用。