kubelet 資源清理緩解磁盤壓力指南
在 Kubernetes 集群中,當節點磁盤壓力過大時,可通過以下幾種方式利用 kubelet 清理資源,從而緩解磁盤壓力。
一、鏡像垃圾回收
自動回收
kubelet 內置了鏡像垃圾回收機制,其行為由配置參數控制。編輯 /var/lib/kubelet/config.yaml
文件,添加或修改如下參數:
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageGCHighThresholdPercent
表示當磁盤使用率達到 85% 時觸發鏡像回收;imageGCLowThresholdPercent
表示回收操作將持續進行,直到磁盤使用率降至 80%。修改后,重啟 kubelet 服務:
sudo systemctl restart kubelet
手動回收
根據不同的容器運行時,使用對應命令手動清理鏡像:
- Docker:
docker image prune -a -f
- containerd:
crictl rmi $(crictl images -q)
觸發條件與過程
- 觸發條件:當節點的磁盤使用率超過設定的閾值時,kubelet 會觸發鏡像垃圾回收。正常情況下會定時執行,以保證節點資源充足;在節點資源不足時,Kubelet 在驅逐 Pod 前會先強制執行一次垃圾回收,如果清理后資源充足則不會驅逐 Pod。
- 清理過程:kubelet 會識別不再被任何容器引用的鏡像(未使用鏡像),并按照最近使用時間排序,優先刪除最舊的鏡像。對于新拉取的鏡像,會存活一定時間(默認 2 分鐘)后才執行清理,以防止剛拉取的鏡像就被清理掉。
關鍵參數
--image-gc-high-threshold
:磁盤使用率的上限閾值,默認為 85%。--image-gc-low-threshold
:磁盤使用率的下限閾值,默認為 80%。--minimum-image-ttl-duration
:鏡像最短生存時間,默認 2 分鐘。
回收頻率與流程
- 回收頻率:Kubelet 默認每 5 分鐘執行一次鏡像垃圾回收。
- 回收流程:Kubelet 會識別不再被任何 Pod 引用的鏡像,并按照最近使用時間(LRU)策略逐個清理,直到磁盤使用率降到設定的下限或沒有空閑鏡像可以清理。
二、容器垃圾回收
自動回收
kubelet 可以根據配置自動清理已停止的容器。編輯 /var/lib/kubelet/config.yaml
文件,添加或修改如下參數:
containerRuntimeOptions:containerGC:maxPerPodContainer: 1minAge: 2m
maxPerPodContainer
限制每個 Pod 最多保留的已停止容器數量為 1;minAge
表示只有停止時間超過 2 分鐘的容器才會被清理。修改后,重啟 kubelet 服務。
手動回收
- Docker:
docker container prune -f
- containerd:
crictl rm $(crictl ps -a -q)
觸發條件與過程
- 觸發條件:kubelet 定期執行容器垃圾回收,以清理不再需要的容器,主要針對普通容器、sandbox 容器以及容器日志目錄。對于普通容器,Kubelet 會根據
MaxPerPodContainer
與MaxContainers
的設置,按照 LRU 策略,從 Pod 的死亡容器列表刪除一定數量的容器,直到滿足配置需求;對于 sandbox 容器,Kubelet 按照每個 Pod 保留一個的原則清理多余的死亡 sandbox;對于日志目錄,只要沒有 Pod 與之關聯了就將其刪除。 - 清理過程:kubelet 會刪除已經終止的容器,特別是那些已經超出保留時間的容器。
關鍵參數
--maximum-dead-containers-per-container
:每個 Pod 可以保留的死亡容器的最大數量,默認為 1。--maximum-dead-containers
:節點上可以保留的死亡容器的最大數量,默認為 -1,表示沒有限制。--minimum-container-ttl-duration
:容器可被回收的最小生存時間,默認為 0 分鐘,即死亡容器可以立即被回收。
回收頻率與流程
- 回收頻率:Kubelet 默認每分鐘執行一次容器垃圾回收。
- 回收流程:Kubelet 會清理可以驅逐的容器,包括那些狀態不是
RUNNING
且在本輪 GC 前創建的容器。Kubelet 在到達 GC 時間點時,會遍歷所有 Pod,使其滿足--maximum-dead-containers-per-container
的設置,如果不滿足--maximum-dead-containers
,則計算值X = (--maximum-dead-containers)/(Pod 總數)
,再遍歷所有 Pod,使其滿足已停止運行的容器集個數不大于X
且至少為 1,如果還不滿足--maximum-dead-containers
,則對所有已停止的容器(普通容器 + sandbox 容器)排序,優先刪除創建時間最早的容器直到滿足--maximum-dead-containers
為止。執行清理直到滿足以下條件之一:- 每個 Pod 中存在的已掛掉的容器數滿足閾值。
- 所有 Pod 中存在的已掛掉的容器數滿足閾值。
三、未使用的 Volume 清理
手動清理
定期清理不再使用的持久卷聲明(PVC)和掛載的 Volume 能釋放大量磁盤空間。使用以下命令刪除所有處于 Released
狀態的 PVC:
kubectl get pvc --field-selector status.phase=Released -o name | xargs kubectl delete
此外,若使用的是動態存儲卷,確保存儲類(StorageClass)配置了正確的回收策略。
觸發條件與過程
- 觸發條件:當節點磁盤空間不足時,kubelet 會嘗試清理未使用的 Volumes。
- 清理過程:kubelet 會識別并刪除那些不再被任何 Pod 引用的 Volumes。
自動清理涉及方面
- PersistentVolumeClaim (PVC) 和 PersistentVolume (PV) 的回收策略:Kubernetes 中的 PVC 對象可以設置
reclaimPolicy
屬性,該屬性有兩個值:Retain
和Delete
。當 PVC 與 PV 綁定后,如果 Pod 被刪除,根據reclaimPolicy
的設置,Volume 可以被保留或自動刪除。 - StorageClass 的 reclaimPolicy:在 StorageClass 對象中,可以設置
reclaimPolicy
,這將決定 PV 的默認回收策略。當設置為Delete
時,PV 和綁定的存儲資源在 PVC 刪除時將被自動清理。 - Kubelet 垃圾回收機制:Kubelet 定期進行垃圾收集,包括容器和鏡像。Kubelet 每分鐘對未使用的容器執行一次垃圾收集,每五分鐘對未使用的鏡像執行一次垃圾收集。
- Volume 插件目錄清理:Kubelet 可以通過配置
--volume-plugin-dir
參數來指定卷插件目錄,并定期清理其中的數據。 - 日志文件管理:Kubelet 會定期清理舊的日志文件,或者配置日志輪轉工具(如 logrotate)來管理日志文件的大小和生命周期,以釋放磁盤空間。
- 手動清理命令:可以使用
kubectl
命令清理未使用的 PV 和 PVC,例如查找未被使用的 PVC 并刪除它們,進而可能觸發關聯 Volume 的清理。 - 定期審計和清理:定期檢查集群中的 Volume 使用情況,手動清理未被自動回收的 Volume。
四、驅逐機制(Eviction)
配置參數
kubelet 可以基于磁盤壓力等條件驅逐 Pod,釋放節點資源。編輯 /var/lib/kubelet/config.yaml
文件,添加或修改如下參數:
evictionHard:imagefs.available: 10%nodefs.available: 10%
evictionSoft:imagefs.available: 15%nodefs.available: 15%
evictionSoftGracePeriod:imagefs.available: 5mnodefs.available: 5m
evictionMinimumReclaim:imagefs.available: 5%nodefs.available: 5%
上述配置中,當鏡像文件系統或節點文件系統的可用空間低于 10% 時,觸發硬驅逐;低于 15% 時觸發軟驅逐,軟驅逐會在 5 分鐘后執行,每次驅逐操作至少回收 5% 的可用空間。修改后,重啟 kubelet 服務。
觸發條件與過程
- 觸發條件:當節點資源(如內存、磁盤空間)低于硬驅逐閾值時,kubelet 會觸發驅逐機制。
- 驅逐過程:kubelet 會根據配置的驅逐策略,選擇并終止某些 Pod 以釋放資源。例如,當節點的可用內存低于 100Mi 時,kubelet 可能會開始驅逐 Pod。
五、日志文件管理
自動輪轉
使用 logrotate
工具配置日志輪轉,編輯 /etc/logrotate.d/kubelet
文件:
/var/log/kubelet.log {dailymissingokrotate 7compressdelaycompressnotifemptycreate 0640 root admsharedscriptspostrotateif [ -f /var/run/kubelet.pid ]; thenkill -HUP `cat /var/run/kubelet.pid`fiendscript
}
上述配置表示每天輪轉一次 kubelet 日志文件,保留最近 7 天的日志,壓縮舊日志文件。
手動清理
手動刪除不再需要的日志文件:
sudo rm -rf /var/log/pods/*
需注意,此操作會清除所有 Pod 的日志,操作前請備份重要日志。
觸發條件與管理過程
- 觸發條件:日志文件占用大量磁盤空間時。
- 管理過程:kubelet 會定期清理舊的日志文件,或者配置日志輪轉工具(如 logrotate)來管理日志文件的大小和生命周期。
日志管理涉及方面
- 日志文件路徑規則:Kubelet 將容器日志默認寫入
/var/log/pods
目錄下,每個 Pod 的日志存放在以其命名空間、名稱和 UID 為名的子目錄中。容器日志文件以容器重啟次數命名,格式為<容器重啟次數>.log
。 - 日志文件軟鏈接規則:容器日志目錄下的日志文件實際上是軟鏈接類型文件,指向實際的日志文件。
- 日志文件清理:Kubelet 每 1 分鐘執行一次容器清理,包括清理死亡容器的日志目錄。如果一個 Pod 已經不再占用其日志目錄,Kubelet 會清理這些日志目錄。
- 日志文件大小和文件數限制:Kubelet 配置選項
containerLogMaxSize
和containerLogMaxFiles
分別允許配置每個日志文件大小的最大值和每個容器允許的最大文件數,默認分別為 10Mi 和 5。 - 日志輪換機制:Kubelet 提供了基于可以執行多少并發日志輪換以及監控和輪換日志所需要的間隔來調整日志的輪換方式的機制。可以通過配置
containerLogMaxWorkers
和containerLogMonitorInterval
來調整。 - 系統組件日志位置:在使用 systemd 的 Linux 節點上,kubelet 和容器運行時默認寫入 journald。如果 systemd 不存在,kubelet 和容器運行時將寫入到
/var/log
目錄中的.log
文件。 - 自定義日志目錄:Kubelet 允許將 Pod 日志目錄從默認的
/var/log/pods
更改為自定義路徑,通過在 kubelet 的配置文件中配置podLogsDir
參數來進行此調整。
六、配置參數調整
減少日志級別
編輯 kubelet 服務的啟動參數文件 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
,添加或修改 --v
參數來降低日志級別:
Environment="KUBELET_EXTRA_ARGS=--v=2"
日志級別范圍從 0 到 10,數值越小,日志輸出越少。修改后,重新加載 systemd 配置并重啟 kubelet 服務:
sudo systemctl daemon-reload
sudo systemctl restart kubelet
減少緩存
減少 kubelet 的緩存數據,如臨時文件和下載的鏡像等。編輯 /var/lib/kubelet/config.yaml
文件,添加或修改如下參數:
cacheDir: /var/lib/kubelet/cache
cacheMaxSize: 1024Mi
上述配置將 kubelet 的緩存目錄設置為 /var/lib/kubelet/cache
,并限制緩存最大為 1024MB。修改后,重啟 kubelet 服務。
通用參數調整
管理員可以通過調整 kubelet 的配置參數來優化資源清理行為,例如調整垃圾回收的閾值和頻率。