1. 程式人生 > >有容雲-【原理】Docker儲存驅動之AUFS

有容雲-【原理】Docker儲存驅動之AUFS

編者按:今天聊一聊Docker的Image(映象)與Container(容器)的儲存以及儲存驅動之AUFS。

Docker儲存驅動簡介

Docker內建多種儲存驅動,每種儲存驅動都是基於Linux檔案系統(Linux FS)或者卷管理(Volume Manager)技術。一般來說,Docker儲存驅動的名稱與檔案系統(儲存技術)同名,見下表對應關係:


AUFS簡介

AUFS,起初名為AnotherUnionFileSystem,是一種UnionFS,V2版本後更名為 advanced multi‐layered unification fileystem,即高階多層統一檔案系統。

AUFS是一位名為岡島純二郎的日本人於2006年基於UnionFS開發的,目的也是為了提高其可靠性和效能,也在AUFS上實現了一些新的概念比如寫分支平衡等(writeable branchbalancing)。

純二郎先生曾多次提交aufs到linux主幹,但一直被拒絕,可純二郎依舊日以繼夜的修改程式碼,並不斷提交,可一直沒有被merge,而純二郎最終也放棄提交程式碼到linux主幹,從而aufs也一直沒有進入linux核心。關於為何linux不要aufs,主要是aufs程式碼太糟糕,“dense,unreadable,and uncommented”,亂,可讀性差,沒註釋...。

Tips:雖然AUFS沒有進入Liunx核心,但是Ubuntu系統使用AUFS作為預設的儲存驅動,Docker早期僅支援Ubuntu便是這個原因。

AUFS核心概念

將多個目錄合併成一個虛擬檔案系統,成員目錄稱為虛擬檔案系統的一個分支(branch)。

例如,把 /tmp, /var, /opt三個目錄聯合掛著到 /aufs目錄下,則 /aufs目錄可見 /tmp, /var, /opt目錄下的所有檔案。而每個成員目錄,則稱為虛擬檔案系統的一個branch。


每個branch可以指定 readwrite/whiteout‐able/readonly許可權,只讀(ro),讀寫(rw),寫隱藏(wo)。一般情況下,aufs只有最上層的branch具有讀寫許可權,其餘branch均為只讀許可權。只讀branch只能邏輯上修改。

例如,把/tmp目錄和 /var目錄聯合掛載到 /aufs目錄下, /var目錄掛載為頂層branch具有rw許可權,而 /tmp目錄掛載為下層branch,具有ro許可權。如果把 /tmp目錄 /var目錄 /opt目錄聯合掛載到 /aufs目錄下,只有最頂層 /optbranch具有rw許可權,下層branch均為ro許可權。


Tips:mount ­t aufs ­obr=/tmp:/var:/opt none /aufs

該指令聯合掛載 /tmp, /var, /opt至掛載點 /aufs,按照從左到右的順序 /tmp位於頂層branch,而 /opt位於最底層branch,所有的branch按照順序共同構成 /aufs棧。

AUFS每層branch可以動態的增加刪除,每增加一層,下層預設置為ro,最上一層為rw。刪除branch是在aufs掛載點移除,並未刪除掛載目錄。

Docker中的AUFS

AUFS是Docker使用的第一個儲存驅動,長時間以來,一直很穩定。雖然目前Docker支援多種儲存驅動,而在Ubuntu中預設使用aufs儲存驅動,可以使用Docker info指令進行檢視。對於Docker而言,AUFS有很多優秀的特點,比如快速啟動容器,高效儲存利用率,高效記憶體利用率等。

Docker映象和AUFS branch對應關係

Docker映象(Image)是由一個或多個AUFS branch組成,並且所有的branch均為只讀許可權。簡單來說,AUFS所有robranch按照一定順序堆積構成Docker Image映象。

在執行容器的時候,建立一個AUFS branch位於image層之上,具有rw許可權,並把這些branch聯合掛載到一個掛載點下。這就是Docker能夠一個映象執行多個容器的原理所在。

例如,Image有3個目錄位於 /var/lib/docker/aufs/diff/資料夾內,當基於該Image建立容器時,建立一個容器執行目錄,同樣位於/var/lib/docker/aufs/diff/目錄下,並使用aufs聯合掛載Image目錄和Container目錄到 /var/lib/docker/aufs/mnt/目錄下。

每一個目錄在aufs內都是一層branch,只有頂層容器branch可讀寫,下層Image branch均只讀。建立多個容器時,只需建立多個容器執行目錄,使用aufs把容器執行目錄掛載在Image目錄之上,即實現一個Image執行多個Container。


如上圖中基於同一個Image執行兩個容器,低層Image一致,每啟動一個新容器,便會新建一個目錄作為aufs branch並與Image branch進行聯合掛載。

容器檔案讀寫與刪除

當容器需要修改一個檔案,而該檔案位於低層branch時,頂層branch會直接複製低層branch的檔案至頂層再進行修改,而低層的檔案不變,這種方式即是CoW技術(寫複製),AUFS預設支援Cow技術。

當容器刪除一個低層branch檔案時,只是在頂層branch對該檔案進行重新命名並隱藏,實際並未刪除檔案,只是不可見,這種方式即AUFS的whiteout(寫隱藏)。

下圖所示,容器層所見file1檔案為映象層檔案,當需要修改file1時,會從映象層把檔案複製到容器層,然後進行修改,從而保證映象層資料的完整性和複用性。


下圖所示,當需要刪除file1時,由於file1是映象層檔案,容器層會建立一個 .wh前置的隱藏檔案,從而實現對file1的隱藏,實際並未刪除file1,從而保證映象層資料的完整性和複用性。


Docker本地儲存目錄

Docker映象存在在/var/lib/docker/aufs/diff/目錄下。/var/lib/docker/aufs/layers/目錄儲存image的元資訊,主要是image的每一層layer組織順序(AUFS branch堆積順序)。

Docker容器掛載點位於/var/lib/docker/aufs/mnt/目錄下,該目錄即為AUFS聯合掛載點。

Tips:早期映象的每一層資料儲存在/var/lib/docker/aufs/diff/目錄下,映象ID與目錄名同名,從docker v1.10 版本之後映象ID不再與 /var/lib/docker/aufs/diff/目錄下的目錄同名,而是採用一個安全的hash值作為映象儲存資料夾名稱。

總結

採用AUFS作為 Docker的容器儲存驅動,使用AUFS技術,能夠提供如下好處:

  • 節省儲存空間:多個容器可以共享基礎映象(Base Image)儲存;

  • 快速部署:如果要部署多個容器,基礎映象(Base Image)可以避免多次拷貝;

  • 記憶體更省:因為多個容器共享Base Image,以及OS的Disk快取機制,多個容器中的程序命中快取內容的機率大大增加;

  • 允許在不更改基礎映象的同時修改其目錄中的檔案:所有寫操作都發生在最上層的writeable層中,這樣可以大大增加Base Image能共享的檔案內容。

往期回顧: