容器如何工作:OverlayFS
容器鏡像很大
容器鏡像可能會很大(儘管有些很小,例如 alpine linux 才 2.5MB)。Ubuntu 16.04 約為 27 MB,Anaconda Python 發行版為 800MB 至 1.5GB。
你以鏡像啟動的每個容器都是原始空白狀態,彷彿它只是為使用容器而複製的一份鏡像拷貝一樣。但是對於大的容器鏡像,像 800MB 的 Anaconda 鏡像,複製一份拷貝既浪費磁碟空間也很慢。因此 Docker 不會複製,而是採用疊加。
疊加如何工作
OverlayFS,也被稱為 聯合文件系統或 聯合掛載,它可讓你使用 2 個目錄掛載文件系統:「下層」目錄和「上層」目錄。
基本上:
- 文件系統的下層目錄是只讀的
- 文件系統的上層目錄可以讀寫
當進程「讀取」文件時,OverlayFS 文件系統驅動將在上層目錄中查找並從該目錄中讀取文件(如果存在)。否則,它將在下層目錄中查找。
當進程「寫入」文件時,OverlayFS 會將其寫入上層目錄。
讓我們使用 mount 製造一個疊加層!
這有點抽象,所以讓我們製作一個 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.txt
lower/in_both.txt
upper/
upper/in_upper.txt
upper/in_both.txt
merged/
merged/in_lower.txt
merged/in_both.txt
merged/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.txt
ls: 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.txt
c--------- 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.txt
cp: 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 將它們全部合併在一起,並使用一個空的上層目錄,容器將對其進行更改。
Docker 也可以使用 btrfs 快照
現在,我使用的是 ext4,而 Docker 使用 OverlayFS 快照來運行容器。但是我曾經用過 btrfs,接著 Docker 將改為使用 btrfs 的寫時複製快照。(這是 Docker 何時使用哪種存儲驅動的列表)
以這種方式使用 btrfs 快照會產生一些有趣的結果:去年某個時候,我在筆記本上運行了數百個臨時的 Docker 容器,這導致我用盡了 btrfs 元數據空間(像這個人一樣)。這真的很令人困惑,因為我以前從未聽說過 btrfs 元數據,而且弄清楚如何清理文件系統以便再次運行 Docker 容器非常棘手。(這個 docker github 上的提案描述了 Docker 和 btrfs 的類似問題)
以簡單的方式嘗試容器功能很有趣!
我認為容器通常看起來像是在做「複雜的」事情,我認為將它們分解成這樣很有趣。你可以運行一條 mount
咒語,而實際上並沒有做任何與容器相關的其他事情,看看疊加層是如何工作的!
via: https://jvns.ca/blog/2019/11/18/how-containers-work–overlayfs/
作者:Julia Evans 選題:lujun9972 譯者:geekpi 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive