為系統守護程序保留計算資源

Kubernetes 節點可以排程到 `Capacity`。預設情況下,Pod 可以佔用節點上所有可用容量。這是一個問題,因為節點通常執行許多系統守護程序來驅動作業系統和 Kubernetes 本身。除非為這些系統守護程序預留資源,否則 Pod 和系統守護程序會爭奪資源,導致節點上的資源飢餓問題。

`kubelet` 暴露了一個名為“Node Allocatable”(節點可分配)的功能,有助於為系統守護程序預留計算資源。Kubernetes 建議叢集管理員根據每個節點上的工作負載密度配置“Node Allocatable”。

準備工作

你需要有一個 Kubernetes 叢集,並且 kubectl 命令列工具已配置為與你的叢集通訊。建議在至少有兩個節點(不充當控制平面主機)的叢集上執行本教程。如果你還沒有叢集,可以使用 minikube 建立一個,或者使用這些 Kubernetes 演練場之一。

你可以使用 kubelet 配置檔案 配置以下 kubelet 配置設定

節點可分配(Node Allocatable)

node capacity

Kubernetes 節點上的“Allocatable”(可分配)定義為可用於 Pod 的計算資源量。排程器不會超額分配“Allocatable”。目前支援“CPU”、“記憶體”和“臨時儲存”。

Node Allocatable 作為 API 中 `v1.Node` 物件的一部分,以及 CLI 中 `kubectl describe node` 的一部分公開。

可以在 `kubelet` 中為兩類系統守護程序預留資源。

啟用 QoS 和 Pod 級別 cgroup

為了在節點上正確實施節點可分配約束,你必須透過 `cgroupsPerQOS` 設定啟用新的 cgroup 層次結構。此設定預設啟用。啟用後,`kubelet` 將把所有終端使用者 Pod 放在由 `kubelet` 管理的 cgroup 層次結構下。

配置 cgroup 驅動程式

`kubelet` 支援使用 cgroup 驅動程式操縱主機上的 cgroup 層次結構。該驅動程式透過 `cgroupDriver` 設定進行配置。

支援的值如下:

  • `cgroupfs` 是預設驅動程式,它透過直接操縱主機上的 cgroup 檔案系統來管理 cgroup 沙盒。
  • `systemd` 是一個替代驅動程式,它使用瞬態切片(transient slices)管理 cgroup 沙盒,以支援該 init 系統所支援的資源。

根據相關容器執行時的配置,操作員可能需要選擇特定的 cgroup 驅動程式以確保系統行為正確。例如,如果操作員使用 `containerd` 執行時提供的 `systemd` cgroup 驅動程式,則 `kubelet` 必須配置為使用 `systemd` cgroup 驅動程式。

Kube 預留

  • KubeletConfiguration 設定:`kubeReserved: {}`。示例值 `{cpu: 100m, memory: 100Mi, ephemeral-storage: 1Gi, pid=1000}`
  • KubeletConfiguration 設定:`kubeReservedCgroup: ""`

`kubeReserved` 旨在捕獲 Kubernetes 系統守護程序(如 `kubelet`、`容器執行時` 等)的資源預留。它不用於為作為 Pod 執行的系統守護程序預留資源。`kubeReserved` 通常是節點上 `Pod 密度` 的函式。

除了 `cpu`、`memory` 和 `ephemeral-storage` 之外,還可以指定 `pid` 以便為 Kubernetes 系統守護程序預留指定數量的程序 ID。

要選擇性地對 Kubernetes 系統守護程序強制執行 `kubeReserved`,請將 kube 守護程序的父控制組指定為 `kubeReservedCgroup` 設定的值,並將 `kube-reserved` 新增到 `enforceNodeAllocatable`

建議將 Kubernetes 系統守護程序放置在頂級控制組下(例如,在 systemd 機器上為 `runtime.slice`)。每個系統守護程序理想情況下應在其自己的子控制組中執行。有關建議的控制組層次結構的更多詳細資訊,請參閱設計提案

請注意,如果 `kubeReservedCgroup` 不存在,Kubelet 不會建立它。如果指定了無效的 cgroup,kubelet 將無法啟動。使用 `systemd` cgroup 驅動程式時,應遵循特定模式來定義 cgroup 的名稱:該名稱應是你為 `kubeReservedCgroup` 設定的值,並附加 `.slice`。

系統預留

  • KubeletConfiguration 設定:`systemReserved: {}`。示例值 `{cpu: 100m, memory: 100Mi, ephemeral-storage: 1Gi, pid=1000}`
  • KubeletConfiguration 設定:`systemReservedCgroup: ""`

`systemReserved` 旨在捕獲 OS 系統守護程序(如 `sshd`、`udev` 等)的資源預留。`systemReserved` 也應為 `kernel` 預留 `memory`,因為目前 Kubernetes 中不將 `kernel` 記憶體計入 Pod。還建議為使用者登入會話預留資源(在 systemd 中為 `user.slice`)。

除了 `cpu`、`memory` 和 `ephemeral-storage` 之外,還可以指定 `pid` 以便為 OS 系統守護程序預留指定數量的程序 ID。

要選擇性地對系統守護程序強制執行 `systemReserved`,請將 OS 系統守護程序的父控制組指定為 `systemReservedCgroup` 設定的值,並將 `system-reserved` 新增到 `enforceNodeAllocatable`

建議將作業系統系統守護程序放置在頂級控制組下(例如,在 systemd 機器上為 `system.slice`)。

請注意,如果 `systemReservedCgroup` 不存在,`kubelet` 不會建立它。如果指定了無效的 cgroup,`kubelet` 將失敗。使用 `systemd` cgroup 驅動程式時,應遵循特定模式來定義 cgroup 的名稱:該名稱應是你為 `systemReservedCgroup` 設定的值,並附加 `.slice`。

顯式預留 CPU 列表

功能狀態: `Kubernetes v1.17 [穩定]`

KubeletConfiguration 設定:`reservedSystemCPUs:`。示例值 `0-3`

`reservedSystemCPUs` 旨在為 OS 系統守護程序和 Kubernetes 系統守護程序定義一個明確的 CPU 集合。`reservedSystemCPUs` 適用於不打算為 OS 系統守護程序和 Kubernetes 系統守護程序在 cpuset 資源方面定義單獨的頂級 cgroup 的系統。如果 Kubelet 沒有 `kubeReservedCgroup` 和 `systemReservedCgroup`,則 `reservedSystemCPUs` 提供的明確 cpuset 將優先於 `kubeReservedCgroup` 和 `systemReservedCgroup` 選項定義的 CPU。

此選項專為電信/NFV 用例設計,在這些用例中,不受控制的中斷/計時器可能會影響工作負載效能。你可以使用此選項為系統/Kubernetes 守護程序以及中斷/計時器定義明確的 cpuset,這樣系統上的其餘 CPU 就可以專門用於工作負載,受不受控制的中斷/計時器的影響較小。要將系統守護程序、Kubernetes 守護程序以及中斷/計時器移動到此選項定義的明確 cpuset,應使用 Kubernetes 之外的其他機制。例如:在 Centos 中,你可以使用 tuned 工具集來完成此操作。

逐出閾值

KubeletConfiguration 設定:`evictionHard: {memory.available: "100Mi", nodefs.available: "10%", nodefs.inodesFree: "5%", imagefs.available: "15%"}`。示例值:`{memory.available: "<500Mi"}`

節點級別的記憶體壓力會導致系統 OOM,這會影響整個節點和其上執行的所有 Pod。節點可能會暫時離線,直到記憶體被回收。為了避免(或降低可能性)系統 OOM,kubelet 提供了資源不足管理。驅逐僅支援 `memory` 和 `ephemeral-storage`。透過 `evictionHard` 設定預留一些記憶體,`kubelet` 會在節點上的記憶體可用性低於預留值時嘗試驅逐 Pod。假設節點上不存在系統守護程序,Pod 不能使用超過 `capacity - eviction-hard` 的資源。因此,為驅逐預留的資源不適用於 Pod。

強制執行節點可分配

KubeletConfiguration 設定:`enforceNodeAllocatable: [pods]`。示例值:`[pods,system-reserved,kube-reserved]`

排程器將“Allocatable”視為 Pod 的可用 `capacity`。

預設情況下,`kubelet` 會對所有 Pod 強制執行“Allocatable”。當所有 Pod 的總使用量超過“Allocatable”時,透過驅逐 Pod 來執行此操作。有關驅逐策略的更多詳細資訊,請參見節點壓力驅逐頁面。此強制執行透過將 `pods` 值指定給 KubeletConfiguration 設定 `enforceNodeAllocatable` 來控制。

可以選擇性地讓 `kubelet` 透過在同一設定中指定 `kube-reserved` 和 `system-reserved` 值來強制執行 `kubeReserved` 和 `systemReserved`。請注意,要強制執行 `kubeReserved` 或 `systemReserved`,需要分別指定 `kubeReservedCgroup` 或 `systemReservedCgroup`。

通用指南

系統守護程序應被視為與Guaranteed Pods 類似。系統守護程序可以在其限制控制組內突發,此行為需要作為 Kubernetes 部署的一部分進行管理。例如,`kubelet` 應該有自己的控制組,並與容器執行時共享 `kubeReserved` 資源。但是,如果強制執行 `kubeReserved`,Kubelet 就不能突發並用盡所有可用的節點資源。

在強制執行 `systemReserved` 預留時要格外小心,因為它可能導致關鍵系統服務 CPU 飢餓、OOM 終止或無法在節點上派生。建議僅在使用者對節點進行了詳盡的分析以得出精確估計並有信心在組中任何程序 OOM 終止時恢復的情況下,才強制執行 `systemReserved`。

  • 首先對 `pods` 強制執行“Allocatable”。
  • 一旦建立足夠的監控和警報來跟蹤 kube 系統守護程序,嘗試根據使用啟發式方法強制執行 `kubeReserved`。
  • 如果絕對必要,隨著時間的推移強制執行 `systemReserved`。

隨著越來越多的功能新增,kube 系統守護程序的資源需求可能會隨著時間增長。隨著時間的推移,Kubernetes 專案將嘗試降低節點系統守護程序的利用率,但目前這不是一個優先事項。因此,預計未來版本中 `Allocatable` 容量會下降。

示例場景

以下是一個說明節點可分配計算的示例

  • 節點有 `32Gi` 記憶體、`16 個 CPU` 和 `100Gi` 儲存
  • `kubeReserved` 設定為 `{cpu: 1000m, memory: 2Gi, ephemeral-storage: 1Gi}`
  • `systemReserved` 設定為 `{cpu: 500m, memory: 1Gi, ephemeral-storage: 1Gi}`
  • `evictionHard` 設定為 `{memory.available: "<500Mi", nodefs.available: "<10%"}`

在這種情況下,“Allocatable”將是 14.5 個 CPU,28.5Gi 記憶體和 `88Gi` 本地儲存。排程器確保該節點上所有 Pod 的總記憶體 `requests` 不超過 28.5Gi,儲存不超過 88Gi。當 Pod 的總記憶體使用量超過 28.5Gi 或總磁碟使用量超過 88Gi 時,Kubelet 將驅逐 Pod。如果節點上的所有程序都儘可能地消耗 CPU,Pod 總共不能消耗超過 14.5 個 CPU。

如果未強制執行 `kubeReserved` 和/或 `systemReserved` 且系統守護程序超出其預留,當節點總記憶體使用量高於 31.5Gi 或 `儲存` 大於 90Gi 時,`kubelet` 將驅逐 Pod。

上次修改時間:2024 年 6 月 4 日太平洋標準時間凌晨 3:39:改進“為系統守護程序預留計算資源”文件 (#45771) (bc35539293)