K8s如何啟用cgroup2支援?

什麼是 cgroup

📚️Reference:

control groups(控制組),通常被稱為cgroup,是Linux內核的一項功能。它允許將進程組織成分層的組,然後限制和監控各種資源的使用。 內核的cgroup介面是通過一個叫做cgroupfs的偽文件系統提供的。 分組是在核心的cgroup內核程式碼中實現的,而資源跟蹤和限制是在一組每個資源類型的子系統中實現的(記憶體、CPU等等)。

cgroup 是容器和雲原生的底層技術棧. kubelet 和 CRI 都需要對接 cgroup 來強制執行為 Pod 和容器管理資源,即: requests/limits 和 cpu/memory。

Linux 中有兩個 cgroup 版本:cgroup v1 和 cgroup v2。cgroup v2 是新一代的 cgroup API。

Kubernetes 自 v1.25 起 cgroup2 特性正式 stable.

cgroup v2 有哪些優勢

📚️Reference:

cgroup v2 提供了一個具有增強資源管理能力的統一控制系統。

cgroup v2 對 cgroup v1 進行了多項改進,例如:

  • API 中單個統一的層次結構設計
  • 更安全的子樹委派給容器
  • 更新的功能特性, 例如壓力阻塞資訊(Pressure Stall Information,PSI)
  • 跨多個資源的增強資源分配管理和隔離
    • 統一核算不同類型的記憶體分配(網路記憶體、內核記憶體等)
    • 考慮非即時資源變化,例如頁面快取回寫

一些 Kubernetes 特性專門使用 cgroup v2 來增強資源管理和隔離。 例如,MemoryQoS 特性改進了記憶體 QoS 並依賴於 cgroup v2 原語。

使用 cgroup v2 前提

📚️Reference:

cgroup v2 具有以下要求:

  • 作業系統發行版啟用 cgroup v2
    • Ubuntu(從 21.10 開始,推薦 22.04+)
    • Debian GNU/Linux(從 Debian 11 Bullseye 開始)
    • Fedora(從 31 開始)
    • RHEL 和類似 RHEL 的發行版(從 9 開始)
  • Linux 內核為 5.8 或更高版本
  • 容器運行時支援 cgroup v2。例如:
  • kubelet 和容器運行時被配置為使用 systemd cgroup 驅動

使用 cgroup v2

📝Notes:

這裡以 Debian 11 Bullseye + containerd v1.4 為例.

啟用並檢查 Linux 節點的 cgroup v2

Debian 11 Bullseye 默認已啟用 cgroup v2.

可以通過如下命令驗證:

stat -fc %T /sys/fs/cgroup/
  • 對於 cgroup v2,輸出為 cgroup2fs
  • 對於 cgroup v1,輸出為 tmpfs

如果沒有啟用, 可以通過在 /etc/default/grub 下的 GRUB_CMDLINE_LINUX 中添加 systemd.unified_cgroup_hierarchy=1, 然後執行 sudo update-grub

📝Notes:
如果是樹莓派, 標準 Raspberry Pi OS 安裝時不會啟用 cgroups。 需要 cgroups 來啟動 systemd 服務。可以通過將 cgroup_memory=1 cgroup_enable=memory systemd.unified_cgroup_hierarchy=1 附加到 /boot/cmdline.txt 來啟用 cgroups
並重啟生效

kubelet 使用 systemd cgroup 驅動

kubeadm 支援在執行 kubeadm init 時,傳遞一個 KubeletConfiguration 結構體。 KubeletConfiguration 包含 cgroupDriver 欄位,可用於控制 kubelet 的 cgroup 驅動。

說明: 在版本 1.22 中,如果用戶沒有在 KubeletConfiguration 中設置 cgroupDriver 欄位, kubeadm init 會將它設置為默認值 systemd

這是一個最小化的示例,其中顯式的配置了此欄位:

# kubeadm-config.yaml
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.21.0
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd

這樣一個配置文件就可以傳遞給 kubeadm 命令了:

kubeadm init --config kubeadm-config.yaml

說明:

Kubeadm 對集群所有的節點,使用相同的 KubeletConfigurationKubeletConfiguration 存放於 kube-system 命名空間下的某個 ConfigMap 對象中。

執行 initjoinupgrade 等子命令會促使 kubeadm 將 KubeletConfiguration 寫入到文件 /var/lib/kubelet/config.yaml 中, 繼而把它傳遞給本地節點的 kubelet。

containerd 使用 systemd cgroup 驅動

編輯 /etc/containerd/config.toml:

[plugins.cri.containerd.runtimes.runc.options]
    SystemdCgroup = true

升級監控組件以支援 cgroup v2 監控

📚️Reference:

cgroup v2 使用一個與 cgroup v1 不同的 API,因此如果有任何應用直接訪問 cgroup 文件系統, 則需要將這些應用更新為支援 cgroup v2 的版本。例如:

  • 一些第三方監控和安全代理可能依賴於 cgroup 文件系統。你要將這些代理更新到支援 cgroup v2 的版本。
  • 如果以獨立的 DaemonSet 的形式運行 cAdvisor 以監控 Pod 和容器, 需將其更新到 v0.43.0 或更高版本。
  • 如果你使用 JDK,推薦使用 JDK 11.0.16 及更高版本或 JDK 15 及更高版本, 以便完全支援 cgroup v2

完成🎉🎉🎉

總結

Kubernetes 自 v1.25 起 cgroup2 特性正式 stable. cgroup2 相比 cgroup v1 有以下優勢:

  • API 中單個統一的層次結構設計
  • 更安全的子樹委派給容器
  • 更新的功能特性, 例如壓力阻塞資訊(Pressure Stall Information,PSI)
  • 跨多個資源的增強資源分配管理和隔離
    • 統一核算不同類型的記憶體分配(網路記憶體、內核記憶體等)
    • 考慮非即時資源變化,例如頁面快取回寫

推薦在使用 Kubernetes v1.25及以上版本時, 使用支援 cgroup v2 的linux 和 CRI. 並啟用 Kubernetes 的cgroup v2 功能.

📚️參考文檔

本文由東風微鳴技術部落格 EWhisper.cn 編寫!