在啟動驅逐程序之前,Kubelet 會嘗試進行自我修復,盡可能回收 Node 的資源,避免不必要的 驅逐。可以回收的 Node 資源都是跟檔案系統為主,所以自我修復的方式大多是清出空間。
以下是自我修復的方式
垃圾回收: Kubelet 會清理已終止 Pod 和容器的相關資源,例如 Log、暫存檔等。
未使用的 Container Image: 當 imagefs 檔案系統觸發驅逐閾值時,Kubelet 會刪除未被任何 Pod 使用的 Container Image,釋放磁碟空間。
最小回收量 (Minimum Eviction Reclaim): 為了避免頻繁觸發驅逐程序,我們可以設定每個資源的最小回收量。例如,evictionMinimumReclaim: nodefs.available: "500Mi" 表示每次資源回收至少需要釋放 500MiB 的磁碟空間。
如果自我修復無法緩解資源壓力,Kubelet 就會開始執行 Pod 驅逐程序。在這個過程中,Kubelet 需要與 CRI 互動,請求終止指定的 Pod。
Pod 驅逐流程: Kubelet 會根據驅逐策略選擇要驅逐的 Pod,並透過 CRI 向 Container Runtime 發送終止 Pod 的請求。Container Runtime 收到請求後,會執行 Pod 的終止流程,包括停止 Container、釋放資源等。
資源使用量與請求量之差: 資源使用量超過請求量的 Pod 會優先被考慮。
Priority: Priority 較低的 Pod 更容易被驅逐。我們可以透過設定 Pod 的 priorityClassName 來調整 Pod 的優先級。
資源使用量相對於請求量的比例: 對於資源使用量超過請求量的 Pod,使用量超出比例越多的 Pod 越優先被驅逐。
這邊我看文件看很久,最後看 Code 才瞭解,QoS 並不會傳入作為驅逐的判斷,但是因為資源使用量與請求量之差是決策的第一個參數,而資源的使用量與請求量之差與 QoS 有關,所以才容易被誤解驅逐跟 QoS 有關,所以 kubelet 不會使用 Pod 的 QoS 類別來決定驅逐順序。
當 kubelet 因 inode 或 PID 耗盡而驅逐 Pod 時,它會使用 Priority 來決定驅逐順序,因為 inode 和 PID 沒有請求。
Kubelet 會根據驅逐訊號更新 Node 狀態。例如,當 memory.available 觸發驅逐閾值時,Node 會被標記為 MemoryPressure。這些狀態資訊有助於我們了解 Node 的健康狀況,並根據需要採取相應的措施。
由於現在 Node Pressure Eviction 全仰賴 kubelet 的決策,但是 kubelet 的決策不會跟 control plane 溝通,這意味者它並沒有辦法拉取任何和 API Object 做決策,這樣缺乏彈性,所以介紹一個專案有潛力的專案。
Descheduler 是一個重新創建 Running Pod 的組件。
Descheduler 可以根據 Node 資源使用率來重新創建 Pod。
當 Node 使用率過低, Descheduler 可以主動驅逐上面的 Pod,讓 ClusterAutoscaler之類的工具主動縮減 Node。
當 Node 使用率過高,Descheduler 可以主動驅逐上面的 Pod,避免觸發 Node Pressure Eviction
在 Kubernetes 中,我們前面介紹的排程設定,例如 PodAffinity
,PodTopologySpread
,這些設定僅在排程時作用,但不能約束排程後的 Pod。Descheduler 會驅逐違反排程設定的 Pod,讓它們被重新創建和重新排程。
現在不建議 Control Plane Node 放 Worker Node,其中一個原因是因為 Control Plane Components 跟 Pod 容易會有競爭關係,descheduler 似乎可以解決這個問題,我們可以期待分散式 Kubernetes 嗎?