天天看點

深入了解overlayfs(一):初識Overlayfs概述小結參考文獻

Overlayfs是一種類似aufs的一種堆疊檔案系統,于2014年正式合入Linux-3.18主線核心,目前其功能已經基本穩定(雖然還存在一些特性尚未實作)且被逐漸推廣,特别在容器技術中更是勢頭難擋。本系列博文将首先介紹overlayfs的基本概念和應用場景,然後通過若幹執行個體描述它的使用方式,最後從源碼角度結合Linux VFS Layer和Ext4fs連通分析overlayfs的實作。本文先來大緻認識一下什麼是Overlayfs,它有什麼應用場景和使用限制。

核心版本:Linux-4.13.y

Overlayfs概述

基本概念

Overlayfs是一種堆疊檔案系統,它依賴并建立在其它的檔案系統之上(例如ext4fs和xfs等等),并不直接參與磁盤空間結構的劃分,僅僅将原來底層檔案系統中不同的目錄進行“合并”,然後向使用者呈現。是以對于使用者來說,它所見到的overlay檔案系統根目錄下的内容就來自挂載時所指定的不同目錄的“合集”。見圖1。

深入了解overlayfs(一):初識Overlayfs概述小結參考文獻

圖1 Overlayfs基本結構

其中lower dirA / lower dirB目錄和upper dir目錄為來自底層檔案系統的不同目錄,使用者可以自行指定,内部包含了使用者想要合并的檔案和目錄,merge dir目錄為挂載點。當檔案系統挂載後,在merge目錄下将會同時看到來自各lower和upper目錄下的内容,并且使用者也無法(無需)感覺這些檔案分别哪些來自lower dir,哪些來自upper dir,使用者看見的隻是一個普通的檔案系統根目錄而已(lower dir可以有多個也可以隻有一個)。

雖然overlayfs将不同的各層目錄進行合并,但是upper dir和各lower dir這幾個不同的目錄并不完全等價,存在層次關系。首先當upper dir和lower dir兩個目錄存在同名檔案時,lower dir的檔案将會被隐藏,使用者隻能看見來自upper dir的檔案,然後各個lower dir也存在相同的層次關系,較上層屏蔽叫下層的同名檔案。除此之外,如果存在同名的目錄,那就繼續合并(lower dir和upper dir合并到挂載點目錄其實就是合并的一個典型例子)。

各層目錄中的upper dir是可讀寫的目錄,當使用者通過merge dir向其中一個來自upper dir的檔案寫入資料時,那資料将直接寫入upper dir下原來的檔案中,删除檔案也是同理;而各lower dir則是隻讀的,在overlayfs挂載後無論如何操作merge目錄中對應來自lower dir的檔案或目錄,lower dir中的内容均不會發生任何的改變(理論設計如此,但實際在一些極端場景存在偏差,後面我會詳細介紹)。既然lower dir是隻讀的,那當使用者想要往來自lower層的檔案添加或修改内容時,overlayfs首先會拷貝一份lower dir中的檔案副本到upper dir中,後續的寫入和修改操作将會在upper dir下的copy-up的副本檔案中進行,lower dir原檔案被隐藏。

以上就是overlayfs最基本的特性,簡單的總結為以下3點:(1)上下層同名目錄合并;(2)上下層同名檔案覆寫;(3)lower dir檔案寫時拷貝。這三點對使用者都是不感覺的。

應用

基本了解overlayfs的基本特性以後,來了解overlayfs特性所帶來的好處和應用場景。在實際的使用中,我們可能會存在以下的多使用者複用共享檔案和目錄的場景。見圖2。

深入了解overlayfs(一):初識Overlayfs概述小結參考文獻

圖2 複用共享目錄檔案

在同一個裝置上,使用者A和使用者B有一些共同使用的共享檔案(例如運作程式所依賴的動态連結庫等),一般是隻讀的;同時也有自己的私有檔案(例如系統配置檔案等),往往是需要能夠寫入修改的;最後即使使用者A修改了被共享的檔案也不會影響到使用者B。

對于以上的需求場景,我們并不希望每個使用者都有一份完全一樣的檔案副本,因為這樣不僅帶來空間的浪費也會影響性能,是以overlayfs是一個較為完美的解決方案。我們将這些共享的檔案和目錄所在的目錄設定為lower dir (1~n),将使用者私有的檔案和目錄所在的目錄設定為upper dir,然後挂載到使用者指定的挂載點,這樣即能夠保證前面列出的3點需求,同時也能夠保證使用者A和B獨有的目錄樹結構。最後最為關鍵的是使用者A和使用者B在各自挂載目錄下看見的共享檔案其實是同一個檔案,這樣磁盤空間的節省自是不必說了,還有就是共享同一份cache而減少記憶體的使用和提高通路性能,因為隻要cache不被回收,隻需某個使用者首次通路時建立cache,後續其他所有使用者都可以通過通路cache來提高IO性能。

上面說的這種使用場景在容器技術中應用最為廣泛,下面以docker容器為例來介紹overlay的兩種應用方式:Overlay和Overlay2.

Docker容器将鏡像層(image layer)作為lower dir,将容器層(container layer)作為upper dir,最後挂載到容器merge挂載點,即容器的根目錄下。遺憾的是,早期核心中的overlayfs并不支援多lower layer,在Linux-4.0以後的核心版本中才陸續支援完善。而容器中可能存在多層鏡像,是以出現了兩種overlayfs的挂載方式,早期的overlay不使用多lower layer的方式挂載而overlay2則使用該方式挂載。

1. Overlay Driver

Overlay挂載方式如下。見圖3(該圖引用自Miklos Szeredi的《overlayfs and containers》2017 linux核心大會演講材料)。

深入了解overlayfs(一):初識Overlayfs概述小結參考文獻

圖3 Overlay Driver

本圖黃色框中的部分是鏡像層和容器層的組織方式,各個鏡像層中,每下一層中的檔案以硬連結的方式出現在它的上一層中,以此類推,最終挂載overlayfs的lower dir為最上層鏡像層目錄imager layer N。與此同時,容器的writable dir作為upper dir,挂載成為容器的rootfs。本圖中雖然隻描述了一個容器的挂載方式,但是其他容器也類似,鏡像層lower dir N共享,隻是各個容器的upper dir不同而已。

2. Overlay2 Driver

Overlay2挂載方式如下。見圖4(該圖引用自Miklos Szeredi的《overlayfs and containers》2017 linux核心大會演講材料)。

深入了解overlayfs(一):初識Overlayfs概述小結參考文獻

圖4 Overlay2 Driver

Overlay2的挂載方式比Overlay的要簡單許多,它基于核心overlayfs的Multiple lower layers特性實作,不在需要硬連結,直接将鏡像層的各個目錄設定為overlayfs的各個lower layer即可(Overlayfs最多支援500層lower dir),對比Overlay Driver将減少inode的使用。

注意事項

盡管Overlayfs看起來是這麼的優秀,但是目前它還并不是那麼的完美,依然存在一些缺點和使用限制(還沒有完全支援POSIX标準),這裡簡單列出一些,先認識一下,以後遇到也能心中有數:

0. Mount Overlayfs之後就不允許在對原lower dir和upper dir進行操作

當我們挂載完成overlayfs以後,對檔案系統的任何操作都隻能在merge dir中進行,使用者不允許再直接或間接的到底層檔案系統的原始lower dir或upper dir目錄下修改檔案或目錄,否則可能會出現一些無法預料的後果(kernel crash除外)。

1. Copy-up

Overlayfs的lower layer檔案寫時複制機制讓某一個使用者在修改來自lower層的檔案不會影響到其他使用者(容器),但是這個檔案的複制動作會顯得比較慢,後面我們會看到為了保證檔案系統的一緻性,這個copy-up實作包含了很多步驟,其中最為耗時的就是檔案資料塊的複制和fsync同步。使用者在修改檔案時,如果檔案較小那可能不一定能夠感受出來,但是當檔案比較大或一次對大量的小檔案進行修改,那耗時将非常可觀。雖然自Linux-4.11起核心引入了“concurrent copy up”特性來提高copy-up的并行性,但是對于大檔案也還是沒有明顯的效果。不過幸運的是,如果底層的檔案系統支援reflink這樣的延時拷貝技術(例如xfs)那就不存在這個問題了。

2. Rename directory(POSIX标準支援問題)

如果Overlayfs的某一個目錄是單純來自lower layer或是lower layer和upper layer合并的,那預設情況下,使用者無法對該目錄執行rename系統調用,否則會傳回-EXDEV錯誤。不過你會發現通過mv指令重命名該目錄依然可以成功,那是因為mv指令的實作對rename系統調用的-EXDEV錯誤進行規避(這當然是有缺點的,先暫不展開)。在Linux-4.10起核心引入了“redirect dir”特性來修複這個問題,為此引入了一個核心選項:CONFIG_OVERLAY_FS_REDIRECT_DIR,使用者想要支援該特性可以在核心中開啟這個選項,否則就應避免對這兩類目錄使用rename系統調用。

3. Hard link break(POSIX标準支援問題)

該問題源自copy-up機制,當lower dir目錄中某個檔案擁有多個硬連結時,若使用者在merge layer對其中一個寫入了一些資料,那将觸發copy-up,由此該檔案将拷貝到upper dir,那麼和原始檔案的hard link也就斷開了,變成了一個單獨的檔案,使用者在merge layer通過stat和ls指令能夠直接看到這個變化。在Linux-4.13起核心引入了“index feature”來修複這個問題,同樣引入了一個核心選項:CONFIG_OVERLAY_FS_INDEX,使用者想要修複該問題可以打開這個選項,不過該選項不具有向前相容性,請謹慎使用。

4. Unconstant st_dev&st_ino(POSIX标準支援問題)

該問題同樣源自copy-up機制,當原來在lower dir中的檔案觸發了copy-up以後,那使用者在merge layer見到的将是來自upper dir的新檔案,那也就意味着它倆的inode是不同的,雖然inode中很多的attr和xattr是可以copy的,但是st_dev和st_ino這兩個字段卻具有唯一性,是不可以複制的,是以使用者可以通過ls和stat指令看到的該字段将發生變化。在Linux-4.12和Linux-4.13分别進行了部分的修複,目前在lower dir和upper dir都在同一個檔案系統挂載點的場景下,問題已經修複,但lower dir和upper dir若來自不同的檔案系統,問題依然存在。

5. File descriptor change(POSIX标準支援問題)

該問題也同樣源自copy-up機制,使用者在檔案發生copy-up之前以隻讀方式open檔案(這操作不會觸發copy-up)得到的檔案描述符fd1和copy-up之後open檔案得到的檔案描述符fd2指向不同的檔案,使用者通過fd2寫入的新資料,将無法從fd1中擷取到,隻能重新open一個新的fd。該問題目前社群主線核心依然存在,暫未修複。

以上這6點列出了目前Overlayfs的主要問題和限制,将在後文中陸續展開。社群為了讓Overlayfs能夠更加向支援Posix标準的檔案系統靠攏,做出了很多的努力,後續将進一步修複上面提到且未修複的問題,還會增加對NFS Export、freeze snapshots、overlayfs snapshots等的支援,進一步完善overlayfs。

小結

Overlayfs在以它特有的機制已經使用的越來越廣泛,在Docker容器技術中以它優異的性能将會漸漸成為首選。不過overlayfs也尚存諸多限制,到目前為止,它還不是一個完全符合Posix規範的檔案系統,但社群的開發人員們一直在努力完善,相信不久的将來我們會看到一個非常易用且成熟的Overlayfs。

參考文獻

1. <overlayfs and containers> by Miklos Szeredi.

2. Documentation/filesystems/overlayfs.txt

轉自:

https://blog.csdn.net/luckyapple1028/article/details/77916194