在新 Linux 发行版上切换 cgroups 版本
后知后觉 暂无评论

cgroups (control groups) 是一个 Linux 内核功能,用来限制、分配和隔离进程的资源使用(CPU、内存、磁盘 I/O、网络等)。

前言

cgroups v1 发布于 2008 年,因此很多功能和特性已经不适应现代操作系统,cgroups v1 的接任者 cgroups v2 由 Facebook 的工程师 Tejun Heo 开发,并且合并进了 kernel 4.5 版本,但并未默认启用。

如何辨别版本

从 Debian 11、Ubuntu 22.04 LTS、Red Hat 9、CentOS 9 stream 开始,默认启用 cgroups v2。

如果想分辨当前使用的 Linux 操作系统使用的是哪个版本的 cgroups 也很简单,只需要检查 /sys/fs/cgroup 路径下的结构即可。

cgroups v1

在 cgroups v1 中可以看到目录结构状态的文件夹。

$ ls -l /sys/fs/cgroup/
total 0
dr-xr-xr-x 5 root root  0 Aug 12 03:27 blkio/
lrwxrwxrwx 1 root root 11 Aug 12 03:27 cpu -> cpu,cpuacct/
lrwxrwxrwx 1 root root 11 Aug 12 03:27 cpuacct -> cpu,cpuacct/
dr-xr-xr-x 5 root root  0 Aug 12 03:27 cpu,cpuacct/
dr-xr-xr-x 2 root root  0 Aug 12 03:27 cpuset/
dr-xr-xr-x 5 root root  0 Aug 12 03:27 devices/
dr-xr-xr-x 3 root root  0 Aug 12 03:27 freezer/
dr-xr-xr-x 2 root root  0 Aug 12 03:27 hugetlb/
dr-xr-xr-x 5 root root  0 Aug 12 03:27 memory/
lrwxrwxrwx 1 root root 16 Aug 12 03:27 net_cls -> net_cls,net_prio/
dr-xr-xr-x 2 root root  0 Aug 12 03:27 net_cls,net_prio/
lrwxrwxrwx 1 root root 16 Aug 12 03:27 net_prio -> net_cls,net_prio/
dr-xr-xr-x 2 root root  0 Aug 12 03:27 perf_event/
dr-xr-xr-x 5 root root  0 Aug 12 03:27 pids/
dr-xr-xr-x 2 root root  0 Aug 12 03:27 rdma/
dr-xr-xr-x 5 root root  0 Aug 12 03:27 systemd/
dr-xr-xr-x 5 root root  0 Aug 12 03:27 unified/

cgroups v2

在 cgroups v2 中,不再以目录形式出现,而是零大小的入口文件形式,并且入口文件的命名更加规范和整齐。

$ ls -l /sys/fs/cgroup
total 0
-r--r--r--  1 root root 0 Aug 12 11:24 cgroup.controllers
-rw-r--r--  1 root root 0 Aug 12 11:24 cgroup.max.depth
-rw-r--r--  1 root root 0 Aug 12 11:24 cgroup.max.descendants
-rw-r--r--  1 root root 0 Aug 12 11:24 cgroup.procs
-r--r--r--  1 root root 0 Aug 12 11:24 cgroup.stat
-rw-r--r--  1 root root 0 Aug 10 17:46 cgroup.subtree_control
-rw-r--r--  1 root root 0 Aug 12 11:24 cgroup.threads
-rw-r--r--  1 root root 0 Aug 12 11:24 cpu.pressure
-r--r--r--  1 root root 0 Aug 12 11:24 cpu.stat
-r--r--r--  1 root root 0 Aug 12 11:24 cpuset.cpus.effective
-r--r--r--  1 root root 0 Aug 12 11:24 cpuset.mems.effective
drwxr-xr-x  2 root root 0 Jul 12 15:52 dev-hugepages.mount
drwxr-xr-x  2 root root 0 Jul 12 15:52 dev-mqueue.mount
drwxr-xr-x  2 root root 0 Aug 10 17:46 init.scope
-rw-r--r--  1 root root 0 Aug 12 11:24 io.cost.model
-rw-r--r--  1 root root 0 Aug 12 11:24 io.cost.qos
-rw-r--r--  1 root root 0 Aug 12 11:24 io.pressure
-r--r--r--  1 root root 0 Aug 12 11:24 io.stat
-r--r--r--  1 root root 0 Aug 12 11:24 memory.numa_stat
-rw-r--r--  1 root root 0 Aug 12 11:24 memory.pressure
-r--r--r--  1 root root 0 Aug 12 11:24 memory.stat
drwxr-xr-x  2 root root 0 Jul 12 15:52 sys-fs-fuse-connections.mount
drwxr-xr-x  2 root root 0 Jul 12 15:52 sys-kernel-config.mount
drwxr-xr-x  2 root root 0 Jul 12 15:52 sys-kernel-debug.mount
drwxr-xr-x  2 root root 0 Jul 12 15:52 sys-kernel-tracing.mount
drwxr-xr-x 57 root root 0 Aug 12 06:48 system.slice
drwxr-xr-x  3 root root 0 Aug 12 11:05 user.slice

Mixed v1 v2

特殊的是,在部分发行版中(比如 Debian 11),启用了兼容性 cgroups 特性,即同时启用 cgroups v1 和 cgroups v2,这种也很好分辨,可以在 /sys/fs/cgroup 目录中发现一个名为 -.mount 的目录。

$ ls /sys/fs/cgroup
-.mount                 cpuset.cpus.effective  memory.pressure
cgroup.controllers      cpuset.mems.effective  memory.stat
cgroup.max.depth        dev-hugepages.mount    sys-fs-fuse-connections.mount
cgroup.max.descendants  dev-mqueue.mount       sys-kernel-config.mount
cgroup.procs            init.scope             sys-kernel-debug.mount
cgroup.stat             io.cost.model          sys-kernel-tracing.mount
cgroup.subtree_control  io.cost.qos            system.slice
cgroup.threads          io.pressure            user.slice
cpu.pressure            io.stat
cpu.stat                memory.numa_stat

子目录结构

$ ls /sys/fs/cgroup/-.mount/
cgroup.controllers      cpuset.cpus.partition     memory.low
cgroup.events           cpuset.mems               memory.max
cgroup.freeze           cpuset.mems.effective     memory.min
cgroup.max.depth        hugetlb.2MB.current       memory.numa_stat
cgroup.max.descendants  hugetlb.2MB.events        memory.oom.group
cgroup.procs            hugetlb.2MB.events.local  memory.pressure
cgroup.stat             hugetlb.2MB.max           memory.stat
cgroup.subtree_control  hugetlb.2MB.rsvd.current  memory.swap.current
cgroup.threads          hugetlb.2MB.rsvd.max      memory.swap.events
cgroup.type             io.max                    memory.swap.high
cpu.max                 io.pressure               memory.swap.max
cpu.pressure            io.stat                   pids.current
cpu.stat                io.weight                 pids.events
cpu.weight              memory.current            pids.max
cpu.weight.nice         memory.events             rdma.current
cpuset.cpus             memory.events.local       rdma.max
cpuset.cpus.effective   memory.high

启用 cgroups v2

如果系统内核版本 > 4.5 ,那么就可以通过内核参数的形式启用 cgroups v2 ,不过需要注意的是,部分未默认开启的发行版强制开启后,仓库内的软件可能存在不兼容的问题。

对于使用 systemd 引导的系统,可以在引导文件 /etc/default/grub 中添加如下一行,启用 v2 版本。

GRUB_CMDLINE_LINUX_DEFAULT="systemd.unified_cgroup_hierarchy=yes"

关于 systemd.unified_cgroup_hierarchy 字段的说明(引用自金步国翻译文档):

  • systemd.unified_cgroup_hierarchy
    设置是否使用单一层次资源控制接口(cgroups-v2)。既可以明确设为一个布尔值,也可以仅使用此选项而不设置任何参数(相当于设为 yes )。 设为 yes 表示明确仅使用新式的 cgroups-v2,设为 no 表示当 cgroups-v2 不可用时可以回退到使用 cgroups-v1 (也就是可以混合使用 v1 与 v2)。
    此选项的默认值取决于编译时的 -Ddefault-hierarchy= meson 设置。 如果内核版本低于Linux-4.5(完全不支持 v2), 那么将无条件的完全使用 cgroups-v1 (无视此处的设置)。
  • systemd.legacy_systemd_cgroup_controller
    此选项仅在上一个选项值为 no 时生效。既可以明确设为一个布尔值,也可以仅使用此选项而不设置任何参数(相当于设为 yes )。 设为 yes 表示 禁止混合使用 cgroups-v1 与 cgroups-v2 , 也就是必须完全仅仅使用老旧的 cgroups-v1 。设为 no 表示 允许混合使用 cgroups-v1 与 cgroups-v2 。
    此选项的默认值取决于编译时的 -Ddefault-hierarchy= meson 设置。 如果内核版本低于Linux-4.5(完全不支持 v2), 那么将无条件的完全使用 cgroups-v1 (无视此处的设置)。

修改完成后需要重新生成引导文件

md5sum /boot/grub/grub.cfg
sudo vim /etc/default/grub
sudo grub-mkconfig -o /boot/grub/grub.cfg
md5sum /boot/grub/grub.cfg

检查前后的配置文件 MD5 是否变化,如果发生变化,确定无误后重启系统即可。

后语

目前部分软件尚未适配 cgroups v2 ,比如 OpenStack Victoria 在部署存储节点时需要禁用 cgroups v2 ,以便使用 v1 的 blkio 功能。

同时在 Kubernetes 部署在启用 v2 的系统上初始化时会见到以下警告

...
OS: Linux
CGROUPS_CPU: enabled
CGROUPS_CPUSET: enabled
CGROUPS_DEVICES: enabled
CGROUPS_FREEZER: enabled
CGROUPS_MEMORY: enabled
CGROUPS_PIDS: enabled
CGROUPS_HUGETLB: enabled
        [WARNING SystemVerification]: missing optional cgroups: blkio
...

对于只开启了 v2 的系统只能使用 Kubernetes 1.23 及之后的版本。对于 1.24.x 版本来说,仅提示警告,对功能无影响,最新的改动已经合并进入主线版本,可能还需要等待版本迭代去掉警告信息,具体可参见Use not "blkio" but "io" controller in cgroups v2


附录

参考链接

本文撰写于一年前,如出现图片失效或有任何问题,请在下方留言。博主看到后将及时修正,谢谢!
禁用 / 当前已拒绝评论,仅可查看「历史评论」。