Linux AUFS 檔案系統

sparkdev發表於2019-07-25

AUFS 的英文全稱為 Advanced Mult-Layered Unification Filesystem,曾經是 Another Mult-Layered Unification Filesystem,顯然,現在的內涵規格更高些。說明:本文的演示環境為 ubuntu 16.04。

Union File System

Union File System,簡稱 UnionFS,是一種為 Linux、FreeBSD 和 NetBSD 作業系統設計的,把其它檔案系統聯合到一個聯合掛載點的檔案系統服務。它使用 branch 把不同檔案系統的檔案和目錄"透明地"覆蓋,形成一個單一一致的檔案系統。這些 branch 或者是 read-only 的,或者是 read-write 的,所以當對這個虛擬後的聯合檔案系統進行寫操作的時候,系統是真正寫到了一個新的檔案中。看起來這個虛擬後的聯合檔案系統是可以對任何檔案進行操作的,但是其實它並沒有改變原來的檔案。這是因為 Union File System 用到了一個重要的資源管理技術:寫時複製。

寫時複製(copy-on-write,常被簡寫為 CoW),也叫隱式共享,是一種提高資源使用效率的資源管理技術。它的思想是:如果一個資源是重複的,在沒有對資源做出修改前,並不需要立即複製出一個新的資源例項,這個資源被不同的所有者共享使用。當任何一個所有者要對該資源做出修改時,複製出一個新的資源例項給該所有者進行修改,修改後的資源成為其所有者的私有資源。通過這種資源共享的方式,可以顯著地減少複製相同資源帶來的消耗,但是這樣做也會在進行資源的修改時增加一部分開銷。

建立 AUFS

我們可以通過 mount 命令手動建立 AUFS,接下來我們就用這種方式來演示 AUFS 的主要特徵。

建立演示用的目錄和檔案
先建立一個名稱為 aufs 的資料夾用作實驗目錄:

$ mkdir aufs

然後在 aufs 中建立名稱為 mnt 的目錄作為檔案系統的掛載點:

$ mkdir aufs/mnt

接下來在 aufs 目錄下建立 container-layer 資料夾(模擬容器的讀寫層),並且在資料夾中建立檔案 container-layer.txt,檔案的內容初始化為 "I am container layer":

$ mkdir aufs/container-layer
$ echo "I am container layer" > aufs/container-layer/container-layer.txt

最後在 aufs 目錄下建立三個資料夾 image-layer1、image-layer2、image-layer3(用它們來模擬容器的映象層)。在這三個資料夾中分別建立檔案,並初始化為對應的內容:

$ mkdir aufs/{image-layer1,image-layer2,image-layer3}
$ echo "I am image layer 1" > aufs/image-layer1/image-layer1.txt
$ echo "I am image layer 2" > aufs/image-layer2/image-layer2.txt
$ echo "I am image layer 3" > aufs/image-layer3/image-layer3.txt

準備的目錄和檔案結構如下圖所示:

建立 AUFS 檔案系統
mount 是一個非常強大的命令,我們可以用它來建立 AUFS 檔案系統。下面的命令把 container-layer、image-layer1、image-layer2、image-layer3 以 AUFS 的方式掛載到剛才建立的 mnt 目錄下:

$ cd aufs
$ sudo mount -t aufs -o dirs=./container-layer:./image-layer1:./image-layer2:./image-layer3 none ./mnt

掛載完成後可以看到 mnt 目錄下的檔案結構為:

注意,在 mount 命令中我們沒有指定要掛載的 4 個資料夾的許可權資訊,其預設行為是:dirs 指定的左邊起第一個目錄是 read-write 許可權,後續目錄都是 read-only 許可權。我們可以通過下面的方式檢視詳情:

其中的 si_99b90cdd124201eb 目錄是系統為 mnt 這個掛載點建立的,從上圖中我們可以清楚的看到各個目錄的掛載許可權。

驗證寫時複製
下面讓我們向 mnt/image-layer2.txt 檔案中寫入些資料,看看會發生什麼變化?

$ echo "I changed mnt/image-layer2.txt" >> mnt/image-layer2.txt

檢視 mnt/image-layer2.txt 的內容,發現已經變化了:

I am image layer 2
I changed mnt/image-layer2.txt

再去看看 image-layer2/image-layer2.txt,發現它的內容沒有變化,還是:

I am image layer 2

原因在哪裡呢?去 container-layer 目錄下看看:

這裡多了一個 image-layer2.txt 檔案,其內容如下:

原來,當嘗試向 mnt/image-layer2.txt 中寫入檔案時,系統首先在 mnt 目錄下查詢名為 image-layer2.txt 的檔案,將其拷貝到 read-write 層的 container-layer 目錄中,接著對 container-layer 目錄中的 image-layer2.txt 的檔案進行寫操作。這個過程也就是 AUFS 的實際工作原理。

至此,我們完成了一個簡單的 AUFS demo。可以看出 AUFS 的原理並不是很複雜,但是當與容器技術相結合後,就展示出來超強的魅力,併成為初代 docker 預設的儲存驅動。雖然當前 docker 預設的儲存驅動已經演進到了 overlay2,但是學習 AUFS 依然可以幫助我們深入理解 docker 中的檔案系統。

參考:
維基百科 AUFS
Linux AuFS Examples
AUFS Source Code
Docker Use the AUFS storage driver
《自己動手寫 docker》

相關文章