docker檔案系統分層儲存原理

nice_xm發表於2021-05-07

一,前言

眾所周知,docker映象技術的基礎是聯合檔案系統(UnionFS),其檔案系統是分層的,那它的分層機制是什麼樣的呢?共分為幾種層呢?又是怎麼工作的呢?

目前docker支援的聯合檔案系統有很多種,包括:AUFS、overlay、overlay2、DeviceMapper、VSF等

Linux 中各發行版實現的 UnionFS 各不相同,所以docker在不同 linux 發行版中使用的也不同。通過docker info 命令可以檢視當前系統所使用哪種 UnionFS,常見的幾種發行版使用如下:

CentOS, Storage Driver: overlay2、overlay
debain, Storage Driver: aufs
RedHat, Storage Driver: devicemapper

二,介紹

下面我們就以Centos發行版的overlay2檔案系統進行介紹,其實不管是什麼發行版,其原理都如出一轍。

先來看張圖:

從上述圖中可以看到三個層結構,即lowerdir、upperdir、merged層

對應的,使用docker inspect [容器ID]就可以看到這幾個層所在的位置

"GraphDriver": {
            "Name": "overlay2",
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/45abab78c6fd022d9ce132a0fb995f9e91bc0a807ccc73e2461fce6c9b68b250/root",
                "MergedDir": "/var/lib/docker/overlay2/dc838cbc7d903a4bfd6bd0280a6910c063f2d1f03439e917ebc773fccc377402/merged",
                "UpperDir": "/var/lib/docker/overlay2/dc838cbc7d903a4bfd6bd0280a6910c063f2d1f03439e917ebc773fccc377402/upper",
                "WorkDir": "/var/lib/docker/overlay2/dc838cbc7d903a4bfd6bd0280a6910c063f2d1f03439e917ebc773fccc377402/work"
            }
        },

1、lowerdir層:

其中lowerdir是隻讀的映象層(image layer),其中就包含bootfs/rootfs層,bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引導載入kernel,當boot成功 kernel 被載入到記憶體中,bootfs就被umount了,rootfs(root file system)包含的就是典型Linux系統中的/dev、/proc、/bin、/etc等標準目錄。

lowerdir是可以分很多層的,除了bootfs/rootfs層以外,還可以通過Dockerfile建立很多image層,構建過程如下:

Dockerfile中每一個指令都會生成一個新的image層,如上圖所示。

當FROM時就已經生成了bootfs/rootfs層,也就是kernel和base層。

2、upperdir層

upperdir層是lowerdir的上一層,只有這一層可讀可寫的,其實就是Container層,在啟動一個容器的時候會在最後的image層的上一層自動建立,所有對容器資料的更改都會發生在這一層。

3、merged層

merged層就是聯合掛載層,也就是給使用者暴露的統一視覺,將image層和container層結合,就如最上邊的圖中描述一致,同一檔案,在此層會展示離它最近的層級裡的檔案內容,或者可以理解為,只要container層中有此檔案,便展示container層中的檔案內容,若container層中沒有,則展示image層中的。

三,聯合掛載系統的工作原理

1、讀:

如果檔案在upperdir(容器)層,直接讀取檔案;

如果檔案不在upperdir(容器)層,則從映象層(lowerdir)讀取;

2、寫:

首次寫入:如果upperdir中不存在,overlay和overlay2執行copy_up操作,把檔案從lowdir拷貝到upperdir中,由於overlayfs是檔案級別的(即使只有很少的一點修改,也會產生copy_up的動作),後續對同一檔案的再次寫入操作將對已經複製到容器層的檔案副本進行修改,這也就是嚐嚐說的寫時複製(copy-on-write)。

刪除檔案或目錄:當檔案被刪除時,在容器層(upperdir)建立whiteout檔案,映象層(lowerdir)的檔案是不會被刪除的,因為它們是隻讀的,但without檔案會阻止它們顯示,當目錄被刪除時,在容器層(upperdir)一個不透明的目錄,這個和上邊的whiteout的原理一樣,組織使用者繼續訪問,image層不會發生改變

3、注意事項

  1. copy_up操作只發生在檔案首次寫入,以後都是隻修改副本,
  2. overlayfs只適用兩層目錄,,相比於比AUFS,查詢搜尋都更快。
  3. 容器層的檔案刪除只是一個“障眼法”,是靠whiteout檔案將其遮擋,image層並沒有刪除,這也就是為什麼使用docker commit 提交儲存的映象會越來越大,無論在容器層怎麼刪除資料,image層都不會改變。

4、容器整體構成圖

此圖中沒有展現聯合掛載層

四,docker與VM的對比

帶著問題看事物,docker容器為什麼啟動這麼快呢???

先來看一張docker與VM的對比圖:

可以清楚的看到,VM比docker多了Hypervisor 和 Guest OS的過程,也正是省略了這些過程使docker技高一籌,問題又來了,為什麼docker可以省略這些過程呢?

  • Hypervisor:主要作用是實現硬體資源虛擬化;因為docker容器上程式直接使用的都是物理機的硬體資源,所以不需要資源虛擬化的過程,也因此在CPU、記憶體利用率上docker將會在效率上明顯提高

  • Guest OS:主要作用載入作業系統核心;因為docker利用的是宿主機的核心,所以在啟動一個容器時,不需要像VM一樣重新載入一個作業系統核心,也因此大大節約了啟動時間。

以下是官網提供的容器啟動過程圖:

相關文章