实验-手动通过cgroup进行资源限制

2022/8/5 docker

# 实验目的

在支持 cgroup 的 Linux 系统上,可以通过直接操作 /sys/fs/cgroup 文件系统来手动控制资源配额。

这样可以更加深层次地理解docker等容器技术的底层原理,以及如何通过 cgroup 控制资源配额。

# 实验步骤

目前绝大部分linux内核已经支持 cgroup v2,但是 cgroup v1 也支持的。

下面是手动通过 cgroup 控制资源配额的步骤:

# 1. 检查和确认 cgroup 支持

检查挂载的 cgroup:

mount | grep cgroup
1

输出类似以下内容表示 cgroup 已挂载:

cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate,memory_recursiveprot)
1

查看支持的 cgroup 控制器:

cat /proc/cgroups
1

输出示例:

#subsys_name    hierarchy       num_cgroups     enabled
cpuset  0       68      1
cpu     0       68      1
cpuacct 0       68      1
blkio   0       68      1
memory  0       68      1
devices 0       68      1
freezer 0       68      1
net_cls 0       68      1
perf_event      0       68      1
net_prio        0       68      1
hugetlb 0       68      1
pids    0       68      1
rdma    0       68      1
misc    0       68      1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# cgroup名词解释

hierarchy

hierarchy为0表示这些控制器都在同一个统一层次结构中(通常是 cgroup v2 的特点),如果是 cgroup v1,不同控制器可能会属于不同的层次。

num_cgroups

num_cgroups为68表示当前系统中为这些控制器创建了 75 个 cgroup。

enabled

enabled为1表示这些控制器已启用并可用。

cpuset

用于分配 CPU 和内存节点(NUMA)给特定的 cgroup。将任务限制到特定的 CPU 核心和内存节点范围。

cpu

控制 CPU 调度分配(时间片、优先级等)。用于设置 CPU 时间配额,例如通过 cpu.shares 配置优先级。

cpuacct

提供 CPU 使用统计。记录和报告 cgroup 中任务的 CPU 消耗情况。

blkio

控制块设备(如磁盘)的 IO 限制。限制或记录磁盘读写速率。

memory

控制内存使用,包括物理内存和交换分区。设置内存使用上限、防止内存泄漏。

devices

控制访问设备的权限。允许或禁止 cgroup 中的任务访问特定的设备(如磁盘、USB)。

freezer

冻结或恢复 cgroup 中的所有任务。用于暂停 cgroup 中的所有进程,常用于任务管理或系统调试。

net_cls

为网络数据包打分类标记。配合流量控制(如 tc)对网络流量进行管理。

perf_event

管理性能监控事件。限制任务对性能监控资源的使用(如 perf 工具)。

net_prio

设置网络优先级。通过接口对网络流量的优先级进行调整。

hugetlb

管理大页内存的分配。为高性能应用分配和限制大页内存。

pids

限制 cgroup 中的进程数。防止 fork 炸弹(通过无限创建进程耗尽系统资源)。

rdma

控制远程直接内存访问(RDMA)资源。限制 cgroup 中的 RDMA 资源消耗。

misc

用于未分类的控制器,或未来扩展功能。当前无具体用途,但为扩展提供占位符。

# 2. 创建一个 cgroup

本实验后续以cgroup2为例

在 /sys/fs/cgroup 下创建一个新的 cgroup 目录:

sudo mkdir /sys/fs/cgroup/mygroup
1

当创建一个mygroup目录后,会自动生成资源配置的文件,如cpu.shares、cpu.cfs_quota_us、cpu.cfs_period_us等。

[root@master mygroup]# ll /sys/fs/cgroup/mygroup
total 0
-r--r--r--. 1 root root 0 Nov 30 14:59 cgroup.controllers
-r--r--r--. 1 root root 0 Nov 30 14:59 cgroup.events
-rw-r--r--. 1 root root 0 Nov 30 14:59 cgroup.freeze
--w-------. 1 root root 0 Nov 30 14:59 cgroup.kill
-rw-r--r--. 1 root root 0 Nov 30 14:59 cgroup.max.depth
-rw-r--r--. 1 root root 0 Nov 30 14:59 cgroup.max.descendants
-rw-r--r--. 1 root root 0 Nov 30 15:15 cgroup.procs
-r--r--r--. 1 root root 0 Nov 30 14:59 cgroup.stat
-rw-r--r--. 1 root root 0 Nov 30 14:59 cgroup.subtree_control
-rw-r--r--. 1 root root 0 Nov 30 14:59 cgroup.threads
-rw-r--r--. 1 root root 0 Nov 30 14:59 cgroup.type
-rw-r--r--. 1 root root 0 Nov 30 14:59 cpu.idle
-rw-r--r--. 1 root root 0 Nov 30 15:00 cpu.max
-rw-r--r--. 1 root root 0 Nov 30 14:59 cpu.max.burst
-rw-r--r--. 1 root root 0 Nov 30 14:59 cpuset.cpus
-r--r--r--. 1 root root 0 Nov 30 14:59 cpuset.cpus.effective
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 3. 配置资源限制

根据需要限制资源,可以设置以下参数:

CPU 配额限制,单位是微秒

cpu使用率是 50000/100000=0.5,即 50%

echo "50000 100000" > /sys/fs/cgroup/mygroup/cpu.max
1

内存限制

限制内存使用为 512MB:

echo $((512*1024*1024)) > /sys/fs/cgroup/mygroup/memory.max
1

# 4. 运行一个测试进程

#!/bin/bash

a=1
while true
do

        a=$[$a+1]
done
1
2
3
4
5
6
7
8

运行该脚本

# 5. 将进程加入 cgroup

找到目标进程的 PID:

ps aux | grep <process_name>
1

通过top查看该进程的资源使用情况,发现cpu使用率为100%

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
2242 root      20   0    6744   2944   2688 R  100.0   0.2   0:09.22 test.sh                                                              
1
2

添加进程到 cgroup:

echo <PID> > /sys/fs/cgroup/mygroup/cgroup.procs
1

再次查看,会发现cpu使用率被限制在50%左右

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                              
2242 root      20   0    6744   2944   2688 R  49.7   0.2   1:46.99 test.sh   
1
2

# 6. 移除 cgroup

当使用cgroup2时,要将一个进程从cgroup中移除,需要将该进程加入另一个cgroup。或者关闭进程,重新启动。

另外,对于cgroup2,删除cgroup时,需要先删除cgroup中的所有进程,否则会报错。

sudo rmdir /sys/fs/cgroup/cpu/mygroup
1

注意事项

权限:操作 /sys/fs/cgroup 文件系统需要 root 权限。
版本差异:cgroup v2 的配置文件和参数名称不同,请根据系统版本使用对应命令。
监控和调试:可以使用 systemd-cgls ls 或 cat 检查 cgroup 的状态和参数:

完成以上步骤,你就能手动使用 cgroup 控制资源配额了!