Device Mapper 儲存驅動程式 (已棄用)

已棄用

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) 級別使用檔案系統。

先決條件

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

使用 devicemapper 儲存驅動配置 Docker

在執行這些步驟之前,您必須首先滿足所有先決條件

配置 loop-lvm 模式進行測試

此配置僅適用於測試。loop-lvm 模式使用一種“迴環”機制,允許像讀寫實際物理磁碟或塊裝置一樣讀寫本地磁碟上的檔案。然而,迴環機制的增加以及與作業系統檔案系統層的互動,意味著 I/O 操作可能會很慢且資源密集。使用迴環裝置還可能引入競爭條件。但是,設定 loop-lvm 模式有助於在嘗試更復雜的設定(啟用 direct-lvm 模式所需)之前識別基本問題(例如缺少使用者空間軟體包、核心驅動程式等)。因此,loop-lvm 模式只應用於在配置 direct-lvm 之前進行初步測試。

對於生產系統,請參閱配置直接 LVM 模式用於生產

  1. 停止 Docker。

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

    {
      "storage-driver": "devicemapper"
    }

    請參閱守護程序參考文件中每個儲存驅動的所有儲存選項。

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

  3. 啟動 Docker。

    $ sudo systemctl start docker
    
  4. 驗證守護程序是否正在使用 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 模式下執行,該模式受生產系統支援。這由 Data loop fileMetadata loop file 位於 /var/lib/docker/devicemapper 下的檔案中這一事實表示。這些是環回掛載的稀疏檔案。對於生產系統,請參閱配置直接 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從傳入的塊裝置中用於儲存的空間百分比。95dm.thinp_percent=95
dm.thinp_metapercent從傳入的塊裝置中用於元資料儲存的空間百分比。1dm.thinp_metapercent=1
dm.thinp_autoextend_thresholdLVM 自動擴充套件精簡池的閾值,以總儲存空間的百分比表示。80dm.thinp_autoextend_threshold=80
dm.thinp_autoextend_percent觸發自動擴充套件時精簡池增加的百分比。20dm.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"
  ]
}

請參閱守護程序參考文件中每個儲存驅動的所有儲存選項。

重啟 Docker 以使更改生效。Docker 將呼叫命令為您配置塊裝置。

警告

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

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

手動配置 direct-lvm 模式

以下過程建立一個配置為精簡池的邏輯卷,用作儲存池的後端。它假設您在 /dev/xvdf 上有一個備用塊裝置,其中有足夠的可用空間來完成任務。您的環境中的裝置識別符號和卷大小可能不同,您應該在整個過程中替換您自己的值。該過程還假設 Docker 守護程式處於 stopped 狀態。

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

  2. 停止 Docker。

    $ sudo systemctl stop docker
    
  3. 安裝以下軟體包

    • RHEL / CentOS: device-mapper-persistent-data, lvm2, 以及所有依賴項

    • Ubuntu / Debian / SLES 15: thin-provisioning-tools, lvm2, 以及所有依賴項

  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 列中的輸出如上所示報告卷 not monitored,則需要明確啟用監控。如果沒有此步驟,無論應用配置檔案中的任何設定如何,邏輯卷的自動擴充套件都不會發生。

    $ sudo lvchange --monitor y docker/thinpool
    

    透過再次執行 sudo lvs -o+seg_monitor 命令,仔細檢查監控是否已啟用。現在,Monitor 列應報告邏輯卷正在被 monitored

  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 配置正確,Data fileMetadata file 將為空,並且池名稱為 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

如果您反覆遇到精簡池問題,可以在 /etc/docker/daemon.json 中將儲存選項 dm.min_free_space 設定為一個值(表示百分比)。例如,將其設定為 10 可確保當可用空間達到或接近 10% 時,操作將失敗併發出警告。有關詳情,請參閱Engine 守護程式參考中的儲存驅動程式選項

增加正在執行裝置的容量

您可以在正在執行的精簡池裝置上增加池的容量。當資料邏輯卷已滿且卷組已達到最大容量時,這非常有用。具體過程取決於您使用的是loop-lvm 精簡池還是direct-lvm 精簡池

調整 loop-lvm 精簡池的大小

調整 loop-lvm 精簡池大小最簡單的方法是使用 device_tool 實用程式,但您也可以改用作業系統實用程式

使用 device_tool 實用程式

moby/moby Github 倉庫中提供了一個社群貢獻的指令碼 device_tool.go。您可以使用此工具調整 loop-lvm 精簡池的大小,避免上述漫長的過程。不保證此工具有效,但您只應在非生產系統上使用 loop-lvm

如果您不想使用 device_tool,則可以手動調整精簡池大小

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

  2. 使用該工具。以下示例將精簡池大小調整為 200GB。

    $ ./device_tool resize 200GB
    
使用作業系統實用程式

如果您不想使用 device-tool 實用程式,您可以使用以下過程手動調整 loop-lvm 精簡池的大小。

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

按照以下步驟增加精簡池的大小。在此示例中,精簡池為 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 精簡池。

    a. 首先獲取池名稱。池名稱是第一個欄位,由 : 分隔。此命令會提取它。

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

    b. 轉儲精簡池的裝置對映器表。

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

    c. 使用輸出的第二個欄位計算精簡池的總扇區數。該數字以 512k 扇區表示。一個 100G 檔案有 209715200 個 512k 扇區。如果您將此數字翻倍到 200G,您將得到 419430400 個 512k 扇區。

    d. 使用以下三個 dmsetup 命令,以新的扇區號重新載入精簡池。

    $ 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 精簡池的大小

要擴充套件 direct-lvm 精簡池,您需要首先將新的塊裝置連線到 Docker 主機,並記下核心分配給它的名稱。在此示例中,新的塊裝置是 /dev/xvdg

按照此過程擴充套件 direct-lvm 精簡池,根據您的情況替換您的塊裝置和其他引數。

  1. 收集有關您的卷組的資訊。

    使用 pvdisplay 命令查詢您的精簡池當前正在使用的物理塊裝置以及卷組的名稱。

    $ 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% 的卷,無需自動擴充套件。若要改為擴充套件元資料精簡池,請使用 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 欄位驗證新的精簡池大小。如果您擴充套件的是 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 將映象和層內容儲存在精簡池中,並透過將其掛載在 /var/lib/docker/devicemapper/ 的子目錄下,將其暴露給容器。

磁碟上的映象和容器層

/var/lib/docker/devicemapper/metadata/ 目錄包含有關 Devicemapper 配置本身以及每個存在的映象和容器層的元資料。devicemapper 儲存驅動程式使用快照,此元資料包括有關這些快照的資訊。這些檔案是 JSON 格式的。

/var/lib/docker/devicemapper/mnt/ 目錄包含每個存在的映象和容器層的掛載點。映象層掛載點為空,但容器的掛載點顯示容器的檔案系統,就像它在容器內部出現一樣。

映象分層與共享

devicemapper 儲存驅動程式使用專用塊裝置而不是格式化的檔案系統,並在塊級別操作檔案,以在寫時複製 (CoW) 操作期間實現最大效能。

快照

devicemapper 的另一個特性是其使用快照(有時也稱為精簡裝置虛擬裝置),它將每個層中引入的差異儲存為非常小、輕量級的精簡池。快照提供了許多好處:

  • 容器之間共享的層僅在磁碟上儲存一次,除非它們是可寫的。例如,如果您有 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 儲存驅動程式使用 allocate-on-demand 操作從精簡池中分配新的塊到容器的可寫層。每個塊為 64KB,因此這是用於寫入的最小空間量。

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

效能最佳實踐

使用 devicemapper 儲存驅動程式時,請記住以下事項以最大化效能。

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

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

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

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

    注意

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