Please enable Javascript to view the contents

如何升级 Kubernetes 节点的 cgroup 版本

 ·  ☕ 2 分钟

1. cgroup v1 与 v2 接口路径差别

  • v1
1
2
3
4
/sys/fs/cgroup/cpu/cpu.cfs_quota_us
/sys/fs/cgroup/cpu/cpuacct.usage
/sys/fs/cgroup/memory/memory.limit_in_bytes
/sys/fs/cgroup/memory/memory.usage_in_bytes
  • v2
1
2
3
4
/sys/fs/cgroup/cpu.max
/sys/fs/cgroup/cpu.stat
/sys/fs/cgroup/memory.max
/sys/fs/cgroup/memory.current

cgroup v2 是 v1 的升级版本,具有更统一的资层级管理、精准的资源隔离等优点。但也导致了,写代码时,读取相关接口文件时路径不一样,需要做兼容处理。另外,一个思路就是,统一到一个 cgroup 版本。

Kubernetes 默认支持 cgroup v2,但 Pod 实际使用哪种 cgroup,取决于宿主机内核挂载的 cgroup 类型。

2. 查看全部节点的 cgroup 配置

找一个 DaemonSet,查看全部节点上 Pod 的 cgroup 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
for pod in $(kubectl -n monitoring get pod -l k8s-app=node-exporter -o jsonpath='{.items[*].metadata.name}'); do
  node=$(kubectl -n monitoring get pod $pod -o jsonpath='{.spec.nodeName}')
  runtime=$(kubectl get node $node -o jsonpath='{.status.nodeInfo.containerRuntimeVersion}')
  os=$(kubectl get node $node -o jsonpath='{.status.nodeInfo.osImage}')

  echo "===== Pod: $pod | Node: $node | Runtime: $runtime | OS: $os ====="

  if kubectl -n monitoring exec $pod -- test -f /sys/fs/cgroup/cpu.max 2>/dev/null; then
    echo "cgroup v2"
    kubectl -n monitoring exec $pod -- cat /sys/fs/cgroup/cpu.max
  else
    echo "cgroup v1"
    if kubectl -n monitoring exec $pod -- test -f /sys/fs/cgroup/cpu/cpu.cfs_quota_us 2>/dev/null; then
      kubectl -n monitoring exec $pod -- cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us
    else
      echo "cpu.cfs_quota_us not found"
    fi
  fi
done

我发现,Ubuntu 20 默认使用的是 cgroup v1,而 Ubuntu 22 默认使用的是 cgroup v2。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
===== Pod: node-exporter-2d7q2 | Node: node-4090-76 | Runtime: containerd://1.6.31 | OS: Ubuntu 20.04.1 LTS =====
cgroup v1
-1
===== Pod: node-exporter-2z9ts | Node: node-4090-53 | Runtime: containerd://1.6.31 | OS: Ubuntu 20.04.1 LTS =====
cgroup v1
-1
===== Pod: node-exporter-462mh | Node: node-4090-ywd-04 | Runtime: containerd://1.6.31 | OS: Ubuntu 22.04.2 LTS =====
cgroup v2
max 100000
===== Pod: node-exporter-4bskd | Node: k8s-cpu-2 | Runtime: containerd://1.6.31 | OS: Ubuntu 22.04.3 LTS =====
cgroup v2
max 100000
===== Pod: node-exporter-4kz4s | Node: node-a800-52 | Runtime: containerd://1.6.31 | OS: Ubuntu 20.04.1 LTS =====
cgroup v1
-1
===== Pod: node-exporter-4lvsm | Node: node-4090-d2r1-25 | Runtime: containerd://1.6.31 | OS: Ubuntu 20.04.1 LTS =====
cgroup v1
-1
===== Pod: node-exporter-592wh | Node: node-a800-gc-09 | Runtime: containerd://1.6.31 | OS: Ubuntu 20.04.1 LTS =====
cgroup v1

3. 升级节点的 cgroup 版本

虽然 4.5 就开始引入了 cgroup v2,但是推荐在 5.4 及之后版本才需要考虑生产启用。

  • 查看使用的 cgroup 版本
1
stat -fc %T /sys/fs/cgroup/

输出 cgroup2fs -> cgroup v2,输出 tmpfs -> cgroup v1

  • 查看内核版本
1
uname -r
1
5.4.0-169-generic
  • 编辑 /etc/default/grub
1
vim /etc/default/grub

GRUB_CMDLINE_LINUX 一行引号内添加参数 systemd.unified_cgroup_hierarchy=1

  • 更新 grub 配置
1
update-grub
  • 重启系统
1
reboot

4. 检查 Containerd cgroup 配置

1
cat /etc/containerd/config.toml | grep SystemdCgroup
1
            SystemdCgroup = true

SystemdCgroup 设置为 true 时,Containerd 使用 cgroup v2。

5. 检查 Kubelet cgroup 配置

1
cat /var/lib/kubelet/config.yaml |grep cgroupDriver
1
cgroupDriver: systemd

cgroupDriver 设置为 systemd 时,Kubelet 使用 cgroup v2。

6. 遇到的问题

  • 内核版本太低,无法启用 cgroup v2
1
Warning Failed 6s (x5 over 91s) kubelet Error: failed to create containerd task: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error setting cgroup config for procHooks process: open /sys/fs/cgroup/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podd427dc62_807d_4218_b638_ddf5a6c6f7e7.slice/cri-containerd-node-exporter.scope/cpuset.cpus: no such file or directory: unknown

在内核 4.15 的主机上遇到这个报错,尝试清理 Pod、清空 Containerd 数据均无法解决。


微信公众号
作者
微信公众号