Linux Cgroup V2 初体验

本文主要记录 Linux Cgroup V2 版本基本使用操作,包括 cpu、memory 子系统演示。

1. 开启 Cgroup V2

版本检查

通过下面这条命令来查看当前系统使用的 Cgroups V1 还是 V2

1

stat -fc %T /sys/fs/cgroup/如果输出是cgroup2fs 那就是 V2,就像这样

1

2

root@tezn:~# stat -fc %T /sys/fs/cgroup/

cgroup2fs如果输出是tmpfs 那就是 V1,就像这样

1

2

[root@docker cgroup]# stat -fc %T /sys/fs/cgroup/

tmpfs启用 cgroup v2

如果当前系统未启用 Cgroup V2,也可以通过修改内核 cmdline 引导参数在你的 Linux 发行版上手动启用 cgroup v2。

如果你的发行版使用 GRUB,则应在 /etc/default/grub 下的 GRUB_CMDLINE_LINUX 中添加 systemd.unified_cgroup_hierarchy=1, 然后执行 sudo update-grub。

具体如下:

1)编辑 grub 配置

1

vi /etc/default/grub内容大概是这样的:

1

2

3

4

5

6

GRUB_DEFAULT=0

GRUB_TIMEOUT_STYLE=hidden

GRUB_TIMEOUT=0

GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"

GRUB_CMDLINE_LINUX=""对最后一行GRUB_CMDLINE_LINUX进行修改

1

GRUB_CMDLINE_LINUX="quiet splash systemd.unified_cgroup_hierarchy=1"2)然后执行以下命令更新 GRUB 配置

1

sudo update-grub3)最后查看一下启动参数,确认配置修改上了

1

cat /boot/grub/grub.cfg | grep "systemd.unified_cgroup_hierarchy=1"4)然后就是重启

1

reboot重启后查看,不出意外切换到 cgroups v2 了

1

2

root@cgroupv2:~# stat -fc %T /sys/fs/cgroup/

cgroup2fs发行版推荐

不过,推荐的方法仍是使用一个默认已启用 cgroup v2 的发行版。

有关使用 cgroup v2 的 Linux 发行版的列表,

Container-Optimized OS(从 M97 开始)Ubuntu(从 21.10 开始,推荐 22.04+)Debian GNU/Linux(从 Debian 11 Bullseye 开始)Fedora(从 31 开始)Arch Linux(从 2021 年 4 月开始)RHEL 和类似 RHEL 的发行版(从 9 开始)2. 基本使用

cgroup v2 使用上和 v1 版本基本一致,v2 版本也是默认在/sys/fs/cgroup/目录。

1

2

3

4

5

6

root@mydocker:~# ls /sys/fs/cgroup/

cgroup.controllers cgroup.subtree_control init.scope system.slice

cgroup.max.depth cgroup.threads io.cost.model user.slice

cgroup.max.descendants cpu.pressure io.cost.qos

cgroup.procs cpuset.cpus.effective io.pressure

cgroup.stat cpuset.mems.effective memory.pressure创建 sub-cgroup: 只需要创建一个子目录1

2

cd /sys/fs/cgroup

mkdir $CGROUP_NAME将进程移动到指定 cgroup:将 PID 写入到相应 cgroup 的 cgroup.procs 文件即可,就像这样:1

echo 1001 > /sys/fs/cgroup/test/cgroup.procs删除 cgroup/sub-cgroup: 也是直接删除对应目录即可如果一个cgroup 已经没有任何children或活进程,那直接删除对应的文件夹就删除该cgroup了如果一个cgroup已经没有children,但是还有僵尸进程,也认为这个cgroup是空的,可以直接删除1

rmdir /sys/fs/cgroup/test修改 cpu、memory 限制:往对应配置文件写入配置内容即可cpu.max 用于配置 cpu 使用限制memory.max 则用于配置 内存使用限制…创建 cgroup

接下来,以 cpu、memory 为例,简单演示一下 cgroup v2 版本使用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

root@mydocker:~# cd /sys/fs/cgroup/

root@mydocker:/sys/fs/cgroup# mkdir test

root@mydocker:/sys/fs/cgroup# cd test

root@mydocker:/sys/fs/cgroup/test# ls

cgroup.controllers cpu.uclamp.max memory.current

cgroup.events cpu.uclamp.min memory.events

cgroup.freeze cpu.weight memory.events.local

cgroup.max.depth cpu.weight.nice memory.high

cgroup.max.descendants cpuset.cpus memory.low

cgroup.procs cpuset.cpus.effective memory.max

cgroup.stat cpuset.cpus.partition memory.min

cgroup.subtree_control cpuset.mems memory.oom.group

cgroup.threads cpuset.mems.effective memory.pressure

cgroup.type io.max memory.stat

cpu.max io.pressure pids.current

cpu.pressure io.stat pids.events

cpu.stat io.weight pids.maxCPU

启动一个死循环

1

2

root@mydocker:/sys/fs/cgroup/test# while : ; do : ; done &

[1] 90482不出意外的话,应该占用了 100% cpu

1

2

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

90482 root 20 0 10160 1772 0 R 99.3 0.1 0:05.01 bash 接下来使用 cgroup v2 限制该进程只能使用 20% cpu

1)修改配置

1

echo 2000 10000 > cpu.max含义是在 10000 微秒的 CPU 时间周期内,有 2000 微秒是分配给本 cgroup 的,也就是本 cgroup 管理的进程在单核 CPU 上的使用率不会超过 20%。

2)将进程加入当前 cgroup

1

echo 90482 > cgroup.procs再次查看

1

2

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

90482 root 20 0 10160 1772 0 R 20.2 0.1 2:07.78 bash 可以看到,已经被限制到了 20%

Memory

接下来演示内存限制,使用以下代码来模拟内存消耗,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

cat < ~/mem-allocate.c

#include

#include

#include

#include

#define MB (1024 * 1024)

int main(int argc, char *argv[])

{

char *p;

int i = 0;

while(1) {

p = (char *)malloc(MB);

memset(p, 0, MB);

printf("%dM memory allocated\n", ++i);

sleep(1);

}

return 0;

}

EOF编译

1

gcc ~/mem-allocate.c -o ~/mem-allocate然后启动该文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

root@mydocker:/sys/fs/cgroup/test# ~/mem-allocate

1M memory allocated

2M memory allocated

3M memory allocated

4M memory allocated

5M memory allocated

6M memory allocated

7M memory allocated

8M memory allocated

9M memory allocated

10M memory allocated

11M memory allocated

12M memory allocated

^C可以看到,每秒会消耗 1M 内存,若不停止会一直运行直到 OOM。

接下来使用 cgroup v2 限制最多消耗 10M 内存。

1)修改配置

单位为字节 10485760= 10 * 1024 * 1024

1

echo 10485760 > memory.max也就是本 cgroup 管理的进程内存使用不会超过 10M

2)将进程加入当前 cgroup

1

2

#将当前bash加入到test中,这样这个bash创建的所有进程都会自动加入到test中

sh -c "echo $$ >> cgroup.procs"再次查看

1

2

3

4

5

6

7

8

9

10

11

root@mydocker:/sys/fs/cgroup/test# ~/mem-allocate

1M memory allocated

2M memory allocated

3M memory allocated

4M memory allocated

5M memory allocated

6M memory allocated

7M memory allocated

8M memory allocated

9M memory allocated

Killed可以看到,到 10M 时就因为达到内存上限而被 Kill 了。

删除 cgroup

演示完成,把 cgroup 删除。

首先把进程 kill 一下

1

2

3

4

5

root@mydocker:/sys/fs/cgroup# cat test/cgroup.procs

90444

90630

root@mydocker:/sys/fs/cgroup# kill -9 90630

root@mydocker:/sys/fs/cgroup# kill -9 90444然后删除目录

1

root@mydocker:/sys/fs/cgroup# rmdir test这样 cgroup 就删除了。

3. v1 v2 对比

v1 的 cgroup 为每个控制器都使用独立的树(目录)

1

2

[root@docker cgroup]# ls /sys/fs/cgroup/

blkio cpu cpuacct cpuacct,cpu cpu,cpuacct cpuset devices freezer hugetlb memory net_cls net_cls,net_prio net_prio perf_event pids rdma systemd每个目录就代表了一个 cgroup subsystem,比如要限制 cpu 则需要到 cpu 目录下创建子目录(树),限制 memory 则需要到 memory 目录下去创建子目录(树)。

比如 Docker 就会在 cpu、memory 等等目录下都创建一个名为 docker 的目录,在 docker 目录下在根据 containerID 创建子目录来实现资源限制。

各个 Subsystem 各自为政,看起来比混乱,难以管理

因此最终的结果就是:

用户空间最后管理着多个非常类似的 hierarchy,在执行 hierarchy 管理操作时,每个 hierarchy 上都重复着相同的操作。v2 中对 cgroups 的最大更改是将重点放在简化层次结构上

v1 为每个控制器使用独立的树(例如 /sys/fs/cgroup/cpu/GROUPNAME 和 /sys/fs/cgroup/memory/GROUPNAME)。v2 将统一/sys/fs/cgroup/GROUPNAME中的树,如果进程 X 加入/sys/fs/cgroup/test,则启用 test 的每个控制器都将控制进程 X。更多 v1 和 v2 差异见 v1 存在的问题及 v2 的设计考虑

4. 小结

本文主要分享了 Linux cgroup v2 版本的基本使用,以及 v1 和 v2 版本的差异。

更多 cgroup v2 信息推荐阅读:Control Group v2 及其译文 Control Group v2(cgroupv2 权威指南)(KernelDoc, 2021)

关停中国投资公司,IBM中国业务还有什么?
地下城堡4失落小镇怎么玩 地下城堡4失落小镇玩法攻略