今天早上,我為未來潛在容器雜誌畫了一幅 OverlayFS 的漫畫,我對這個主題感到興奮,想寫一篇關於它的部落格來提供更多詳細資訊。
容器映象可能會很大(儘管有些很小,例如 alpine linux 才 2.5MB)。Ubuntu 16.04 約為 27 MB,Anaconda Python 發行版為 800MB 至 1.5GB。
你以映象啟動的每個容器都是原始空白狀態,彷彿它只是為使用容器而複製的一份映象拷貝一樣。但是對於大的容器映象,像 800MB 的 Anaconda 映象,複製一份拷貝既浪費磁碟空間也很慢。因此 Docker 不會複製,而是採用疊加。
OverlayFS,也被稱為 聯合檔案系統或 聯合掛載,它可讓你使用 2 個目錄掛載檔案系統:“下層”目錄和“上層”目錄。
基本上:
當進程“讀取”檔案時,OverlayFS 檔案系統驅動將在上層目錄中查詢並從該目錄中讀取檔案(如果存在)。否則,它將在下層目錄中查詢。
當進程“寫入”檔案時,OverlayFS 會將其寫入上層目錄。
這有點抽象,所以讓我們製作一個 OverlayFS 並嘗試一下!這將只包含一些檔案:我將建立上、下層目錄,以及用來掛載合併的檔案系統的 merged
目錄:
$ mkdir upper lower merged work$ echo "I'm from lower!" > lower/in_lower.txt$ echo "I'm from upper!" > upper/in_upper.txt$ # `in_both` is in both directories$ echo "I'm from lower!" > lower/in_both.txt$ echo "I'm from upper!" > upper/in_both.txt
合併上層目錄和下層目錄非常容易:我們可以通過 mount
來完成!
$ sudo mount -t overlay overlay -o lowerdir=/home/bork/test/lower,upperdir=/home/bork/test/upper,workdir=/home/bork/test/work /home/bork/test/merged
在執行此操作時,我不斷收到一條非常煩人的錯誤訊息,內容為:mount: /home/bork/test/merged: special device overlay does not exist.
。這條訊息是錯誤的,實際上只是意味著我指定的一個目錄缺失(我寫成了 ~/test/merged
,但它沒有被展開)。
讓我們嘗試從 OverlayFS 中讀取其中一個檔案!檔案 in_both.txt
同時存在於 lower/
和 upper/
中,因此應從 upper/
目錄中讀取該檔案。
$ cat merged/in_both.txt"I'm from upper!
可以成功!
目錄的內容就是我們所期望的:
find lower/ upper/ merged/lower/lower/in_lower.txtlower/in_both.txtupper/upper/in_upper.txtupper/in_both.txtmerged/merged/in_lower.txtmerged/in_both.txtmerged/in_upper.txt
$ echo 'new file' > merged/new_file$ ls -l */new_file-rw-r--r-- 1 bork bork 9 Nov 18 14:24 merged/new_file-rw-r--r-- 1 bork bork 9 Nov 18 14:24 upper/new_file
這是有作用的,新檔案會在 upper
目錄建立。
讀寫似乎很簡單。但是刪除會發生什麼?開始試試!
$ rm merged/in_both.txt
發生了什麼?讓我們用 ls
看下:
ls -l upper/in_both.txt lower/lower1.txt merged/lower1.txtls: cannot access 'merged/in_both.txt': No such file or directory-rw-r--r-- 1 bork bork 6 Nov 18 14:09 lower/in_both.txtc--------- 1 root root 0, 0 Nov 18 14:19 upper/in_both.txt
所以:
in_both.txt
仍在 lower
目錄中,並且保持不變merged
目錄中。到目前為止,這就是我們所期望的。upper
中發生的事情有點奇怪:有一個名為 upper/in_both.txt
的檔案,但是它是字元裝置?我想這就是 overlayfs 驅動表示刪除的檔案的方式。如果我們嘗試複製這個奇怪的字元裝置檔案,會發生什麼?
$ sudo cp upper/in_both.txt upper/in_lower.txtcp: cannot open 'upper/in_both.txt' for reading: No such device or address
好吧,這似乎很合理,複製這個奇怪的刪除信號檔案並沒有任何意義。
Docker 映象通常由 25 個“層”組成。OverlayFS 支援具有多個下層目錄,因此你可以執行:
mount -t overlay overlay -o lowerdir:/dir1:/dir2:/dir3:...:/dir25,upperdir=...
因此,我假設這是有多個 Docker 層的容器的工作方式,它只是將每個層解壓縮到一個單獨的目錄中,然後要求 OverlayFS 將它們全部合併在一起,並使用一個空的上層目錄,容器將對其進行更改。
現在,我使用的是 ext4,而 Docker 使用 OverlayFS 快照來執行容器。但是我曾經用過 btrfs,接著 Docker 將改為使用 btrfs 的寫時複製快照。(這是 Docker 何時使用哪種儲存驅動的列表)
以這種方式使用 btrfs 快照會產生一些有趣的結果:去年某個時候,我在筆電上執行了數百個臨時的 Docker 容器,這導致我用盡了 btrfs 後設資料空間(像這個人一樣)。這真的很令人困惑,因為我以前從未聽說過 btrfs 後設資料,而且弄清楚如何清理檔案系統以便再次執行 Docker 容器非常棘手。(這個 docker github 上的提案描述了 Docker 和 btrfs 的類似問題)
我認為容器通常看起來像是在做“複雜的”事情,我認為將它們分解成這樣很有趣。你可以執行一條 mount
咒語,而實際上並沒有做任何與容器相關的其他事情,看看疊加層是如何工作的!