1. 程式人生 > 其它 >AUFS:多點合一,寫時複製

AUFS:多點合一,寫時複製

AUFS(全稱:advanced multi-layered unification filesystem,高階多層統一檔案系統),用於為 Linux 檔案系統實現聯合掛載。提到聯合掛載,就要先解一下 Union File System。

Union File System

Union File System,簡稱 UnionFS,是一種為 Linux、FreeBSD 和 NetBSD 作業系統設計的檔案系統,它能夠多個其他檔案系統聯合到一個地方來掛載。換句話說,就是不過目錄合併 mount 到同一個目錄中。
它和核心原理有兩個:

  • 分支管理:它使用 branch 把不同檔案系統的檔案和目錄"透明地"覆蓋,形成一個單一一致的檔案系統。這些 branch 或者是 read-only 的,或者是 read-write 的,所以當對這個虛擬後的聯合檔案系統進行寫操作的時候,系統是真正寫到了一個新的檔案中。
  • 寫時複製:copy-on-write,簡寫為 CoW,也叫隱式共享,是一種提高資源使用效率的資源管理技術。它的思想是:如果一個資源是重複的,在沒有對資源做出修改前,並不需要立即複製出一個新的資源例項,這個資源被不同的所有者共享使用。當任何一個所有者要對該資源做出修改時,複製出一個新的資源例項給該所有者進行修改,修改後的資源成為其所有者的私有資源。通過這種資源共享的方式,可以顯著地減少複製相同資源帶來的消耗,但是這樣做也會在進行資源的修改時增加一部分開銷。

AUFS

AUFS 又叫 Another UnionFS,後來叫 Alternative UnionFS,後來可能覺得不夠霸氣,叫成 Advance UnionFS。是個叫 Junjiro Okajima(岡島順治郎)在 2006 年開發的,AUFS 完全重寫了早期的 UnionFS 1.x,其主要目的是為了可靠性和效能,並且引入了一些新的功能,比如可寫分支的負載均衡。AUFS 在使用上全相容 UnionFS,而且比之前的 UnionFS 在穩定性和效能上都要好很多,後來的 UnionFS 2.x 開始抄 AUFS 中的功能。

實戰 AUFS

在 Ubuntu 中,我們可以通過 mount 命令手動來建立 AUFS,以此來體驗一下 AUFS 的巧妙之處。

建立實驗目錄和檔案

  1. 建立實驗目錄 aufs
$ mkdir aufs
  1. 在 aufs 目錄下建立 mnt 目標作為檔案系統的掛載點
$ mkdir aufs/mnt
  1. 在 aufs 目錄下建立 container-layer 資料夾,用來模擬容器的讀寫層
$ mkdir aufs/container-layer
# 同時建立檔案 container-layer.txt 並初始化內容
$ echo "I am container layer" > aufs/container-layer/container-layer.txt
  1. 在 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.tx

準備好的實驗目錄和檔案結構如下:

建立 AUFS 檔案系統

  1. 通過 mount 把 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_f7dd5867fe18e716 目錄是系統為 mnt 這個掛載點建立的,從上圖中我們可以清楚的看到各個目錄的掛載許可權。

驗證寫時複製

接下來我們向 mnt/image-layer3.txt 檔案寫入資料:

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

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

那再去看看底層檔案 image-layer3/image-layer3.txt,發現他的內容並沒有改變:

那麼,改變的內容被儲存到了什麼地方呢?去看看 container-layer 目錄:

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

到這裡,我們就完成了 AUFS 的實驗,從中也學到了 AUFS 寫時複製的技術原理。實驗結束完,別忘了回收實驗環境:

$ sudo umount aufs/mnt

Docker by UnionFS

雖然當前 docker 預設的儲存驅動已經演進到了 overlay2,但是學習 AUFS 依然可以幫助我們深入理解 docker 中的檔案系統。當我們以後在使用 Docker 容器時,我們在 build 映象時,寫時複製就在發揮著作用。