為什麼要驅逐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 Signal | Description |
---|---|
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型別的驅逐:
-
nodefs:kubelet 用來儲存 pods 或 volume 和 daemon logs 的資訊等
-
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,直到資源使用狀況恢復到閾值以下。以硬驅逐為例,整體流程是:
-
每隔一段時間從cadvisor中獲取資源使用情況,和定義的閥值進行對比,在 kubelet 中 --node-status-update-frequency 引數來定義獲取上報的頻率,預設為10s。
-
-
首先從執行中的pod裡找到QoS策略最開放的型別 pod ;
-
然後根據 Pod 排程請求的被耗盡資源的消耗量來結合進行驅逐。
-
-
檢查資源是否到達閥值以內,若還未滿足,則再進行第二步。
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,則表示沒有限制。