OverlayFS作為Docker儲存驅動,提供比AUFS更佳的效能和記憶體效率。其核心機制包含工作目錄、多層結構支援和檔案合併,透過這些機制,Docker有效管理映像層和容器層。組態OverlayFS驅動後,Docker會為每個容器建立一個新的上層檔案系統,僅儲存與基礎映像的差異部分,提升儲存效率。文章提供指令碼範例,展示如何在容器內建立檔案、提交變更以及驗證新映像層的內容。此外,也詳細解析了OverlayFS的目錄結構,包含upperworkmerged目錄和lower-id檔案的功能。OverlayFS的優勢在於原生核心支援、低記憶體佔用、高效能和檔案硬連結最佳化。然而,作為相對較新的檔案系統,其長期穩定性仍需持續驗證。

除了OverlayFS,文章也介紹了VFS儲存驅動,它不使用寫入時複製機制,每個映像層都是一個完整目錄,適用於沒有CoW檔案系統的平台或Docker VOLUME。然而,VFS的缺點是速度慢且磁碟空間效率低。文章透過實務範例展示了VFS的特性,並分析了其速度和空間效率問題。最後,文章探討了Docker網路模型,包含IP分配、網域名稱解析和容器服務發現等核心概念,並以圖表說明Docker網路架構,同時也提出了Docker網路在多主機網路、網路安全增強和效能最佳化等方面。

OverlayFS:Docker儲存驅動的技術解析與實踐

前言

OverlayFS是一種強大的檔案系統,它為Docker提供了高效的儲存驅動支援。相較於AUFS,OverlayFS具有更好的效能表現和更低的記憶體佔用。本文將探討OverlayFS的工作原理、Docker中的應使用案例項,以及它在容器儲存管理中的優勢。

OverlayFS的基本原理

工作目錄(workdir)的作用

OverlayFS引入了工作目錄的概念,這是一個位於上層檔案系統的目錄,主要用於在上下層之間進行原子性複製。這個機制確保了檔案操作的完整性和一致性。

多層結構的支援

OverlayFS允許有多個下層檔案系統層級,這些層級可以堆積疊在一起形成一個統一的檔案系統檢視。下層檔案系統通常是唯讀的,而上層檔案系統則是可寫的。這種架構使得Docker能夠有效地管理多層的映像層和容器層。

檔案合併機制

當兩個或多個目錄中存在相同路徑的檔案時,OverlayFS會將它們合併呈現為一個目錄。這種合併機制最佳化了檔案查詢的時間,特別是在多層映像的場景下,相比於AUFS有明顯的效能提升。

Docker中的OverlayFS應用

儲存驅動組態

要在Docker中使用OverlayFS,需要確保核心版本至少為3.18,並明確指定使用overlay儲存驅動。透過docker info命令可以確認目前使用的儲存驅動:

# docker info
Containers: 0
Images: 0
Storage Driver: overlay
Backing Filesystem: extfs
Execution Driver: native-0.2
Kernel Version: 3.18.0-031800-generic
Operating System: Ubuntu 14.04 LTS
CPUs: 1
Total Memory: 489.2 MiB
Name: docker
ID: NQJM:HHFZ:5636:VGNJ:ICQA:FK4U:6A7F:EUDC:VFQL:PJFF:MI7N:TX7L
WARNING: No swap limit support

容器建立與層級管理

建立新容器時,Docker會為其建立一個新的上層檔案系統,包含與基礎映像層的差異部分。這種設計與AUFS類別似,但OverlayFS提供了更好的效能:

# docker run -d busybox top
# grep eb9e1a68c705 /proc/mounts
overlay /var/lib/docker/overlay/eb9e1a68c70532ecd31e20d8ca4b7f598d2259d1ac8accaa02090f32ee0b95c1/merged overlay rw,relatime,lowerdir=/var/lib/docker/overlay/4986bf8c15363d1c5d15512d5266f8777bfba4974ac56e3270e7760f6f0a8125/root,upperdir=/var/lib/docker/overlay/eb9e1a68c70532ecd31e20d8ca4b7f598d2259d1ac8accaa02090f32ee0b95c1/upper,workdir=/var/lib/docker/overlay/eb9e1a68c70532ecd31e20d8ca4b7f598d2259d1ac8accaa02090f32ee0b95c1/work 0 0

內容解密:

這段程式碼展示瞭如何檢視 Docker 容器的掛載資訊。透過 grep 命令過濾出特定容器的掛載資訊,可以看到 OverlayFS 的掛載詳情,包括 lowerdirupperdirworkdir 的路徑組態,這些引數對於理解 OverlayFS 的工作機制至關重要。

實際操作與驗證

建立測試檔案與提交變更

在執行中的容器內建立一個空檔案,並提交變更以建立新的映像層:

# docker exec -it eb9e1a68c705 touch /etc/testfile
# docker commit eb9e1a68c705
eae6654d10c2c6467e975a80559dcc2dd57178baaea57dd8d347c950a46c404b

驗證新映像層的內容

檢查新建立的映像層是否包含預期的變更:

# ls -l /var/lib/docker/overlay/eae6654d10c2c6467e975a80559dcc2dd57178baaea57dd8d347c950a46c404b/root/etc/testfile
-rw-r--r-- 1 root root 0 Apr 8 21:44 /var/lib/docker/overlay/eae6654d10c2c6467e975a80559dcc2dd57178baaea57dd8d347c950a46c404b/root/etc/testfile

內容解密:

這裡展示瞭如何驗證新映像層中是否包含了我們在容器中建立的測試檔案。透過檢查 OverlayFS 的目錄結構,可以確認檔案是否正確地被儲存。

OverlayFS的目錄結構解析

三個主要子目錄的作用

OverlayFS為每個容器建立三個子目錄:

  • upper:可讀寫的上層檔案系統
  • work:用於原子性複製的暫存目錄
  • merged:執行中容器的掛載點

此外,還有一個lower-id檔案,用於記錄父層的ID,以便正確掛載下層檔案系統。

OverlayFS的優勢與挑戰

主要優勢:

  1. 原生核心支援:無需額外的核心補丁
  2. 低記憶體佔用:支援頁面快取分享
  3. 更好的效能表現:相比AUFS有更快的處理速度
  4. 檔案硬連結最佳化:相同檔案在不同映像間硬連結,節省空間並提升效能

目前限制:

儘管OverlayFS展現出許多優勢,但仍是一個相對較新的檔案系統,其在生產環境中的穩定性和長期表現仍待進一步驗證。

隨著容器技術的不斷發展,儲存驅動的效能和穩定性將變得越來越重要。未來,我們可以期待看到更多針對OverlayFS的最佳化工作,例如進一步提升大規模容器佈署下的效能表現,以及增強其在不同儲存後端上的適配能力。

最佳實踐建議

對於正在考慮採用OverlayFS的使用者,建議:

  1. 確保核心版本滿足最低需求(3.18以上)
  2. 在測試環境中充分驗證其穩定性
  3. 關註上遊核心和Docker的更新,以獲得最新的效能最佳化

透過合理規劃和充分測試,OverlayFS有望為您的容器化應用提供強有力的儲存支援。以下是相關 Plantuml 圖表,用於展示 OverlayFS 的工作流程: 圖表翻譯: 此圖展示了 OverlayFS 的基本架構。上層檔案系統和基礎映像層透過合併檢視形成容器的最終檔案系統。工作目錄用於支援原子性操作,確保操作的完整性。

綜上所述,OverlayFS 為 Docker 提供了一個強大且高效的儲存解決方案,具有廣泛的應用前景和技術優勢。隨著技術的不斷進步,我們可以期待看到更多根據 OverlayFS 的創新應用和最佳實踐。

Docker 儲存驅動程式詳解:VFS 儲存驅動程式

在前面的章節中,我們討論了多種 Docker 儲存驅動程式,包括 AUFS、OverlayFS、BTRFS 和 DeviceMapper。這些儲存驅動程式都使用了寫入時複製(Copy on Write, CoW)的機制來提高效能和降低磁碟空間的使用。然而,Docker 還提供了一種不使用 CoW 機制的儲存驅動程式:VFS。

VFS 儲存驅動程式的特點

VFS 儲存驅動程式是 Docker 中唯一不使用寫入時複製機制的儲存驅動程式。每個映像層都是一個簡單的目錄。當 Docker 建立一個新的層時,它會將基礎層目錄進行完整的物理複製到新建立的目錄中。這種方法可能使用此驅動程式的速度變慢且磁碟空間效率低下。

VFS 儲存驅動程式的優缺點

  • 優點
    • 平台移植性高,可以在沒有 CoW 檔案系統的平台上使用。
    • 適合用於 Docker VOLUME。
  • 缺點
    • 速度慢,因為每次建立新的層都需要進行完整的物理複製。
    • 磁碟空間效率低下,因為每個層都是獨立的目錄。

VFS 儲存驅動程式的實務範例

首先,我們需要修改 DOCKER_OPTS 以告訴 Docker 守護程式使用 VFS 驅動程式,並重新啟動它:

# ps -ef|grep docker
root 2680 1 0 21:51 ? 00:00:02 /usr/bin/docker -d --storage-driver=vfs

接下來,我們將使用一個小的 busybox 容器來執行 top 工具,以展示 VFS 驅動程式的一些特性:

# docker run -d busybox top
...
[FILTERED OUTPUT]
...
de8c6e2684acefa1e84791b163212d92003886ba8cb73eccef4b2c4d167a59a4

VFS 映像層儲存在 /var/lib/docker/vfs/dir 目錄中。現在,我們將展示使用此驅動程式的速度和磁碟空間使用效率低下的問題。

# docker run -ti busybox /bin/sh
/ # dd if=/dev/zero of=sample.txt bs=200M count=1
1+0 records in
1+0 records out
/ # du -sh sample.txt
200.0M sample.txt
/ #

提交新的映像層並觀察速度

# time docker commit 24247ae7c1c0
7f3a2989b52e0430e6372e34399757a47180080b409b94cb46d6cd0a7c46396e
real    0m1.029s
user    0m0.008s
sys     0m0.008s

建立新的映像層花費了超過 1 秒的時間,這是由於基礎映像層中存在 200M 的檔案。最後,讓我們從新提交的層建立一個新的容器,並再次觀察速度:

# time docker run --rm -it 7f3a2989b52e0430e6372e34399757a47180080b409b94cb46d6cd0a7c46396e echo VFS is slow
VFS is slow
real    0m3.124s
user    0m0.021s
sys     0m0.007s

從之前提交的映像層建立新的容器花費了超過 3 秒的時間!此外,我們現在有兩個容器,每個容器在主機檔案系統上佔用了 200M 的磁碟空間。

#### 內容解密:

此範例展示了使用 VFS 儲存驅動程式的速度和磁碟空間使用效率低下的問題。由於 VFS 不使用 CoW 機制,每次建立新的層都需要進行完整的物理複製,這導致了速度變慢和磁碟空間浪費。

VFS 的適用場景

儘管 VFS 不是為生產環境設計的,但它仍然可以在某些場景下使用,例如:

  • 在沒有 CoW 檔案系統的平台上執行 Docker。
  • 用於 Docker VOLUME,因為它具有平台移植性。

Docker 網路功能詳解

在前面的章節中,我們討論了 Docker 的各種儲存驅動程式,以及它們如何幫助從建置的映像檔中高效地封裝和執行 Docker 容器。Docker 的真正強大之處在於用於構建分散式應用程式。分散式應用程式由任意數量的服務組成,這些服務在電腦網路上進行通訊以執行某些計算任務。本章將嘗試回答一個簡單的問題:如何使在 Docker 容器內執行的應用程式可在網路上存取?為了回答這個問題,我們需要了解 Docker 網路模型。

Docker 網路模型的三個主要方面

  1. IP 分配:Docker 需要為容器分配 IP 位址,以便它們可以在網路上進行通訊。
  2. 網域名稱解析:Docker 需要提供網域名稱解析功能,以便容器可以透過網域名稱互相存取。
  3. 容器或服務發現:Docker 需要提供容器或服務發現功能,以便容器可以發現彼此並進行通訊。

這些概念是零組態網路(zeroconf)的基礎。zeroconf是一組技術,可以在沒有任何手動干預的情況下自動建立和組態 TCP/IP 網路。

Docker 網路的挑戰

在複雜的環境中,Docker 容器的密度可能會迅速波動,管理和操作這樣的環境可能是一個真正的挑戰。在這些環境中實作 zeroconf 的「咒語」應該是最終的網路目標。它可以解除開發人員和操作人員手動組態網路的負擔。

Docker 網路的實務問題

  • 如何存取在 Docker 容器內執行的應用程式或服務?
  • 如何安全地連線或發現依賴的應用程式服務?
  • 如何在網路上保護在 Docker 容器中執行的應用程式?

本章將嘗試回答這些問題。首先,我們將討論 Docker 網路的內部工作原理,這應該可以讓您對目前的網路模型有很好的瞭解。然後,我們將研究一些實務範例,這些範例將展示如何在現實世界中使用 Docker 網路功能。

#### 圖表翻譯:

此圖展示了Docker 網路模型的架構,包括 IP 分配、網域名稱解析和容器或服務發現等主要元件。

#### 內容解密:

此圖表說明瞭 Docker 網路模型的主要元件,包括 IP 分配、網域名稱解析和容器或服務發現。這些元件共同工作,使 Docker 容器能夠在網路上進行通訊和協同工作。

Docker 網路基礎與實務應用

Docker 的網路模型設計簡潔卻功能強大。預設情況下,新建立的 Docker 容器會自動連線到內部的 Docker 網路,無需手動組態。使用者只需執行熟悉的 docker run <image> <cmd> 命令,容器啟動後即可在網路上存取。這種無縫體驗背後有著複雜的網路組態,值得探討。

Docker 網路基礎架構

當 Docker 守護程式(daemon)在主機上以預設組態啟動時,會建立一個 Linux 網路橋接裝置並命名為 docker0。該橋接裝置會被自動分配一個來自 RFC 1918 定義的私有 IP 範圍內的隨機 IP 位址和子網路。這個子網路定義了所有新建立容器將被分配 IP 位址的範圍。

關鍵網路元件與組態

  1. Linux 網路橋接裝置(docker0)

    • Docker 守護程式建立 docker0 橋接裝置。
    • 自動分配私有 IP 範圍內的 IP 位址和子網路。
  2. iptables 規則修改

    • Docker 守護程式修改主機上的 iptables 規則。
    • 建立特殊的 DOCKER 篩選鏈並插入到 FORWARD 鏈頂部。
    • 修改 iptables nat 表以啟用容器到外部網路的連線。
  3. 網路名稱空間與 veth 裝置

    • 為每個新容器建立新的網路名稱空間。
    • 生成一對 veth(Virtual Ethernet)裝置,這是一種特殊的 Linux 網路裝置,總是以成對形式出現,模擬網路管道。
    • 將一端 veth 裝置分配給容器網路名稱空間,另一端保留在主機的網路名稱空間中,並以 veth 字首隨機命名。
  4. IP 位址分配與路由組態

    • 將主機端的 veth 裝置加入 docker0 橋接裝置。
    • 為容器端的 veth 裝置分配 IP 位址。
    • 在主機路由表中插入新的網路路由,並啟用 IP 轉發功能。

程式碼範例:檢視 Docker 網路組態

# 檢視 docker0 網橋資訊
ip addr show docker0

# 檢視 iptables 規則
iptables -nvL

# 檢視網路名稱空間
ip netns list

內容解密:

上述命令用於檢查 Docker 網路組態的關鍵部分。ip addr show docker0 用於檢視 docker0 網橋的 IP 組態,iptables -nvL 用於檢查當前 iptables 規則,而 ip netns list 則列出目前系統中的網路名稱空間。

容器網路存取控制

預設情況下,Docker 容器位於私有網路中,無法直接從外部存取。若需從外部存取容器服務,需透過埠對映或使用 Docker 的連結功能。

自定義 iptables 設定

若不希望 Docker 修改 iptables 規則,可在啟動 Docker 守護程式時設定 --iptables=false。此時,需手動管理 iptables 規則和 IP 轉發設定。

# 設定 DOCKER_OPTS 環境變數
export DOCKER_OPTS="--iptables=false"

# 重啟 Docker 守護程式
systemctl restart docker

內容解密:

設定 --iptables=false 後,Docker 將不會修改 iptables 規則,使用者需自行管理容器的網路存取控制。這種方式提供了更高的自定義性,但也增加了管理複雜度。

IP 位址分配管理

在動態容器環境中,手動管理 IP 位址並不可行。Docker 的 IP 位址分配機制自動為容器分配 IP 位址,簡化了網路管理。

Docker 網路架構圖示

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Docker儲存驅動OverlayFS技術解析

package "Docker 架構" {
    actor "開發者" as dev

    package "Docker Engine" {
        component [Docker Daemon] as daemon
        component [Docker CLI] as cli
        component [REST API] as api
    }

    package "容器運行時" {
        component [containerd] as containerd
        component [runc] as runc
    }

    package "儲存" {
        database [Images] as images
        database [Volumes] as volumes
        database [Networks] as networks
    }

    cloud "Registry" as registry
}

dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置

@enduml

圖表翻譯: 此圖示展示了 Docker 守護程式如何建立 docker0 網橋、修改 iptables 規則,並為每個容器建立獨立的網路名稱空間和 veth 裝置對。veth 裝置對的一端連線到 docker0 網橋,另一端組態在容器的網路名稱空間中。

  1. 多主機網路:目前 Docker 主要支援單主機容器網路,未來可望支援跨多主機的容器通訊。
  2. 網路安全增強:加強容器的網路隔離和安全控制,例如使用更細粒度的網路策略。
  3. 效能最佳化:持續最佳化容器網路的效能,降低延遲和提升吞吐量。

透過不斷的最佳化和創新,Docker 網路技術將更好地服務於雲原生應用和微服務架構的需求。