Docker Storage Driver:儲存驅動
每個Docker容器都有一個本地儲存空間,用於儲存層疊的映象層(Image Layer)以及掛載的容器檔案系統。
預設情況下,容器的所有讀寫操作都發生在其映象層上或掛載的檔案系統中,所以儲存是每個容器的效能和穩定性不可或缺的一個環節。
以往,本地儲存是通過儲存驅動(Storage Driver)進行管理的,有時候也被稱為 Graph Driver 或者 GraphDriver。
雖然儲存驅動在上層抽象設計中都採用了棧式映象層儲存和寫時複製(Copy-on-Write)的設計思想,但是 Docker 在 Linux 底層支援幾種不同的儲存驅動的具體實現,每一種實現方式都採用不同方法實現了映象層和寫時複製。
雖然底層實現的差異不影響使用者與 Docker 之間的互動,但是對 Docker 的效能和穩定性至關重要。
在 Linux 上,Docker 可選擇的一些儲存驅動包括 AUFS(最原始也是最老的)、Overlay2(可能是未來的最佳選擇)、Device Mapper、Btrfs 和 ZFS。
Docker 在 Windows 作業系統上只支援一種儲存驅動,即 Windows Filter。
儲存驅動的選擇是節點級別的。這意味著每個 Docker 主機只能選擇一種儲存驅動,而不能為每個容器選擇不同的儲存驅動。
在 Linux 上,讀者可以通過修改 /etc/docker/daemon.json 檔案來修改儲存引擎配置,修改完成之後需要重啟 Docker 才能夠生效。
下面的程式碼片段展示瞭如何將儲存驅動設定為 overlay2。
{ "storage-driver": "overlay2" }
提示:如果配置所在行不是檔案的最後一行,則需要在行尾處增加逗號。
如果讀者修改了正在執行 Docker 主機的儲存引擎型別,則現有的映象和容器在重啟之後將不可用,這是因為每種儲存驅動在主機上儲存映象層的位置是不同的(通常在 /var/lib/docker/ <storage-driver>/... 目錄下)。
修改了儲存驅動的型別,Docker 就無法找到原有的映象和容器了。切換到原來的儲存驅動,之前的映象和容器就可以繼續使用了。
如果希望在切換儲存引擎之後還能夠繼續使用之前的映象和容器,需要將映象儲存為 Docker 格式,上傳到某個映象倉庫,修改本地 Docker 儲存引擎並重啟,之後從映象倉庫將映象拉取到本地,最後重啟容器。
通過下面的命令來檢查 Docker 當前的儲存驅動型別。
$ docker system info <Snip> Storage Driver: overlay2 Backing Filesystem: xfs Supports d_type: true Native Overlay Diff: true <Snip>
選擇儲存驅動並正確地配置在 Docker 環境中是一件重要的事情,特別是在生產環境中。
下面的清單可以作為一個參考指南,幫助我們選擇合適的儲存驅動。同時還可以參閱 Docker 官網上由 Linux 發行商提供的最新文件來做出選擇。
- Red Hat Enterprise Linux:4.x版本核心或更高版本 + Docker 17.06 版本或更高版本,建議使用 Overlay2。
- Red Hat Enterprise Linux:低版本核心或低版本的 Docker,建議使用 Device Mapper。
- Ubuntu Linux:4.x 版本核心或更高版本,建議使用 Overlay2。
- Ubuntu Linux:更早的版本建議使用 AUFS。
- SUSE Linux Enterprise Server:Btrfs。
我們需要時刻關注 Docker 文件中關於儲存驅動的最新支援和版本相容列表。尤其是正在使用 Docker 企業版(EE),並且有售後支援合同的情況下,更有必要查閱最新文件。
Device Mapper 配置
大部分 Linux 儲存驅動不需要或需要很少的配置。但是,Device Mapper 通常需要合理配置之後才能表現出良好的效能。
預設情況下,Device Mapper 採用 loopback mounted sparse file 作為底層實現來為 Docker 提供儲存支援。
如果需要的是開箱即用並且對效能沒什麼要求,那麼這種方式是可行的。但這並不適用於生產環境。實際上,預設方式的效能很差,並不支援生產環境。
為了達到 Device Mapper 在生產環境中的最佳效能,讀者需要將底層實現修改為 direct-lvm 模式。
這種模式下通過使用基於裸塊裝置(Raw Block Device)的 LVM 精簡池(LVM thin pool)來獲取更好的效能。
在 Docker 17.06 以及更高的版本中可以配置 direct-lvm 作為儲存驅動。
其中最主要的一點是,這種方式只能配置一個塊裝置,並且只有在第一次安裝後才能設定生效。未來可能會有改進,但就目前情況來看配置單一塊裝置這種方式在效能和可靠性上都有一定的風險。
讓 Docker 自動設定 direct-lvm
下面的步驟會將 Docker 配置儲存驅動為 Device Mapper,並使用 direct-lvm 模式。
1) 將下面的儲存驅動配置新增到 /etc/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" ] }
Device Mapper 和 LVM 是很複雜的知識點,下面簡單介紹一下各配置項的含義。
- dm.directlvm_device:設定了塊裝置的位置。為了儲存的最佳效能以及可用性,塊裝置應當位於高效能儲存裝置(如本地 SSD)或者外部 RAID 儲存陣列之上。
- dm.thinp_percent=95:設定了映象和容器允許使用的最大儲存空間佔比,預設是 95%。
- dm.thinp_metapercent:設定了元資料儲存(MetaData Storage)允許使用的儲存空間大小。預設是 1%。
- dm.thinp_autoextend_threshold:設定了 LVM 自動擴充套件精簡池的閾值,預設是 80%。
- dm.thinp_autoextend_percent:表示當觸發精簡池(thin pool)自動擴容機制的時候,擴容的大小應當佔現有空間的比例。
- dm.directlvm_device_force:允許使用者決定是否將塊裝置格式化為新的檔案系統。
2) 重啟 Docker。
3) 確認 Docker 已成功執行,並且塊裝置配置已被成功載入。
$ docker version Client: Version: 18.01.0-ce <Snip> Server: Version: 18.01.0-ce <Snip> $ docker system info <Snipped output only showing relevant data> Storage Driver: devicemapper Pool Name: docker-thinpool Pool Blocksize: 524.3 kB Base Device Size: 25 GB Backing Filesystem: xfs Data file: << Would show a loop file if in loopback mode Metadata file: << Would show a loop file if in loopback mode Data Space Used: 1.9 GB Data Space Total: 23.75 GB Data Space Available: 21.5 GB Metadata Space Used: 180.5 kB Metadata Space Total: 250 MB Metadata Space Available: 250 MB
即使 Docker 在 direct-lvm 模式下只能設定單一塊裝置,其效能也會顯著優於 loopback 模式。
手動配置 Device Mapper 的 direct-lvm
1) 塊裝置(Block Device)
在使用 direct-lvm 模式的時候,讀者需要有可用的塊裝置。這些塊裝置應該位於高效能的儲存裝置之上,比如本地 SSD 或者外部高效能 LUN 儲存。
如果 Docker 環境部署在企業私有云(On-Premise)之上,那麼外部 LUN 儲存可以使用 FC、iSCSI,或者其他支援塊裝置協議的儲存陣列。
如果 Docker 環境部署在公有云之上,那麼可以採用公有云廠商提供的任何高效能的塊裝置(通常基於 SSD)。
2) LVM配置
Docker 的 Device Mapper 儲存驅動底層利用 LVM(Logical Volume Manager)來實現,因此需要配置 LVM 所需的物理裝置、卷組、邏輯卷和精簡池。
讀者應當使用專用的物理卷並將其配置在相同的卷組當中。這個卷組不應當被 Docker 之外的工作負載所使用。
此外還需要配置額外兩個邏輯卷,分別用於儲存資料和源資料資訊。另外,要建立 LVM 配置檔案、指定 LVM 自動擴容的觸發閾值,以及自動擴容的大小,並且為自動擴容配置相應的監控,保證自動擴容會被觸發。
3) Docker 配置
修改 Docker 配置檔案之前要先儲存原始檔案(etc/docker/daemon.json),然後再進行修改。
環境中的 dm.thinpooldev 配置項對應值可能跟下面的示例內容有所不同,需要修改為合適的配置。
{ "storage-driver": "devicemapper", "storage-opts": [ "dm.thinpooldev=/dev/mapper/docker-thinpool", "dm.use_deferred_removal=true", "dm.use_deferred_deletion=true" ] }
修改並儲存配置後,讀者可以重啟 Docker daemon。