摘要:使用者在使用 Docker 部署業務一段時間後,可能會發現宿主節點的磁碟容量持續增長,甚至將磁碟空間耗盡進而引發宿主機異常,進而對業務造成影響。 本文先對 Docker 的空間分析與清理進行說明,然後對容器的磁碟容量限制與使用建議做簡要說明。
典型問題場景
使用者發現 Docker 宿主機的磁碟空間使用率非常高。通過 du 逐層分析,發現是 Volume 或 overlay2 等目錄佔用了過高空間。示例如下:
空間使用分析
遇到此類問題,可以參閱如下步驟進行空間分析,定位佔用過高空間的業務來源。
分析 Docker 空間分佈
Docker 的內建 CLI 指令docker system df,可用於查詢映象(Images)、容器(Containers)和本地卷(Local Volumes)等空間使用大戶的空間佔用情況。 示例輸出如下:
檢視空間佔用細節
可以進一步通過-v引數檢視空間佔用細節,以確定具體是哪個映象、容器或本地卷佔用了過高空間。示例輸出如下:
空間清理
自動清理
可以通過 Docker 內建的 CLI 指令docker system prune來進行自動空間清理。
Tips:
不同狀態的映象
已使用映象(used image): 指所有已被容器(包括已停止的)關聯的映象。即 docker ps -a 看到的所有容器使用的映象。
未引用映象(unreferenced image):沒有被分配或使用在容器中的映象,但它有 Tag 資訊。
懸空映象(dangling image):未配置任何 Tag (也就無法被引用)的映象,所以懸空。這通常是由於映象 build 的時候沒有指定 -t 引數配置 Tag 導致的。比如:
掛起的卷(dangling Volume)
類似的,dangling=true 的 Volume 表示沒有被任何容器引用的卷。
docker system prune 自動清理說明:
該指令預設會清除所有如下資源:
已停止的容器(container)
未被任何容器所使用的卷(volume)
未被任何容器所關聯的網路(network)
所有懸空映象(image)。
該指令預設只會清除懸空映象,未被使用的映象不會被刪除。
新增-a 或 --all引數後,可以一併清除所有未使用的映象和懸空映象。
可以新增-f 或 --force引數用以忽略相關告警確認資訊。
指令結尾處會顯示總計清理釋放的空間大小。
操作示例:
手工清理
網路清理
網路配置通常佔用的空間非常低,略過。
映象清理
如果通過 docker system df 分析,是映象佔用了過高空間。則可以根據業務情況,評估相關映象的使用情況。對於懸空和未使用的映象, 可以使用如下指令手工清理:
容器清理
如果通過 docker system df 分析,是某個容器佔用了過高空間。則可以根據業務情況,評估相關容器的業務歸屬並進行處理。對於已停止或其它異常狀態的容器,可以結合-f 或 --filter篩選器,使用類似如下指令來手工清理:
在用空間資源分析
對於還在使用的空間資源,可以參閱如下說明做進一步排查分析。
映象空間分析
如果某個映象佔用了過高空間,則可以通過如下方式做進一步空間分析:
通過 docker system df 獲取佔用過高空間的映象資訊。
基於相應映象建立測試容器。
exec 進入容器後,結合 du 等 shell 指令做進一步空間分析,定位出佔用最高空間的目錄或檔案。
結合業務情況做進一步處理,重新 build 映象。
示例:
容器空間分析
如果某個執行中的容器佔用了過高空間,則可以通過如下方式做進一步空間分析:
Tips:
容器的只讀層與映象層的空間佔用情況
一個容器的佔用的總空間,包含其最頂層的讀寫層(writable layer)和底部的只讀映象層(base image layer,read-only)。更多相關說明,可以參閱官方文件。
可以通過 docker ps 的-s引數來分別顯示二者的空間佔用情況,進而判斷相應容器的空間佔用主要是來自原始映象,還是執行中產生。
容器空間佔用的分析步驟:
通過 docker system df 獲取佔用過高空間的容器資訊。
通過前述-s引數確認到底是底層映象,還是執行過程中產生的資料佔用了過高空間。
exec 進入容器,結合 du 等 shell 指令做進一步空間分析,定位出佔用最高空間的目錄或檔案。
結合業務情況做進一步處理。
引申:Docker 磁碟空間限制與使用建議
磁碟空間限制
使用 Device Mapper 儲存驅動限制容器磁碟空間
如果使用 Device Mapper 作為底層儲存驅動,則可以通過 Docker daemon 的如下引數來全侷限制單個容器佔用空間的大小:
--storage-opt dm.basesize=20G表示限制單個容器最多佔用 20G 空間,將應用於任何新建容器。
更多關於 Device Mapper 儲存驅動的說明,可以參閱官方文件。
使用 btrfs 儲存驅動限制容器磁碟空間
btrfs 驅動主要使用 btrfs 所提供的 subvolume 功能來實現。一個容器會對應一個 subvolume。針對容器對應的 subvolume 啟用並配置 quota 即可限制其磁碟空間。示例配置:btrfs 還有其它很好的特性,比如可以線上擴容(線上加入一塊新的塊裝置,來擴充整個檔案系統的大小)。
外掛 LVM 卷
如果使用的是其它不支援對單個容器的磁碟容量進行限制的儲存驅動,則可以考慮如下通用方案:
通過 LVM 方式建立一個指定容量的卷,然後掛載到宿主作業系統上特定目錄。最後通過 --volume 引數來讓容器來掛載使用相應目錄。
注意:該方案的前提條件是,容器中所有落盤操作要全部落到上述 "--volume" 引數指定的卷中,否則容器還會佔用預設 aufs 所在盤的空間,進而造成統計不準。
Docker 儲存使用建議
細化的儲存使用最佳實踐與採用的儲存驅動(storage driver)型別強相關
通用的儲存使用建議如下:
容器內的業務日誌務必配置輪詢覆寫,或者使用日誌驅動將日誌輸出到外部儲存。避免日誌檔案持續增長,佔用過高磁碟空間。
結合外部監控對宿主機的磁碟空間使用情況進行監控和告警。