K8s如何启用cgroup2支持?

时间:2022-11-17 14:02:51

什么是 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 进行了多项改进,例如:

  • 统一核算不同类型的内存分配(网络内存、内核内存等)
  • 考虑非即时资源变化,例如页面缓存回写

一些 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。例如:

使用 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 对集群所有的节点,使用相同的 ​​KubeletConfiguration​​。 ​​KubeletConfiguration​​ 存放于 ​​kube-system​​ 命名空间下的某个 ​​ConfigMap​​ 对象中。

执行 ​​init​​、​​join​​ 和 ​​upgrade​​ 等子命令会促使 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 有以下优势:

  • 统一核算不同类型的内存分配(网络内存、内核内存等)
  • 考虑非即时资源变化,例如页面缓存回写

推荐在使用 Kubernetes v1.25及以上版本时, 使用支持 cgroup v2 的linux 和 CRI. 并启用 Kubernetes 的cgroup v2 功能.

????️参考文档