2020-04-14
Bug 描述
測試機進行一次完整的部署(近 90 個新 Pod 被調度到同一個節點)后,通過 Dashboard 查看,發現 Pod 容器組有一個 Failed Pod。
容器總體個數正常,Failed Pod 是“多余的”。
排查流程
- 在 Dashboard 中查看該 Pod,只顯示它處於 Failed 狀態,沒有更多提示。沒什么用。。
- 通過 k9s 查看該 Pod 的詳細信息,發現它是因為 DiskPressure 而被驅逐(Evicted)。
- 用 ssh 進入這個節點,通過
df -h
命令確認磁盤狀態,發現磁盤利用率為 46%,遠低於 DiskPressure 的默認觸發條件:85%。DiskPressure 自己消失了。。
既然磁盤壓力自己恢復了,應該是 kubernetes 自己有某種清理策略,開始網上查詢資料:
- 網上查詢資料 Kubernetes Node節點DiskPressure異常處理,了解到是 kubelet 組件負責管理節點資源。
- 搜索到官方文檔 kubernets - 回收節點資源
- 上述文檔說在 with-imagefs 和 without-imagefs 時,遇到 DiskPressure,有不同的資源回收策略。
- 清理策略比較復雜,后面再討論。
- 通過
vim
查看 kubelet 日志/var/log/message
,搜索關鍵字Evicted
,DiskPressure
,Pressure
等,查找到了DiskPressure
相關信息 - 觀察 DiskPressure 日志的上下文,發現有
imageGCManager
清理 image 相關的日志。這顯然就是一個自動回收資源的事件。 - 搜索 kubernetes image gc,找到官方文檔:配置 kubelet 垃圾回收策略
- 另有硬驅逐策略的默認閾值 Hard Eviction Thresholds 一致,
- 相關 Issue: Kubernetes Issue - Can we deprecate '--image-gc-high-threshold' and 'image-gc-low-threshold'
- 相關提案:Kubelet - Eviction Policy
分析結果
總的來說,就是 DiskPressure 是因為歷史鏡像過多引起的。目前有兩種方法可以讓 kubernetes 自己進行數據清理:
方法一:配置鏡像的垃圾回收策略
已被標記為棄用
這涉及到兩個參數:
image-gc-high-threshold
: 當磁盤使用率超過這個值時,就會觸發鏡像回收器。默認值為 85%。image-gc-low-threshold
: 當鏡像回收器被觸發后,它至少會使磁盤使用率低於這個閾值(否則不會停)。默認值為 80%。
方法二:配置驅逐策略(推薦)
根據官方文檔說明,為了統一 kubernetes 中的資源回收參數,未來將棄用方法一。
新的鏡像GC策略已經被合並到了Pod驅逐策略中,詳細的配置方法見下文。
容器鏡像GC、Pod驅逐以及節點壓力
節點壓力 DiskPressure 會導致 Pod 被驅逐,也會觸發容器鏡像的 GC。
根據官方文檔 配置資源不足時的處理方式,Kubelet 提供如下用於配置容器 GC 及 Evicetion 的閾值:
--eviction-hard
和eviction-soft
: 對應舊參數--image-gc-high-threshold
,這兩個參數配置鏡像 GC 及驅逐的觸發閾值。磁盤使用率的閾值默認為 85%- 區別在於
eviction-hard
是立即驅逐,而eviction-soft
在超過eviction-soft-grace-period
之后才驅逐。
- 區別在於
--eviction-minimum-reclaim
: 對應舊參數--image-gc-low-threshold
。這是進行資源回收(鏡像GC、Pod驅逐等)后期望達到的磁盤使用率百分比。磁盤使用率的閾值默認值為 80%。
問:能否為 ImageGC 設置一個比 DiskPressure 更低的閾值?因為我們希望能自動進行鏡像 GC,但是不想立即觸發 Pod 驅逐。
答:這應該可以通過設置 eviction-soft
和長一點的 eviction-soft-grace-period
來實現。
另外 --eviction-minimum-reclaim
也可以設小一點,清理得更干凈。示例如下:
--eviction-soft=memory.available<1Gi,nodefs.available<2Gi,imagefs.available<200Gi
--eviction-soft-grace-period=3m
--eviction-minimum-reclaim=memory.available=0Mi,nodefs.available=1Gi,imagefs.available=2Gi