Linux中國

容器如何工作: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

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國