Kubernetes-22:kubelet 驅逐策略詳解

vfanCloud發表於2021-07-16

為什麼要驅逐pod?

在可用計算資源較少時,kubelet為保證節點穩定性,會主動地結束一個或多個pod以回收短缺地資源,這在處理記憶體和磁碟這種不可壓縮資源時,驅逐pod回收資源的策略,顯得尤為重要。

可壓縮資源 —— cpu,可壓縮資源不會導致pod驅逐,因為在資源緊缺時系統核心會重新分配權重

不可壓縮資源 —— 記憶體 磁碟

 

Kubelet Eviction 策略的工作機制

  • kubelet預先監控本節點的資源使用,防止資源被耗盡,保證節點穩定性。

  • kubelet會預先Fail N(>=1)個Pod,以回收出現緊缺的資源。

  • kubelet在Fail一個pod時,kill掉pod內所有container,並設定pod.status.phase = Failed。

  • kubelet按照事先設定好的Eviction Threshold來觸發驅逐動作,實現資源回收。

 

驅逐訊號

pkg/kubelet/eviction/api/types.go原始碼中定義了以下幾種驅逐訊號:
Eviction SignalDescription
memory.available node.status.capacity[memory] - node.stats.memory.workingSet
nodefs.available node.stats.fs.available
nodefs.inodesFree node.stats.fs.inodesFree
imagefs.available node.stats.runtime.imagefs.available
imagefs.inodesFree node.stats.runtime.imagefs.inodesFree
allocatableMemory.available pod.allocatable - pod.workingSet
pid.available node.MaxPID - node.NumOfRunningProcesses

上表主要涉及三個方面,memory、file system和pid。

其中kubelet支援2種file system型別的驅逐:

  1. nodefs:kubelet 用來儲存 pods 或 volume 和 daemon logs 的資訊等

  2. Imagesfs:用來儲存 docker 映象層或容器層資料的路徑(readOnly layer and write layer)

 

驅逐策略

k8s中定義了兩種驅逐策略,一種為軟碟機逐,一種為硬驅逐。

 

軟碟機逐(Soft Eviction Thresholds)

軟碟機逐機制表示,當node的 記憶體/磁碟 空間達到一定的閾值後,我要觀察一段時間,如果改善到低於閾值就不進行驅逐,若這段時間一直高於閾值就進行驅逐。

一般由三個引數配合使用:

  • eviction-soft:觸發軟碟機逐策略的閥值

  • eviction-soft-grace-period:觸發軟碟機逐策略的閥值後等待的時間,如果在此時間內還未恢復到閥值以下,則會開始驅逐pod

  • eviction-max-pod-grace-period:達到軟閾值之後,到驅逐一個 Pod 之前的最大寬限時間(單位 s )

 

硬驅逐(Hard Eviction Thresholds)

硬驅逐簡單粗暴,沒有寬限期,一旦達到閾值配置,kubelet立馬回收關聯的短缺資源,將pod kill掉,而不是優雅終止。

原始碼pkg/kubelet/apis/config/v1beta1/defaults_linux.go給出了預設的硬驅逐配置:

  • memory.available < 100Mi

  • nodefs.available < 10%

  • nodefs.inodesFree < 5%

  • imagefs.available < 15%

 

Pod驅逐流程

當資源使用情況觸發了驅逐條件時,kubelet會啟動一個任務去輪流停止執行中的pod,直到資源使用狀況恢復到閾值以下。以硬驅逐為例,整體流程是:

  1. 每隔一段時間從cadvisor中獲取資源使用情況,和定義的閥值進行對比,在 kubelet 中 --node-status-update-frequency 引數來定義獲取上報的頻率,預設為10s。

    • 首先從執行中的pod裡找到QoS策略最開放的型別 pod ;

    • 然後根據 Pod 排程請求的被耗盡資源的消耗量來結合進行驅逐。

  2. 檢查資源是否到達閥值以內,若還未滿足,則再進行第二步。

 

Qos驅逐等級

當一個pod被建立,kubernetes會賦予它們以下型別的值之一

  • Guaranteed

  • Burstable

  • BestEffor

三種Qos型別優先順序(由高到低):Guaranteed > Burstable > BestEffort

從上到下,它們的質量會越來越低,質量越高,該pod就會盡量被保護,不被驅逐

 

滿足以下條件的pod將會被賦予 Guaranteed QoS型別

  • pod中每個容器都必須包含記憶體請求和限制,並且值相等

  • pod中每個容器都必須包含cpu請求和限制,並且值相等

當符合以下條件時,一個pod會被賦予Burstable型別的QoS

  • Pod不符合 Guaranteed 型別的QoS要求

  • pod至少設定了記憶體或者cpu請任一

一個pod即沒有記憶體限制或請求也沒有cpu限制或請求,則會被賦予BestEffort

檢視某pod的qos等級:

kubectl get pod -n kube-system  kube-apiserver-yq01 -o yaml | grep qos
  qosClass: Burstable

 

資源緊缺時,驅逐pod的優先順序規則:
  • 當 pod qos=BestEffort 時,消耗最多緊缺資源的 Pod 最先驅逐。

  • 當 pod qos=Burstable 時,請求(request的值)最多緊缺資源的 Pod 會被驅逐,如果沒有 Pod 超出他們的請求(比如說mem request的值為1G,但實際使用量並沒有超過1G),會驅逐資源消耗量最大的 Pod。

  • 當 pod qos=Guaranteed 時,請求(request的值)最多緊缺資源的 Pod 被驅逐,如果沒有 Pod 超出他們的請求,會驅逐資源消耗量最大的 Pod。

  • 如果當磁碟空間/inodes緊缺時,就會通過 QoS 的等級基礎上,選擇消耗最多磁碟空間inodes的 Pod 進行驅逐。

 

問題擴充

1、如何更改kubelet的預設驅逐閥值呢?

硬閥值的設定:

將以下策略加入到/etc/kubernetes/kubelet.env即kublet啟動引數即可

--eviction-hard=memory.available<256Mi,nodefs.available<1Gi,imagefs.available<1Gi \
--eviction-minimum-reclaim=memory.available=512Mi,nodefs.available=1Gi,imagefs.available=1Gi \
--eviction-pressure-transition-period=30s

第一行表示當memory<256Mi,nodefs<1G,imagesfs<1G,時才會觸發硬驅逐策略

第二行表示最小驅逐回收策略,就是一旦驅逐策略被觸發,則要一直驅逐直到低於此行策略的閥值為止,為了就是防止剛剛觸發硬驅逐策略,驅逐完之後沒一會資源又漲上來了,導致要反覆驅逐的現象

第三行是為了防止node節點狀態振盪

 

軟閥值的設定:

--eviction-soft=memory.available<10%,nodefs.available<15%,imagefs.available<15% \
--eviction-soft-grace-period=memory.available=2m,nodefs.available=2m,imagefs.available=2m \
--eviction-max-pod-grace-period=30

第一行表示軟碟機逐閥值,使用百分比代替

第二行表示觸發軟碟機逐後,等待執行的時間,若此時間內低於閥值,則不再進行驅逐

第三行為pod寬限時間

 

2、當資源不夠或發生爭奪有pod被驅逐後,pod的狀態會變為Eviction,如果資源一直無法協調過來,或者資源真的不夠用了,那麼會產生大量的Eviction狀態的Pod,會影響整個叢集的使用,如何限制Eviction的Pod的數量呢?

此配置其實是由 kube-contoller-manager 來管理的,所以想要修改要修改kube-contoller-manager.yaml的引數,一般在/etc/kubernetes/manifests/kube-contoller-manager.yaml新增:

--terminated-pod-gc-threshold=1

此值設定了Eviction pod最大的產生個數,預設為12500,最小改為1,若為0,則表示沒有限制。

相關文章