本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

Kubernetes 1.27:Kubernetes Pod 的原地資源調整(Alpha)

如果你部署過指定了 CPU 和/或記憶體資源的 Kubernetes Pod,你可能已經注意到更改資源值需要重啟 Pod。這對正在執行的工作負載來說一直是一個破壞性的操作……直到現在。

在 Kubernetes v1.27 中,我們增加了一個新的 Alpha 特性,允許使用者在不重啟容器的情況下調整分配給 Pod 的 CPU/記憶體資源。為了實現這一點,Pod 的容器中的 resources 欄位現在允許變更 cpumemory 資源。只需透過更新正在執行的 Pod 的規約即可更改它們。

這也意味著 Pod 規約中的 resources 欄位再也不能作為 Pod 實際資源的指標。監控工具和其他此類應用程式現在必須檢視 Pod 狀態中的新欄位。Kubernetes 透過 CRI(容器執行時介面)API 呼叫執行時(如 containerd,它負責執行容器),查詢執行中容器上強制執行的實際 CPU 和記憶體請求及限制。來自容器執行時的響應會反映在 Pod 的狀態中。

此外,還增加了一個新的用於調整大小的 restartPolicy。它讓使用者可以控制在資源調整大小時如何處理他們的容器。

v1.27 有哪些新內容?

除了在 Pod 的規約中增加了調整大小策略外,Pod 狀態的 containerStatuses 中還增加了一個名為 allocatedResources 的新欄位。該欄位反映了分配給 Pod 容器的節點資源。

此外,容器的狀態中還增加了一個名為 resources 的新欄位。該欄位反映了由容器執行時報告的、在執行中容器上配置的實際資源請求和限制。

最後,Pod 的狀態中增加了一個名為 resize 的新欄位,以顯示上次請求的調整大小的狀態。值為 Proposed 表示對請求的調整大小的確認,並表明請求已透過驗證和記錄。值為 InProgress 表示節點已接受調整大小請求,並且正在將調整大小請求應用於 Pod 的容器。值為 Deferred 意味著請求的調整大小目前無法被批准,節點將繼續重試。當其他 Pod 離開並釋放節點資源時,調整大小可能會被批准。值為 Infeasible 是一個訊號,表示節點無法滿足請求的調整大小。如果請求的調整大小超出了節點可以為 Pod 分配的最大資源,就會發生這種情況。

何時使用此功能

以下是此功能可能有用的一些示例

  • Pod 正在節點上執行,但資源過多或過少。
  • 由於叢集中 CPU 或記憶體不足,Pod 無法被排程,而該叢集中執行的 Pod 因過度配置而未得到充分利用。
  • 當節點中其他較低優先順序的 Pod 可以被縮小或移動時,驅逐某些需要更多資源以將其排程到更大節點上的有狀態 Pod 是一項昂貴或具有破壞性的操作。

如何使用此功能

為了在 v1.27 中使用此功能,必須啟用 InPlacePodVerticalScaling 特性門控。可以如下所示啟動一個啟用了此功能的本地叢集

root@vbuild:~/go/src/k8s.io/kubernetes# FEATURE_GATES=InPlacePodVerticalScaling=true ./hack/local-up-cluster.sh
go version go1.20.2 linux/arm64
+++ [0320 13:52:02] Building go targets for linux/arm64
    k8s.io/kubernetes/cmd/kubectl (static)
    k8s.io/kubernetes/cmd/kube-apiserver (static)
    k8s.io/kubernetes/cmd/kube-controller-manager (static)
    k8s.io/kubernetes/cmd/cloud-controller-manager (non-static)
    k8s.io/kubernetes/cmd/kubelet (non-static)
...
...
Logs:
  /tmp/etcd.log
  /tmp/kube-apiserver.log
  /tmp/kube-controller-manager.log

  /tmp/kube-proxy.log
  /tmp/kube-scheduler.log
  /tmp/kubelet.log

To start using your cluster, you can open up another terminal/tab and run:

  export KUBECONFIG=/var/run/kubernetes/admin.kubeconfig
  cluster/kubectl.sh

Alternatively, you can write to the default kubeconfig:

  export KUBERNETES_PROVIDER=local

  cluster/kubectl.sh config set-cluster local --server=https://:6443 --certificate-authority=/var/run/kubernetes/server-ca.crt
  cluster/kubectl.sh config set-credentials myself --client-key=/var/run/kubernetes/client-admin.key --client-certificate=/var/run/kubernetes/client-admin.crt
  cluster/kubectl.sh config set-context local --cluster=local --user=myself
  cluster/kubectl.sh config use-context local
  cluster/kubectl.sh

本地叢集啟動並執行後,Kubernetes 使用者可以排程帶有資源的 Pod,並透過 kubectl 調整 Pod 的大小。以下演示影片展示瞭如何使用此功能的示例。

用例示例

基於雲的開發環境

在這種情況下,開發人員或開發團隊在本地編寫程式碼,但在具有與生產環境一致配置的 Kubernetes Pod 中構建和測試他們的程式碼。當開發人員編寫程式碼時,這類 Pod 需要最少的資源,但當他們構建程式碼或執行一系列測試時,則需要顯著更多的 CPU 和記憶體。這個用例可以利用原地 Pod 調整大小功能(藉助 eBPF 的一些幫助)來快速調整 Pod 的資源,並避免核心的 OOM(記憶體不足)殺手終止他們的程序。

這個 KubeCon 北美 2022 會議演講闡述了該用例。

Java 程序初始化 CPU 需求

一些 Java 應用程式在初始化期間可能需要比正常程序操作時顯著更多的 CPU。如果這類應用程式指定的 CPU 請求和限制適合正常操作,它們可能會遭受非常長的啟動時間。這類 Pod 可以在建立 Pod 時請求更高的 CPU 值,並在應用程式完成初始化後,將其大小調整到正常執行所需的大小。

已知問題

此功能在 v1.27 中進入 Alpha 階段。以下是使用者可能遇到的一些已知問題

  • v1.6.9 以下的 containerd 版本不具備此功能完整端到端操作所需的 CRI 支援。調整 Pod 大小的嘗試將似乎“卡”在 InProgress 狀態,並且即使新的資源可能已在執行的容器上生效,Pod 狀態中的 resources 欄位也永遠不會更新。
  • Pod 調整大小可能會與其他 Pod 更新發生競爭條件,導致 Pod 調整大小的實施延遲。
  • 在 Pod 狀態中反映調整後的容器資源可能需要一些時間。
  • 此功能不支援靜態 CPU 管理策略。

致謝

此功能是一個非常協作的 Kubernetes 社群共同努力的結果。這裡要特別感謝為實現這一目標貢獻了無數小時並提供了幫助的眾多人士中的幾位。

  • @thockin 進行了注重細節的 API 設計和嚴密的程式碼審查。
  • @derekwaynecarr 簡化了設計並進行了徹底的 API 和節點審查。
  • @dchen1107 帶來了來自 Borg 的豐富知識,幫助我們避免了陷阱。
  • @ruiwen-zhao 添加了 containerd 支援,從而實現了完整的端到端實現。
  • @wangchen615 實現了全面的端到端測試並推動了排程程式的修復。
  • @bobbypage 提供了寶貴的幫助,準備了 CI 並迅速調查問題,在我休假期間為我代勞。
  • @Random-Liu 進行了徹底的 kubelet 審查並識別了有問題的競爭條件。
  • @Huang-Wei@ahg-g@alculquicondor 幫助完成了排程程式的更改。
  • @mikebrow @marosset 在短時間內進行了審查,幫助 CRI 的更改進入了 v1.25。
  • @endocrimes@ehashman 幫助確保了經常被忽視的測試處於良好狀態。
  • @mrunalp 審查了 cgroupv2 的更改,並確保了對 v1 與 v2 的清晰處理。
  • @liggitt@gjkim42 在合併後追蹤、根本原因分析了重要的遺漏問題。
  • @SergeyKanzhelev 在最後階段支援和引導了各種問題。
  • @pdgetrf 使第一個原型成為現實。
  • @dashpole 讓我快速瞭解了“Kubernetes 的做事方式”。
  • @bsalamat@kgolab 在早期階段提供了非常周到的見解和建議。
  • @sftim@tengqm 確保了文件易於理解。
  • @dims 無處不在,並在關鍵時刻幫助實現合併。
  • 釋出團隊確保了專案的健康發展。

還要特別感謝我非常支援的管理層 丁曉寧博士熊鷹博士 的耐心和鼓勵。

參考資料

針對應用開發者

針對叢集管理員