使用 AUFS 儲存驅動程式

已棄用

AUFS 儲存驅動程式已棄用,並將在 Docker Engine v24.0 中移除。如果您正在使用 AufS,您必須在升級到 Docker Engine v24.0 之前遷移到支援的儲存驅動程式。閱讀 Docker 儲存驅動程式 頁面以瞭解支援的儲存驅動程式。

AUFS 是一個聯合檔案系統aufs 儲存驅動程式以前是用於管理 Docker for Ubuntu 上的映像和層的預設儲存驅動程式,以及 Stretch 之前的 Debian 版本。如果您的 Linux 核心版本為 4.0 或更高,並且您使用 Docker Engine - Community,請考慮使用更新的 overlay2,它可能比 aufs 儲存驅動程式具有更高的效能優勢。

先決條件

  • 對於 Docker Engine - Community,AUFS 在 Ubuntu 和 Stretch 之前的 Debian 版本上受支援。
  • 對於 Docker EE,AUFS 在 Ubuntu 上受支援。
  • 如果您使用 Ubuntu,則需要將 AUFS 模組新增到核心。如果您沒有安裝這些軟體包,則需要使用 overlay2
  • AUFS 無法使用以下作為後端的檔案系統:aufsbtrfsecryptfs。這意味著包含 /var/lib/docker/aufs 的檔案系統不能是這些檔案系統型別之一。

使用 aufs 儲存驅動程式配置 Docker

如果 AUFS 驅動程式在您啟動 Docker 時載入到核心中,並且沒有配置其他儲存驅動程式,則 Docker 預設使用它。

  1. 使用以下命令驗證您的核心是否支援 AUFS。

    $ grep aufs /proc/filesystems
    
    nodev   aufs
    
  2. 檢查 Docker 使用的儲存驅動程式。

    $ docker info
    
    <truncated output>
    Storage Driver: aufs
     Root Dir: /var/lib/docker/aufs
     Backing Filesystem: extfs
     Dirs: 0
     Dirperm1 Supported: true
    <truncated output>
    
  3. 如果您使用的是不同的儲存驅動程式,那麼 AUFS 要麼未包含在核心中(在這種情況下,使用不同的預設驅動程式),要麼 Docker 已明確配置為使用不同的驅動程式。檢查 /etc/docker/daemon.jsonps auxw | grep dockerd 的輸出,以檢視 Docker 是否使用 --storage-driver 標誌啟動。

aufs 儲存驅動程式的工作原理

AUFS 是一個聯合檔案系統,這意味著它將單個 Linux 主機上的多個目錄疊加在一起,並將其呈現為單個目錄。在 AUFS 術語中,這些目錄稱為分支,在 Docker 術語中稱為

統一過程稱為聯合掛載

下圖顯示了一個基於 ubuntu:latest 映像的 Docker 容器。

Layers of an Ubuntu container

每個映像層和容器層在 Docker 主機上都以 /var/lib/docker/ 中的子目錄形式表示。聯合掛載提供了所有層的統一檢視。目錄名稱並不直接對應於層的 ID 本身。

AUFS 使用寫時複製 (CoW) 策略來最大限度地提高儲存效率並最大限度地減少開銷。

示例:磁碟上的映像和容器結構

以下 docker pull 命令顯示了一個 Docker 主機下載包含五個層的 Docker 映像。

$ docker pull ubuntu

Using default tag: latest
latest: Pulling from library/ubuntu
b6f892c0043b: Pull complete
55010f332b04: Pull complete
2955fb827c94: Pull complete
3deef3fcbd30: Pull complete
cf9722e506aa: Pull complete
Digest: sha256:382452f82a8bbd34443b2c727650af46aced0f94a44463c62a9848133ecb1aa8
Status: Downloaded newer image for ubuntu:latest

映像層

警告:不要直接操作 /var/lib/docker/ 中的任何檔案或目錄。這些檔案和目錄由 Docker 管理。

有關映像和容器層的所有資訊都儲存在 /var/lib/docker/aufs/ 的子目錄中。

  • diff/:每層的內容,每個都儲存在單獨的子目錄中
  • layers/:有關映像層堆疊方式的元資料。此目錄包含 Docker 主機上每個映像或容器層的一個檔案。每個檔案都包含其下方堆疊中所有層的 ID(其父層)。
  • mnt/:掛載點,每個映像或容器層一個,用於組裝和掛載容器的統一檔案系統。對於只讀的映像,這些目錄始終為空。

容器層

如果容器正在執行,則 /var/lib/docker/aufs/ 的內容會以下列方式更改

  • diff/:可寫容器層中引入的差異,例如新檔案或修改後的檔案。
  • layers/:有關可寫容器層父層的元資料。
  • mnt/:每個正在執行的容器的統一檔案系統的掛載點,與容器內部看到的一模一樣。

aufs 如何處理容器讀寫操作

讀取檔案

考慮三個場景,其中容器使用 aufs 以讀訪問方式開啟檔案。

  • 檔案不存在於容器層:如果容器以讀訪問方式開啟一個檔案,並且該檔案尚不存在於容器層中,則儲存驅動程式會在映像層中搜索該檔案,從容器層正下方的層開始搜尋。它會從找到該檔案的層中讀取。

  • 檔案僅存在於容器層:如果容器以讀訪問方式開啟一個檔案,並且該檔案存在於容器層中,則會從那裡讀取該檔案。

  • 檔案同時存在於容器層和映像層:如果容器以讀訪問方式開啟一個檔案,並且該檔案存在於容器層和一個或多個映像層中,則會從容器層讀取該檔案。容器層中的檔案會遮蔽映像層中具有相同名稱的檔案。

修改檔案或目錄

考慮容器中修改檔案的一些場景。

  • 首次寫入檔案:容器首次寫入現有檔案時,該檔案不存在於容器中 (upperdir)。aufs 驅動程式執行copy_up 操作,將檔案從它所在的映像層複製到可寫容器層。然後,容器將更改寫入容器層中該檔案的新副本。

    但是,AUFS 針對的是檔案級別,而不是塊級別。這意味著所有 copy_up 操作都會複製整個檔案,即使檔案非常大,並且只有一小部分被修改。這會對容器寫入效能產生明顯的影響。當在包含多個層的映像中搜索檔案時,AUFS 會遇到明顯的延遲。但是,值得注意的是,copy_up 操作僅在首次寫入給定檔案時才會發生。後續寫入同一檔案會針對已複製到容器的該檔案副本進行操作。

  • 刪除檔案和目錄:

    • 當在容器中刪除一個檔案時,會在容器層中建立一個白出檔案。映像層中的檔案版本不會被刪除(因為映像層是隻讀的)。但是,白出文件會阻止容器訪問它。

    • 當在容器中刪除一個目錄時,會在容器層中建立一個不透明檔案。這與白出文件的操作方式相同,並且有效地阻止了對該目錄的訪問,即使它仍然存在於映像層中。

  • 重新命名目錄:在 AUFS 上,呼叫 rename(2) 來重新命名目錄不受完全支援。它會返回 EXDEV(“不允許跨裝置連結”),即使源路徑和目標路徑都位於同一 AUFS 層上,除非該目錄沒有任何子項。您的應用程式需要設計為處理 EXDEV 並回退到“複製和取消連結”策略。

AUFS 和 Docker 效能

總結上面提到的某些與效能相關的方面

  • AUFS 儲存驅動程式的效能不如 overlay2 驅動程式,但對於容器密度很重要的 PaaS 和其他類似用例來說,它是一個不錯的選擇。這是因為 AUFS 可以有效地在多個正在執行的容器之間共享映像,從而實現快速容器啟動時間和最少的磁碟空間使用。

  • AUFS 利用頁快取高效地實現映象層和容器之間檔案共享的底層機制。

  • AUFS 儲存驅動可能會導致容器寫入效能出現顯著延遲。這是因為容器第一次寫入任何檔案時,需要先定位該檔案並將其複製到容器的頂層可寫層。當這些檔案位於多個映象層之下,且檔案本身很大時,延遲會增加並累積。

效能最佳實踐

以下通用效能最佳實踐也適用於 AUFS。

  • **固態硬碟 (SSD)** 比旋轉磁碟提供更快的讀寫速度。

  • **對於寫密集型工作負載,使用卷:** 卷為寫密集型工作負載提供最佳且最可預測的效能。這是因為它們繞過了儲存驅動程式,不會產生由稀疏配置和寫時複製引入的任何潛在開銷。卷還有其他好處,例如允許您在容器之間共享資料,即使沒有執行的容器使用它們也能持久存在。