kubelet 原理解析六: 垃圾回收

概述

在k8s中節(jié)點會通過docker pull機制獲取外部的鏡像,那么什么時候清除鏡像呢?k8s運行的容器又是什么時候清除呢?

  • api-server: 運行在master,無狀態(tài)組件,go自動內(nèi)存垃圾回收
  • controller-manager: 運行在master,無狀態(tài)組件,go自動內(nèi)存垃圾回收,owner機制提供resource垃圾回收
  • scheduler: 運行在master,無狀態(tài)組件,go自動內(nèi)存垃圾回收
  • kube-proxy:運行在node,無狀態(tài)組件,無垃圾收集需要
  • kubelet:運行在node,無狀態(tài)組件,需要管理宿主機的image和container

Kubelet會定期進行垃圾回收(Garbage Collection),以清理節(jié)點上的無用鏡像和容器。

  • 每隔 1 分鐘進行一次容器清理
  • 每隔 5 分鐘進行一次鏡像清理

截止到 v1.15 版本,垃圾回收間隔時間還都是在源碼中固化的,不可自定義配置,如果節(jié)點上已經(jīng)運行了 Kubelet,不建議再額外運行其它的垃圾回收工具,因為這些工具可能錯誤地清理掉 Kubelet 認為本應保留的鏡像或容器,從而可能造成不可預知的問題。

容器的回收

docker容器的本質(zhì)是宿主機上的一個進程,為了將容器做差異化的封裝,docker借助于類似AUFS之類的文件系統(tǒng)做了很多事情。容器停止執(zhí)行后,這些文件系統(tǒng)并不會自動清除,通過docker ps -a也能夠看到這些資源(這是為了下次可以快速啟動)。kubelet有一套container gc的方案,專門用于清理宿主機上的非所需容器。

另外,容器鏡像較耗存儲資源,但是每一臺k8s node的存儲空間都是有限的,kubelet上運行的pod生命周期可能很短,但是每個pod可能都使用不同的鏡像,這就會導致宿主機上會留下很多不再需要的容器鏡像,為了將有限的空間騰出來高效利用,kubelet設(shè)計了一套image gc的方案。

image

GC機制即將被eviction替代,在kubelet參數(shù)中已經(jīng)有對應的提示信息。

容器GC的業(yè)務(wù)邏輯主要在(m *kubeGenericRuntimeManager)GarbageCollect中,主要是三個參數(shù):

  • MinAge:容器可以被垃圾回收的最小年齡,默認0分鐘,命令行參數(shù)為minimum-container-ttl-duration

  • MaxPerPodContainer: 每個pod中保留的最大的停止容器數(shù)量,默認為1,命令行參數(shù)為maximum-dead-containers-per-container

  • MaxContainers: 整個節(jié)點保留的最大的停止容器數(shù)量,默認為-1,標示沒有限制,命令行參數(shù)為maximum-dead-containers

容器回收過程如下:

  1. 頂層函數(shù)會每分鐘被調(diào)用,觸發(fā)container gc操作;
  2. 該操作會以container的結(jié)束時間是否超過gcPolicy.MinAge為依據(jù),查詢出那些滿足條件的容器,并組織成為按照pod為key,container列表為值的字典;這一步并沒有做實際刪除,但是其操作結(jié)果為后兩部奠定了數(shù)據(jù)依據(jù);
  3. 對字典中的每個pod的container做處理,找出該pod超過gcPolicy.MaxPerPodContainer的容器,然后對它們按照結(jié)束時間排序,執(zhí)行刪除,保障每個pod下已結(jié)束的container數(shù)滿足配置參數(shù);
  4. 經(jīng)過上一部的刪除后,針對node來講,如果節(jié)點上待刪除的容器數(shù)依然大于gcPolicy.MaxContainers, 就執(zhí)行反向的運算。把node允許保留的最大容器數(shù)平分給每個pod,再按照該標準對每個pod執(zhí)行一輪刪除;
  5. 如果依然還不滿足要求的數(shù)量,就不再按照pod做key,直接將所有的container拍扁平,按照時間順序先刪除最舊的容器,直到滿足總數(shù)小于gcPolicy.MaxContainers。
image

鏡像的回收

鏡像回收主要參數(shù):

  • minimum-image-ttl-duration:最少這么久鏡像都未被使用,才允許清理;比如:’300ms’, ‘10s’ or ‘2h45m’.”

  • image-gc-high-threshold:imageFS磁盤使用率的上限,當達到該值時觸發(fā)鏡像清理。默認值為 90%

  • image-gc-low-threshold: imageFS磁盤使用率的下限,每次清理直到使用率低于這個值或者沒有可以清理的鏡像了才會停止。默認值為 80%

具體流程比較簡單;

  1. 與容器GC比較起來,鏡像GC頂層函數(shù)被觸發(fā)的周期更長,為5分鐘觸發(fā)一次。
  2. 通過cadvisor獲取到節(jié)點上imageFS的詳情,得到capacity、avaiable,據(jù)此推算磁盤使用率等信息;
  3. 當磁盤使用率大于image-gc-high-threshold參數(shù)中指定的值時,觸發(fā)鏡像的GC操作;
  4. 找出當前未被使用的鏡像列表并按時間排序,過濾掉那些小于minimum-image-ttl-duration的鏡像;
  5. 正式從節(jié)點上刪除鏡像;每次都比較是否刪除的鏡像數(shù)以滿足所需釋放的bytesToFree,若滿足就停止刪除。
  • 那些用戶手動 run 起來的容器,對于 Kubelet 垃圾回收來說就是不可見的,也就不能阻止對相關(guān)鏡像的垃圾回收
  • 當鏡像存放目錄磁盤使用率(df -h) 大于 HighThresholdPercent后,開始刪除節(jié)點中未使用的docker鏡像
  • 當磁盤使用率降低至LowThresholdPercent時,停止鏡像的垃圾回收。
  • 在節(jié)點中存在一定的image是必要的,因為可以減少docker拉取鏡像的速度減少帶寬壓力,加速容器啟動.

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容