AUFS是docker最早支持的存儲引擎。AUFS是一種Union File System,是文件級的存儲驅動,是Docker早期用的存儲驅動,是Docker18.06版本之前,Ubuntu14.04版本前推薦的,支持xfs、ext4文件。
本教程操作環境:linux7.3系統、docker20版、Dell G3電腦。
AUFS是docker最早支持的存儲引擎。
Docker 的存儲引擎
Docker 的存儲引擎設計思路是這樣,但是針對不同的文件系統,是由不同的存儲驅動去實現的。下面我們來聊聊 Docker 的存儲驅動。
Docker 主要有一下幾類存儲驅動:
-
overlay2:是當前版本推薦的存儲驅動,無需額外的依賴和配置即可發揮絕佳的性能。在 18.09 版本之后替換了 overlay 存儲驅動。支持 xfs,ext4 文件系統。
-
aufs:Docker 最早期使用的存儲驅動,是 Docker 18.06 版本之前,Ubuntu 14.04 版本前推薦的。支持 xfs,ext4 文件系統。
-
devicemapper:是較早版本的 CentOS 和 RHEL 系統推薦的存儲驅動,因為它們不支持 overlay2,需要 direct-lvm 的支持。
-
btrfs:僅用于 btrfs 文件系統。
-
zfs:僅用于 zfs 文件系統。
-
vfs:不依賴于文件系統,但是性能奇差,主要用來測試。
需要注意的是,overlay2,overlay,aufs 的層是基于文件的,當單文件的寫并發較高時需要大內存的支持,且讀寫層可能因為單個文件而變得很大。devicemapper,btrfs,zfs 的層是基于塊存儲的,因此對于單個文件的高并發影響不大。但是 btrfs 和 zfs 非常消耗內存。
docker AUFS
AUFS是一種Union File System,所謂UnionFS就是把不同物理位置的目錄合并mount到同一個目錄中。UnionFS的一個最主要的應用是,把一張CD/DVD和一個硬盤目錄給聯合 mount在一起,然后,你就可以對這個只讀的CD/DVD上的文件進行修改(當然,修改的文件存于硬盤上的目錄里)。
AUFS又叫Another UnionFS,后來叫Alternative UnionFS,后來可能覺得不夠霸氣,叫成Advance UnionFS。是個叫Junjiro Okajima(岡島順治郎)在2006年開發的,AUFS完全重寫了早期的UnionFS 1.x,其主要目的是為了可靠性和性能,并且引入了一些新的功能,比如可寫分支的負載均衡。AUFS在使用上全兼容UnionFS,而且比之前的UnionFS在穩定性和性能上都要好很多,后來的UnionFS 2.x開始抄AUFS中的功能。但是他居然沒有進到Linux主干里,就是因為Linus不讓,基本上是因為代碼量比較多,而且寫得爛(相對于只有3000行的union mount和10000行的UnionFS,以及其它平均下來只有6000行代碼左右的VFS,AUFS居然有30000行代碼),所以,岡島不斷地改進代碼質量,不斷地提交,不斷地被Linus拒掉,所以,到今天AUFS都還進不了Linux主干(今天你可以看到AUFS的代碼其實還好了,比起OpenSSL好N倍,要么就是Linus對代碼的質量要求非常高,要么就是Linus就是不喜歡AUFS)。
不過,好在有很多發行版都用了AUFS,比如:Ubuntu 10.04,Debian6.0, Gentoo Live CD支持AUFS,所以,也OK了。
好了,扯完這些閑話,我們還是看一個示例吧(環境:Ubuntu 14.04)
首先,我們建上兩個目錄(水果和蔬菜),并在這兩個目錄中放上一些文件,水果中有蘋果和蕃茄,蔬菜有胡蘿卜和蕃茄。
$?tree . ├──?fruits │???├──?apple │???└──?tomato └──?vegetables ????├──?carrots ????└──?tomato
然后,我們輸入以下命令:
#?創建一個mount目錄 $?mkdir?mnt #?把水果目錄和蔬菜目錄union?mount到?./mnt目錄中 $?sudo?mount?-t?aufs?-o?dirs=./fruits:./vegetables?none?./mnt #??查看./mnt目錄 $?tree?./mnt ./mnt ├──?apple ├──?carrots └──?tomato
我們可以看到在./mnt目錄下有三個文件,蘋果apple、胡蘿卜carrots和蕃茄tomato。水果和蔬菜的目錄被union到了./mnt目錄下了。
我們來修改一下其中的文件內容:
$?echo?mnt?>?./mnt/apple $?cat?./mnt/apple mnt $?cat?./fruits/apple mnt
上面的示例,我們可以看到./mnt/apple的內容改了,./fruits/apple的內容也改了。
$?echo?mnt_carrots?>?./mnt/carrots $?cat?./vegetables/carrots? $?cat?./fruits/carrots mnt_carrots
上面的示例,我們可以看到,我們修改了./mnt/carrots的文件內容,./vegetables/carrots并沒有變化,反而是./fruits/carrots的目錄中出現了carrots文件,其內容是我們在./mnt/carrots里的內容。
也就是說,我們在mount aufs命令中,我們沒有指它vegetables和fruits的目錄權限,默認上來說,命令行上第一個(最左邊)的目錄是可讀可寫的,后面的全都是只讀的。(一般來說,最前面的目錄應該是可寫的,而后面的都應該是只讀的)
所以,如果我們像下面這樣指定權限來mount aufs,你就會發現有不一樣的效果(記得先把上面./fruits/carrots的文件刪除了):
$?sudo?mount?-t?aufs?-o?dirs=./fruits=rw:./vegetables=rw?none?./mnt $?echo?"mnt_carrots"?>?./mnt/carrots? $?cat?./vegetables/carrots mnt_carrots $?cat?./fruits/carrots cat:?./fruits/carrots:?No?such?file?or?directory
現在,在這情況下,如果我們要修改./mnt/tomato這個文件,那么究竟是哪個文件會被改寫?
$?echo?"mnt_tomato"?>?./mnt/tomato? $?cat?./fruits/tomato mnt_tomato $?cat?./vegetables/tomato I?am?a?vegetable
可見,如果有重復的文件名,在mount命令行上,越往前的就優先級越高。
你可以用這個例子做一些各種各樣的試驗,我這里主要是給大家一個感性認識,就不展開試驗下去了。
那么,這種UnionFS有什么用?
歷史上,有一個叫Knoppix的Linux發行版,其主要用于Linux演示、光盤教學、系統急救,以及商業產品的演示,不需要硬盤安裝,直接把CD/DVD上的image運行在一個可寫的存儲設備上(比如一個U盤上),其實,也就是把CD/DVD這個文件系統和USB這個可寫的系統給聯合mount起來,這樣你對CD/DVD上的image做的任何改動都會在被應用在U盤上,于是乎,你可以對CD/DVD上的內容進行任意的修改,因為改動都在U盤上,所以你改不壞原來的東西。
我們可以再發揮一下想像力,你也可以把一個目錄,比如你的源代碼,作為一個只讀的template,和另一個你的working directory給union在一起,然后你就可以做各種修改而不用害怕會把源代碼改壞了。有點像一個ad hoc snapshot。
Docker把UnionFS的想像力發揮到了容器的鏡像。你是否還記得我在介紹Linux Namespace上篇中用mount namespace和chroot山寨了一鏡像。現在當你看過了這個UnionFS的技術后,你是不是就明白了,你完全可以用UnionFS這樣的技術做出分層的鏡像來。
下圖來自Docker的官方文檔Layer,其很好的展示了Docker用UnionFS搭建的分層鏡像。
關于docker的分層鏡像,除了aufs,docker還支持btrfs, devicemapper和vfs,你可以使用 -s 或 storage-driver= 選項來指定相關的鏡像存儲。在Ubuntu 14.04下,docker默認Ubuntu的 aufs(在CentOS7下,用的是devicemapper,關于devicemapper,我會以以后的文章中講解)你可以在下面的目錄中查看相關的每個層的鏡像:
/var/lib/docker/aufs/diff/<id></id>
AUFS的一些特性
AUFS有所有Union FS的特性,把多個目錄,合并成同一個目錄,并可以為每個需要合并的目錄指定相應的權限,實時的添加、刪除、修改已經被mount好的目錄。而且,他還能在多個可寫的branch/dir間進行負載均衡。
上面的例子,我們已經看到AUFS的mount的示例了。下面我們來看一看被union的目錄(分支)的相關權限:
-
rw表示可寫可讀read-write。
-
ro表示read-only,如果你不指權限,那么除了第一個外ro是默認值,對于ro分支,其永遠不會收到寫操作,也不會收到查找whiteout的操作。
-
rr表示real-read-only,與read-only不同的是,rr標記的是天生就是只讀的分支,這樣,AUFS可以提高性能,比如不再設置inotify來檢查文件變動通知。
推薦學習:《docker視頻教程》