裝置映射器儲存驅動程式(已棄用)

已棄用

Device Mapper 驅動程式已棄用,並在 Docker Engine v25.0 中移除。如果您正在使用 Device Mapper,則必須在升級到 Docker Engine v25.0 之前遷移到支援的儲存驅動程式。請閱讀Docker 儲存驅動程式頁面以了解支援的儲存驅動程式。

Device Mapper 是一個基於核心架構,它是 Linux 上許多進階磁碟區管理技術的基礎。Docker 的 devicemapper 儲存驅動程式利用此架構的精簡配置和快照功能來進行映像檔和容器管理。本文將 Device Mapper 儲存驅動程式稱為 devicemapper,將核心架構稱為*Device Mapper*。

對於支援的系統,Linux 核心包含 devicemapper 支援。但是,需要特定設定才能與 Docker 一起使用。

devicemapper 驅動程式使用專用於 Docker 的區塊裝置,並在區塊層級(而不是檔案層級)運作。可以透過將實體儲存新增到 Docker 主機來擴充這些裝置,而且它們的效能比在作業系統 (OS) 層級使用檔案系統更好。

先決條件

  • 在 CentOS、Fedora、SLES 15、Ubuntu、Debian 或 RHEL 上執行的 Docker Engine - Community 支援 devicemapper
  • devicemapper 需要安裝 lvm2device-mapper-persistent-data 套件。
  • 更改儲存驅動程式會導致您已建立的任何容器在本機系統上無法存取。使用 docker save 儲存容器,並將現有映像檔推送到 Docker Hub 或私有儲存庫,這樣您以後就不需要重新建立它們。

使用 devicemapper 儲存驅動程式設定 Docker

在遵循這些程序之前,您必須先滿足所有先決條件

設定 loop-lvm 模式進行測試

此設定僅適用於測試。loop-lvm 模式利用「迴圈」機制,允許讀取和寫入本機磁碟上的檔案,如同它們是實際的實體磁碟或區塊裝置一樣。但是,新增迴圈機制以及與作業系統檔案系統層的互動,表示 IO 作業可能會很慢且資源密集。使用迴圈裝置也可能導致競爭條件。但是,設定 loop-lvm 模式可以協助在嘗試啟用 direct-lvm 模式所需的更複雜設定之前,識別基本問題(例如缺少使用者空間套件、核心驅動程式等)。因此,loop-lvm 模式應該只用於在設定 direct-lvm 之前執行基本測試。

對於生產系統,請參閱設定 direct-lvm 模式進行生產

  1. 停止 Docker。

    $ sudo systemctl stop docker
    
  2. 編輯 /etc/docker/daemon.json。如果它尚不存在,請建立它。假設檔案是空的,請新增以下內容。

    {
      "storage-driver": "devicemapper"
    }

    daemon 參考文件中查看每個儲存驅動程式的suoyou儲存選項

    如果 daemon.json 檔案包含格式錯誤的 JSON,Docker 將不會啟動。

  3. 啟動 Docker。

    $ sudo systemctl start docker
    
  4. 確認 daemon 正在使用 devicemapper 儲存驅動程式。使用 docker info 命令並尋找 Storage Driver

    $ docker info
    
      Containers: 0
        Running: 0
        Paused: 0
        Stopped: 0
      Images: 0
      Server Version: 17.03.1-ce
      Storage Driver: devicemapper
      Pool Name: docker-202:1-8413957-pool
      Pool Blocksize: 65.54 kB
      Base Device Size: 10.74 GB
      Backing Filesystem: xfs
      Data file: /dev/loop0
      Metadata file: /dev/loop1
      Data Space Used: 11.8 MB
      Data Space Total: 107.4 GB
      Data Space Available: 7.44 GB
      Metadata Space Used: 581.6 KB
      Metadata Space Total: 2.147 GB
      Metadata Space Available: 2.147 GB
      Thin Pool Minimum Free Space: 10.74 GB
      Udev Sync Supported: true
      Deferred Removal Enabled: false
      Deferred Deletion Enabled: false
      Deferred Deleted Device Count: 0
      Data loop file: /var/lib/docker/devicemapper/data
      Metadata loop file: /var/lib/docker/devicemapper/metadata
      Library Version: 1.02.135-RHEL7 (2016-11-16)
    <...>
    

此主機正在以 loop-lvm 模式執行,生產系統不支援此模式。 資料迴圈檔案中繼資料迴圈檔案 位於 /var/lib/docker/devicemapper 下的檔案表示了這一點。這些是迴圈掛載的稀疏檔案。對於生產系統,請參閱 設定生產環境的 direct-lvm 模式

設定 direct-lvm 模式進行生產

使用 devicemapper 儲存驅動程式的生產主機必須使用 direct-lvm 模式。此模式使用區塊裝置來建立精簡池。這比使用迴圈裝置更快,更有效地使用系統資源,並且區塊裝置可以根據需要增長。但是,與 loop-lvm 模式相比,需要更多設定。

滿足 先決條件 後,請按照以下步驟設定 Docker 以在 direct-lvm 模式下使用 devicemapper 儲存驅動程式。

警告

更改儲存驅動程式會導致您已建立的任何容器在本機系統上無法存取。使用 docker save 儲存容器,並將現有映像檔推送到 Docker Hub 或私有儲存庫,這樣您以後就不需要重新建立它們。

允許 Docker 設定 direct-lvm 模式

Docker 可以為您管理區塊裝置,簡化 direct-lvm 模式的設定。這僅適用於全新的 Docker 設定。 您只能使用單個區塊裝置。如果您需要使用多個區塊裝置,請改為 手動設定 direct-lvm 模式。以下新的設定選項可用

選項說明是否必要?預設值範例
dm.directlvm_device要設定 direct-lvm 的區塊裝置路徑。dm.directlvm_device="/dev/xvdf"
dm.thinp_percent要從傳入的區塊裝置中使用的儲存空間百分比。9595

dm.thinp_percent=95

dm.thinp_metapercent要從傳入的區塊裝置中使用的中繼資料儲存空間百分比。11

dm.thinp_metapercent=1

dm.thinp_autoextend_thresholdlvm 應自動擴展精簡池的閾值,以總儲存空間的百分比表示。8080

dm.thinp_autoextend_threshold=80

dm.thinp_autoextend_percent觸發自動擴展時,精簡池增加的百分比。2020

dm.thinp_autoextend_percent=20

dm.directlvm_device_force即使區塊裝置上已存在檔案系統,是否仍要格式化該區塊裝置。如果設定為 false 且存在檔案系統,則會記錄錯誤並保留檔案系統。falsedm.directlvm_device_force=true

編輯 daemon.json 檔案並設定適當的選項,然後重新啟動 Docker 以使變更生效。以下 daemon.json 設定會設定上表中的所有選項。

{
  "storage-driver": "devicemapper",
  "storage-opts": [
    "dm.directlvm_device=/dev/xdf",
    "dm.thinp_percent=95",
    "dm.thinp_metapercent=1",
    "dm.thinp_autoextend_threshold=80",
    "dm.thinp_autoextend_percent=20",
    "dm.directlvm_device_force=false"
  ]
}

daemon 參考文件中查看每個儲存驅動程式的suoyou儲存選項

重新啟動 Docker 以使變更生效。 Docker 會呼叫命令來為您設定區塊裝置。

警告

Docker 為您準備好區塊裝置後,不支援變更這些值,並且會導致錯誤。

您仍然需要 執行定期維護任務

手動設定 direct-lvm 模式

以下程序建立一個設定為精簡池的邏輯磁區,以用作儲存池的後盾。它假設您在 /dev/xvdf 上有一個備用區塊裝置,其中有足夠的可用空間來完成任務。裝置識別碼和磁區大小在您的環境中可能不同,您應該在整個程序中替換您自己的值。該程序還假設 Docker daemon 處於 停止 狀態。

  1. 識別您要使用的區塊裝置。該裝置位於 /dev/ 下(例如 /dev/xvdf),並且需要足夠的可用空間來儲存主機執行的 workloads 的映像檔和容器層。固態硬碟 (SSD) 是理想的選擇。

  2. 停止 Docker。

    $ sudo systemctl stop docker
    
  3. 安裝以下套件

    • RHEL / CentOS: device-mapper-persistent-datalvm2 以及所有相依性

    • Ubuntu / Debian / SLES 15: thin-provisioning-toolslvm2 以及所有相依性

  4. 使用 pvcreate 命令在步驟 1 中的區塊裝置上建立一個實體磁區。將您的裝置名稱替換為 /dev/xvdf

    警告

    接下來的幾個步驟具有破壞性,因此請確保您已指定正確的裝置。

    $ sudo pvcreate /dev/xvdf
    
    Physical volume "/dev/xvdf" successfully created.
    
  5. 使用 vgcreate 命令在同一個裝置上建立一個 docker 磁區群組。

    $ sudo vgcreate docker /dev/xvdf
    
    Volume group "docker" successfully created
    
  6. 使用 lvcreate 命令建立兩個名為 thinpoolthinpoolmeta 的邏輯磁區。最後一個參數指定允許自動擴展資料或中繼資料的可用空間量,作為空間不足時的臨時權宜之計。以下是建議值。

    $ sudo lvcreate --wipesignatures y -n thinpool docker -l 95%VG
    
    Logical volume "thinpool" created.
    
    $ sudo lvcreate --wipesignatures y -n thinpoolmeta docker -l 1%VG
    
    Logical volume "thinpoolmeta" created.
    
  7. 使用 lvconvert 命令將磁區轉換為精簡池和精簡池中繼資料的儲存位置。

    $ sudo lvconvert -y \
    --zero n \
    -c 512K \
    --thinpool docker/thinpool \
    --poolmetadata docker/thinpoolmeta
    
    WARNING: Converting logical volume docker/thinpool and docker/thinpoolmeta to
    thin pool's data and metadata volumes with metadata wiping.
    THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.)
    Converted docker/thinpool to thin pool.
    
  8. 透過 lvm 設定檔設定精簡池的自動擴展。

    $ sudo vi /etc/lvm/profile/docker-thinpool.profile
    
  9. 指定 thin_pool_autoextend_thresholdthin_pool_autoextend_percent 值。

    thin_pool_autoextend_thresholdlvm 嘗試自動擴展可用空間之前使用的空間百分比(100 = 禁用,不建議)。

    thin_pool_autoextend_percent 是自動擴展時要新增到裝置的空間量(0 = 禁用)。

    以下範例在磁碟使用率達到 80% 時增加 20% 的容量。

    activation {
      thin_pool_autoextend_threshold=80
      thin_pool_autoextend_percent=20
    }

    儲存檔案。

  10. 使用 lvchange 命令套用 LVM 設定檔。

    $ sudo lvchange --metadataprofile docker-thinpool docker/thinpool
    
    Logical volume docker/thinpool changed.
    
  11. 確保已啟用邏輯磁區的監控。

    $ sudo lvs -o+seg_monitor
    
    LV       VG     Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert Monitor
    thinpool docker twi-a-t--- 95.00g             0.00   0.01                             not monitored
    

    如果 `Monitor` 欄位中的輸出如上所示,報告磁區 `未受監控`,則需要明確啟用監控。如果沒有此步驟,則無論套用設定檔中的任何設定為何,邏輯磁區都不會自動擴展。

    $ sudo lvchange --monitor y docker/thinpool
    

    再次執行 `sudo lvs -o+seg_monitor` 命令,再次確認監控現已啟用。 `Monitor` 欄位現在應報告邏輯磁區正受到 `監控`。

  12. 如果您以前在此主機上執行過 Docker,或者如果 /var/lib/docker/ 存在,請將其移開,以便 Docker 可以使用新的 LVM 池來儲存映像檔和容器的內容。

    $ sudo su -
    # mkdir /var/lib/docker.bk
    # mv /var/lib/docker/* /var/lib/docker.bk
    # exit
    

    如果以下任何步驟失敗並且您需要還原,您可以移除 /var/lib/docker 並將其替換為 /var/lib/docker.bk

  13. 編輯 /etc/docker/daemon.json 並設定 devicemapper 儲存驅動程式所需的選項。如果檔案先前為空,則它現在應包含以下內容

    {
        "storage-driver": "devicemapper",
        "storage-opts": [
        "dm.thinpooldev=/dev/mapper/docker-thinpool",
        "dm.use_deferred_removal=true",
        "dm.use_deferred_deletion=true"
        ]
    }
  14. 啟動 Docker。

    systemd:

    $ sudo systemctl start docker
    

    服務:

    $ sudo service docker start
    
  15. 使用 docker info 驗證 Docker 是否正在使用新的設定。

    $ docker info
    
    Containers: 0
     Running: 0
     Paused: 0
     Stopped: 0
    Images: 0
    Server Version: 17.03.1-ce
    Storage Driver: devicemapper
     Pool Name: docker-thinpool
     Pool Blocksize: 524.3 kB
     Base Device Size: 10.74 GB
     Backing Filesystem: xfs
     Data file:
     Metadata file:
     Data Space Used: 19.92 MB
     Data Space Total: 102 GB
     Data Space Available: 102 GB
     Metadata Space Used: 147.5 kB
     Metadata Space Total: 1.07 GB
     Metadata Space Available: 1.069 GB
     Thin Pool Minimum Free Space: 10.2 GB
     Udev Sync Supported: true
     Deferred Removal Enabled: true
     Deferred Deletion Enabled: true
     Deferred Deleted Device Count: 0
     Library Version: 1.02.135-RHEL7 (2016-11-16)
    <...>
    

    如果 Docker 設定正確,則 資料檔案中繼資料檔案 為空白,且池名稱為 docker-thinpool

  16. 確認設定正確後,您可以移除包含先前設定的 /var/lib/docker.bk 目錄。

    $ sudo rm -rf /var/lib/docker.bk
    

管理 devicemapper

監控精簡池

不要僅依賴 LVM 自動擴展。磁區群組會自動擴展,但磁區仍然可能會滿。您可以使用 lvslvs -a 監控磁區上的可用空間。請考慮在作業系統層級使用監控工具,例如 Nagios。

要檢視 LVM 記錄,您可以使用 journalctl

$ sudo journalctl -fu dm-event.service

如果您在使用 thin pool 時遇到重複發生的問題,您可以設定儲存選項 dm.min_free_space 為一個百分比值,並將其寫入 /etc/docker/daemon.json 檔案中。例如,將其設定為 10 可以確保當剩餘空間等於或接近 10% 時,操作會失敗並顯示警告。請參閱 Engine daemon 參考文件中的儲存驅動程式選項

增加執行中裝置的容量

您可以在執行中的 thin-pool 裝置上增加池的容量。如果資料的邏輯磁碟區已滿,且磁碟區群組的容量也已滿,這將很有用。具體步驟取決於您使用的是 loop-lvm thin pool 還是 direct-lvm thin pool

調整 loop-lvm thin pool 的大小

調整 loop-lvm thin pool 大小的最簡單方法是 使用 device_tool 工具,但您也可以 使用作業系統工具

使用 device_tool 工具

moby/moby Github 儲存庫中提供了一個名為 device_tool.go 的社群貢獻腳本。您可以使用此工具來調整 loop-lvm thin pool 的大小,避免上述冗長的流程。此工具不保證一定能正常運作,但您應該只在非生產環境系統上使用 loop-lvm

如果您不想使用 device_tool,您可以 手動調整 thin pool 的大小

  1. 要使用此工具,請複製 Github 儲存庫,切換到 contrib/docker-device-tool 目錄,並按照 README.md 中的說明編譯此工具。

  2. 使用此工具。以下範例將 thin pool 的大小調整為 200GB。

    $ ./device_tool resize 200GB
    
使用作業系統工具

如果您不想 使用 device-tool 工具,您可以使用以下步驟手動調整 loop-lvm thin pool 的大小。

loop-lvm 模式中,會使用一個迴圈裝置來儲存資料,另一個迴圈裝置則用於儲存中繼資料。loop-lvm 模式僅支援測試用途,因為它在效能和穩定性方面存在顯著的缺點。

如果您使用的是 loop-lvm 模式,docker info 的輸出會顯示 Data loop fileMetadata loop file 的檔案路徑。

$ docker info |grep 'loop file'

 Data loop file: /var/lib/docker/devicemapper/data
 Metadata loop file: /var/lib/docker/devicemapper/metadata

請按照以下步驟增加 thin pool 的大小。在本範例中,thin pool 的大小為 100 GB,並將其增加到 200 GB。

  1. 列出裝置的大小。

    $ sudo ls -lh /var/lib/docker/devicemapper/
    
    total 1175492
    -rw------- 1 root root 100G Mar 30 05:22 data
    -rw------- 1 root root 2.0G Mar 31 11:17 metadata
    
  2. 使用 truncate 命令將 data 檔案的大小增加到 200 G,該命令可用於增加**或**減少檔案的大小。請注意,減少檔案大小是一個破壞性操作。

    $ sudo truncate -s 200G /var/lib/docker/devicemapper/data
    
  3. 驗證檔案大小已更改。

    $ sudo ls -lh /var/lib/docker/devicemapper/
    
    total 1.2G
    -rw------- 1 root root 200G Apr 14 08:47 data
    -rw------- 1 root root 2.0G Apr 19 13:27 metadata
    
  4. 迴圈檔案已在磁碟上更改,但記憶體中尚未更改。以 GB 為單位列出記憶體中迴圈裝置的大小。重新載入它,然後再次列出大小。重新載入後,大小為 200 GB。

    $ echo $[ $(sudo blockdev --getsize64 /dev/loop0) / 1024 / 1024 / 1024 ]
    
    100
    
    $ sudo losetup -c /dev/loop0
    
    $ echo $[ $(sudo blockdev --getsize64 /dev/loop0) / 1024 / 1024 / 1024 ]
    
    200
    
  5. 重新載入 devicemapper thin pool。

    a. 首先取得池的名稱。池名稱是第一個欄位,以 : 分隔。此命令會將其擷取出來。

    $ sudo dmsetup status | grep ' thin-pool ' | awk -F ': ' {'print $1'}
    docker-8:1-123141-pool
    

    b. 傾印 thin pool 的 device mapper 表格。

    $ sudo dmsetup table docker-8:1-123141-pool
    0 209715200 thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing
    

    c. 使用輸出的第二個欄位計算 thin pool 的總磁區數。該數字以 512-k 磁區表示。一個 100G 的檔案有 209715200 個 512-k 磁區。如果您將這個數字加倍到 200G,您將得到 419430400 個 512-k 磁區。

    d. 使用以下三個 dmsetup 命令,使用新的磁區數重新載入 thin pool。

    $ sudo dmsetup suspend docker-8:1-123141-pool
    $ sudo dmsetup reload docker-8:1-123141-pool --table '0 419430400 thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing'
    $ sudo dmsetup resume docker-8:1-123141-pool
    

調整 direct-lvm thin pool 的大小

要擴展 direct-lvm thin pool,您需要先將一個新的區塊裝置連接到 Docker 主機,並記下核心分配給它的名稱。在本範例中,新的區塊裝置是 /dev/xvdg

請按照以下步驟擴展 direct-lvm thin pool,並根據您的情況替換您的區塊裝置和其他參數。

  1. 收集有關您的磁碟區群組的資訊。

    使用 pvdisplay 命令查找 thin pool 目前正在使用的實體區塊裝置,以及磁碟區群組的名稱。

    $ sudo pvdisplay |grep 'VG Name'
    
    PV Name               /dev/xvdf
    VG Name               docker
    

    在以下步驟中,請根據需要替換您的區塊裝置或磁碟區群組名稱。

  2. 使用 vgextend 命令搭配上一步驟中的 VG Name 以及**新的**區塊裝置的名稱來擴展磁碟區群組。

    $ sudo vgextend docker /dev/xvdg
    
    Physical volume "/dev/xvdg" successfully created.
    Volume group "docker" successfully extended
    
  3. 擴展 docker/thinpool 邏輯磁碟區。此命令會立即使用 100% 的磁碟區,而不會自動擴展。要擴展中繼資料 thinpool,請改用 docker/thinpool_tmeta

    $ sudo lvextend -l+100%FREE -n docker/thinpool
    
    Size of logical volume docker/thinpool_tdata changed from 95.00 GiB (24319 extents) to 198.00 GiB (50688 extents).
    Logical volume docker/thinpool_tdata successfully resized.
    
  4. 使用 docker info 輸出中的 Data Space Available 欄位驗證新的 thin pool 大小。如果您改為擴展 docker/thinpool_tmeta 邏輯磁碟區,請尋找 Metadata Space Available

    Storage Driver: devicemapper
     Pool Name: docker-thinpool
     Pool Blocksize: 524.3 kB
     Base Device Size: 10.74 GB
     Backing Filesystem: xfs
     Data file:
     Metadata file:
     Data Space Used: 212.3 MB
     Data Space Total: 212.6 GB
     Data Space Available: 212.4 GB
     Metadata Space Used: 286.7 kB
     Metadata Space Total: 1.07 GB
     Metadata Space Available: 1.069 GB
    <...>

重新啟動後啟用 devicemapper

如果您重新啟動主機後發現 docker 服務無法啟動,請尋找錯誤訊息「Non existing device」。您需要使用以下命令重新啟用邏輯磁碟區。

$ sudo lvchange -ay docker/thinpool

devicemapper 儲存驅動程式的運作方式

警告

請勿直接操作 /var/lib/docker/ 中的任何檔案或目錄。這些檔案和目錄由 Docker 管理。

使用 lsblk 命令從作業系統的角度查看裝置及其池。

$ sudo lsblk

NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda                    202:0    0    8G  0 disk
└─xvda1                 202:1    0    8G  0 part /
xvdf                    202:80   0  100G  0 disk
├─docker-thinpool_tmeta 253:0    0 1020M  0 lvm
│ └─docker-thinpool     253:2    0   95G  0 lvm
└─docker-thinpool_tdata 253:1    0   95G  0 lvm
  └─docker-thinpool     253:2    0   95G  0 lvm

使用 mount 命令查看 Docker 正在使用的掛載點。

$ mount |grep devicemapper
/dev/xvda1 on /var/lib/docker/devicemapper type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

當您使用 devicemapper 時,Docker 會將映像檔和層內容儲存在 thinpool 中,並透過將它們掛載在 /var/lib/docker/devicemapper/ 的子目錄下來將它們公開給容器。

磁碟上的映像檔和容器層

/var/lib/docker/devicemapper/metadata/ 目錄包含關於 Devicemapper 設定本身以及現有每個映像檔和容器層的中繼資料。devicemapper 儲存驅動程式使用快照,這些中繼資料包含關於這些快照的資訊。這些檔案採用 JSON 格式。

/var/lib/docker/devicemapper/mnt/ 目錄包含現有每個映像檔和容器層的掛載點。映像檔層掛載點是空的,但容器的掛載點會顯示容器檔案系統在容器內部的樣子。

映像檔分層和共用

devicemapper 儲存驅動程式使用專用的區塊裝置而不是格式化的檔案系統,並在區塊層級操作檔案,以便在寫入時複製 (CoW) 作業期間達到最佳效能。

快照

devicemapper 的另一個特性是它使用快照(有時也稱為*thin devices* 或 *virtual devices*),這些快照將每一層中引入的差異儲存為非常小、輕量級的 thin pool。快照提供了許多好處:

  • 除非可寫入,否則容器之間共用的層只會在磁碟上儲存一次。例如,如果您有 10 個不同的映像檔,它們都基於 alpine,則 alpine 映像檔及其所有父映像檔只會在磁碟上各儲存一次。

  • 快照是寫入時複製 (CoW) 策略的一種實作方式。這表示只有當容器修改或刪除特定檔案或目錄時,才會將其複製到容器的可寫入層。

  • 由於 devicemapper 在區塊層級運作,因此可寫入層中的多個區塊可以同時修改。

  • 可以使用標準作業系統層級的備份工具來備份快照。只需複製 /var/lib/docker/devicemapper/ 即可。

Devicemapper 工作流程

當您使用 devicemapper 儲存驅動程式啟動 Docker 時,所有與映像檔和容器層相關的物件都會儲存在 /var/lib/docker/devicemapper/ 中,該目錄由一個或多個區塊級裝置支援,可以是迴圈裝置(僅用於測試)或實體磁碟。

  • 基礎裝置 是最低階的物件。這就是精簡池本身。您可以使用 docker info 檢查它。它包含一個檔案系統。這個基礎裝置是每個映像檔和容器層的起始點。基礎裝置是 Device Mapper 的實作細節,而不是 Docker 層。

  • 關於基礎裝置和每個映像檔或容器層的後設資料以 JSON 格式儲存在 /var/lib/docker/devicemapper/metadata/ 中。這些層是寫入時複製的快照,這表示它們在與其父層不同之前都是空的。

  • 每個容器的可寫入層都掛載在 /var/lib/docker/devicemapper/mnt/ 中的掛載點上。每個唯讀映像檔層和每個已停止的容器都存在一個空目錄。

每個映像檔層都是其下方層的快照。每個映像檔的最底層是存在於池中的基礎裝置的快照。當您執行容器時,它是容器所基於的映像檔的快照。以下範例顯示一個 Docker 主機,其中執行兩個容器。第一個是 ubuntu 容器,第二個是 busybox 容器。

Ubuntu and busybox image layers

容器讀寫如何與 devicemapper 配合使用

讀取檔案

使用 devicemapper 時,讀取操作發生在區塊級別。下圖顯示了在範例容器中讀取單個區塊 (0x44f) 的高階流程。

Reading a block with devicemapper

應用程式在容器中發出讀取區塊 0x44f 的請求。由於容器是映像檔的精簡快照,它沒有該區塊,但它有一個指向最近父映像檔上存在該區塊的指標,它從那裡讀取該區塊。該區塊現在存在於容器的記憶體中。

寫入檔案

寫入新檔案:使用 devicemapper 驅動程式,透過 *依需求配置* 操作將新資料寫入容器。新檔案的每個區塊都配置在容器的可寫入層中,並且區塊會寫入到那裡。

更新現有檔案:從存在該檔案的最近層讀取檔案的相關區塊。當容器寫入檔案時,只有修改過的區塊會寫入到容器的可寫入層。

刪除檔案或目錄:當您在容器的可寫入層中刪除檔案或目錄,或者當映像檔層刪除其父層中存在的檔案時,devicemapper 儲存驅動程式會攔截對該檔案或目錄的進一步讀取嘗試,並回應該檔案或目錄不存在。

寫入然後刪除檔案:如果容器寫入檔案然後刪除該檔案,則所有這些操作都發生在容器的可寫入層中。在這種情況下,如果您使用的是 direct-lvm,則會釋放這些區塊。如果您使用 loop-lvm,則可能不會釋放這些區塊。這是不要在生產環境中使用 loop-lvm 的另一個原因。

Device Mapper 和 Docker 效能

  • 依需求配置 的效能影響:

    devicemapper 儲存驅動程式使用 依需求配置 操作將精簡池中的新區塊配置到容器的可寫入層。每個區塊大小為 64KB,因此這是寫入使用的最小空間量。

  • 寫入時複製的效能影響:容器第一次修改特定區塊時,該區塊會寫入到容器的可寫入層。由於這些寫入發生在區塊級別而不是檔案級別,因此效能影響最小。但是,寫入大量區塊仍然會對效能產生負面影響,並且在此情況下,devicemapper 儲存驅動程式的效能實際上可能比其他儲存驅動程式差。對於寫入密集型工作負載,您應該使用資料卷,這完全繞過了儲存驅動程式。

效能最佳實務

使用 devicemapper 儲存驅動程式時,請記住以下事項以最大限度地提高效能。

  • 使用 direct-lvmloop-lvm 模式效能不佳,絕不應在生產環境中使用。

  • 使用快速儲存裝置:固態硬碟 (SSD) 比傳統硬碟提供更快的讀寫速度。

  • 記憶體使用量devicemapper 比其他一些儲存驅動程式使用更多的記憶體。每個啟動的容器都會將其檔案的一個或多個副本載入到記憶體中,具體取決於同時修改同一檔案的區塊數量。由於記憶體壓力,devicemapper 儲存驅動程式可能不適合高密度使用案例中的某些工作負載。

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

    注意

    當使用 devicemapperjson-file 日誌驅動程式時,容器產生的日誌檔仍然儲存在 Docker 的資料根目錄中,預設為 /var/lib/docker。如果您的容器產生大量日誌訊息,這可能會導致磁碟使用量增加或因磁碟已滿而無法管理您的系統。您可以設定日誌驅動程式 將容器日誌儲存在外部。