目录

容器虚拟化基础之 cgroups

1. 什么是 cgroups

2. 为什么使用 cgroups

3. cgroups 的用途

4.cgroups 可以控制的子系统

​编辑

CGroups 资源控制

基础知识

pidstat

stress

实战

实战一、cgroups 信息查看

cgroups 版本查看

cgroups 子系统查看

cgroups 挂载信息查看

查看一个进程上的cgroup限制

实战二、使用 cgroups 对内存进行控制

实操三、使用 cgroups 对CPU进行控制


容器虚拟化基础之 cgroups

1. 什么是 cgroups

cgroups(Control Groups) 是 linux 内核提供的一种机制,这种机制可以根据需求把一 系列系统任务及其子任务整合(或分隔)到按资源划分等级的不同组内,从而为系统资源 管理提供一个统一的框架。简单说,cgroups 可以限制、记录任务组所使用的物理资 源。本质上来说,cgroups 是内核附加在程序上的一系列钩子(hook),通过程序运行时 对资源的调度触发相应的钩子以达到资源追踪和限制的目的。

2. 为什么使用 cgroups

其可以做到对 cpu,内存等资源实现精细化的控制,目前越来越火的轻量级容器  Docker 及 k8s 中的 pod 就使用了 cgroups 提供的资源限制能力来完成 cpu,内存等部分的资源控制。

比如在一个既部署了前端 web 服务,也部署了后端计算模块的八核服务器上,可以使 用 cgroups 限制 web server 仅可以使用其中的六个核,把剩下的两个核留给后端计算 模块。

3. cgroups 的用途

Resource limitation: 限制资源使用,例:内存使用上限/cpu 的使用限制

Prioritization: 优先级控制,例:CPU 利用/磁盘 IO 吞吐

Accounting: 一些审计或一些统计

Control: 挂起进程/恢复执行进程

4.cgroups 可以控制的子系统

子系统作用
blkio对块设备的 I/O 进行限制
cpu限制 CPU 时间片的分配
cpuacct生成 cgroup 中的任务占用 CPU 资源的报告,与 cpu 挂载在同一目录
cpuset给 cgroup 中的任务分配独立的 CPU(多处理器系统)和内存节点
devices限制设备文件的创建,和对设备文件的读写
freezer暂停/恢复 cgroup 中的任务
memory对 cgroup 中的任务的可用内存进行限制,并自动生成资源占用报告
perf_event允许 perf 观测 cgroup 中的 task
net_clscgroup 中的任务创建的数据报文的类别标识符,让 Linux 流量控制器(tc 指令)可以识别来自特定 cgroup 任务的数据包,并进行网络限制
hugetlb限制使用的内存页数量
pids限制任务的数量
rdma限制 RDMA 资源(Remote Direct Memory Access,远程直接数据存取)

一开始就对启动的容器或者说服务做一个资源的限制,限制之后才能保证服务进行一个正常的运行

CGroups 资源控制

实战目的

能够查看 cgroups 基本信息,了解容器化中,操作系统是真正的资源控制层,对 cpu 和内存的控制有一定的理解。

基础知识

pidstat

• 概述

pidstat 是 sysstat 的一个命令,用于监控全部或指定进程的 CPU、内存、线程、设备 IO 等系统资源的占用情况。Pidstat 第一次采样显示自系统启动开始的各项统计信息, 后续采样将显示自上次运行命令后的统计信息。用户可以通过指定统计的次数和时间来获得所需的统计信息。

• 语法

pidstat [ 选项 ] [ <时间间隔> ] [ <次数> ]

• 参数

-u:默认参数,显示各进程的 CPU 使用统计

-r:显示各进程的内存使用统计

-d:显示各进程的 IO 使用情况

-p:指定进程号,ALL 表示所有进程

-C:指定命令

-l:显示命令名和所有参数

• 安装

Ubuntu 安装 

#安装 apt install sysstat -y

#卸载 apt remove sysstat -y

CentOS 安装

#安装 yum install sysstat -y

#卸载 yum remove sysstat -y


stress

• 概述

stress 是 Linux 的一个压力测试工具,可以对 CPU、Memory、IO、磁盘进行压力测试。

• 语法

stress [OPTION [ARG] ]

• 参数

-c, --cpu N:产生 N 个进程,每个进程都循环调用 sqrt 函数产生 CPU 压力。

-i, --io N:产生 N 个进程,每个进程循环调用 sync 将内存缓冲区内容写到磁盘上,产生 IO 压力。通过系统调用 sync 刷新内存缓冲区数据到磁盘中,以确保同步。如果缓 冲区内数据较少,写到磁盘中的数据也较少,不会产生 IO 压力。在 SSD 磁盘环境中尤为明显,很可能 iowait 总是 0,却因为大量调用系统调用 sync,导致系统 CPU 使用 率 sys 升高。

-m, --vm N:产生 N 个进程,每个进程循环调用 malloc/free 函数分配和释放内存。

--vm-bytes B:指定分配内存的大小

--vm-keep:一直占用内存,区别于不断的释放和重新分配(默认是不断释放并重新 分配内存)

-d, --hdd N:产生 N 个不断执行 write 和 unlink 函数的进程(创建文件,写入内容,删除文件)

--hdd-bytes B:指定文件大小

-t, --timeout N:在 N 秒后结束程序

-q, --quiet:程序在运行的过程中不输出信息

另外开一个终端来进行监控

pidstat -C stress -p ALL -u 2 10000

原来的终端

[user1@iZ5waahoxw3q2bZ ~]$ stress -c 1
stress: info: [22518] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
[user1@iZ5waahoxw3q2bZ ~]$ pidstat -C stress -p ALL -u 2 10000
Linux 3.10.0-957.21.3.el7.x86_64 (iZ5waahoxw3q2bZ) 	05/19/2026 	_x86_64_	(2 CPU)

06:21:14 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command

06:21:16 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
06:21:18 PM  1001     22518    0.00    0.00    0.00    0.00     1  stress
06:21:18 PM  1001     22519   95.00    0.00    0.00   95.00     0  stress

^C

Average:      UID       PID    %usr %system  %guest    %CPU   CPU  Command
Average:     1001     22518    0.00    0.00    0.00    0.00     -  stress
Average:     1001     22519   36.85    0.00    0.00   36.85     -  stress

[user1@iZ5waahoxw3q2bZ ~]$ stress -m 1 --vm-bytes 50m
stress: info: [22735] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
[user1@iZ5waahoxw3q2bZ ~]$ pidstat -C stress -p ALL -r 2 10000
Linux 3.10.0-957.21.3.el7.x86_64 (iZ5waahoxw3q2bZ) 	05/19/2026 	_x86_64_	(2 CPU)

06:25:33 PM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command

06:25:35 PM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
06:25:37 PM  1001     22735    115.50      0.00    7312    432   0.02  stress
06:25:37 PM  1001     22736  61344.00      0.00   58516  29792   1.66  stress

06:25:37 PM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
06:25:39 PM  1001     22735      0.00      0.00    7312    432   0.02  stress
06:25:39 PM  1001     22736 515982.50      0.00   58516  10520   0.58  stress
^C

Average:      UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
Average:     1001     22735     38.50      0.00    7312    432   0.02  stress
Average:     1001     22736 192442.17      0.00   58516  20156   1.12  stress

[user1@iZ5waahoxw3q2bZ ~]$ stress -d 1 -t 3
stress: info: [22835] dispatching hogs: 0 cpu, 0 io, 0 vm, 1 hdd
stress: info: [22835] successful run completed in 3s

• 安装

Ubuntu: 

#安装 apt install stress -y

#卸载 apt remove stress -y

CentOS:

#安装 yum install stress -y

#卸载 yum remove stress -y

实战

实战一、cgroups 信息查看

cgroups 版本查看

[user1@iZ5waahoxw3q2bZ ~]$ cat /proc/filesystems |grep cgroup
nodev    cgroup

如果看到 cgroup2,表示支持cgroup v2

cgroups 子系统查看
[user1@iZ5waahoxw3q2bZ ~]$ cat /proc/cgroups
#subsys_name	hierarchy	num_cgroups	enabled
cpuset	11	1	1
cpu	2	6	1
cpuacct	2	6	1
memory	10	4	1
devices	4	18	1
freezer	3	1	1
net_cls	5	1	1
blkio	8	1	1
perf_event	6	1	1
hugetlb	7	1	1
pids	9	1	1
net_prio	5	1	1
cgroups 挂载信息查看
[user1@iZ5waahoxw3q2bZ ~]$ mount |grep cgroup
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_prio,net_cls)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
查看一个进程上的cgroup限制

以当前shell进程为例,查看进程的cgroup

[user1@iZ5waahoxw3q2bZ ~]$ cat /proc/$$/cgroup
11:cpuset:/
10:memory:/
9:pids:/
8:blkio:/
7:hugetlb:/
6:perf_event:/
5:net_prio,net_cls:/
4:devices:/
3:freezer:/
2:cpuacct,cpu:/
1:name=systemd:/user.slice/user-1001.slice/session-6540.scope

实战二、使用 cgroups 对内存进行控制

1. 创建内存的 cgroup,很简单我们进入到 cgroup 的内存控制目录 /sys/fs/cgroup/memory,我们创建目录 test_memory

[user1@iZ5waahoxw3q2bZ ~]$ cd /sys/fs/cgroup/memory
[user1@iZ5waahoxw3q2bZ memory]$ sudo mkdir test_memory
[sudo] password for user1: 
[user1@iZ5waahoxw3q2bZ memory]$ cd test_memory
[user1@iZ5waahoxw3q2bZ test_memory]$ 

2.可以看到内存限制文件已经自动在 test_memory 中创建完成了,cgroups 文件系 统会在创建文件目录的时候自动创建相应的配置文件

[user1@iZ5waahoxw3q2bZ test_memory]$ ls -al
total 0
drwxr-xr-x 2 root root 0 May 19 19:03 .
drwxr-xr-x 6 root root 0 Apr 11 20:10 ..
-rw-r--r-- 1 root root 0 May 19 19:03 cgroup.clone_children
--w--w--w- 1 root root 0 May 19 19:03 cgroup.event_control
-rw-r--r-- 1 root root 0 May 19 19:03 cgroup.procs
-rw-r--r-- 1 root root 0 May 19 19:03 memory.failcnt
--w------- 1 root root 0 May 19 19:03 memory.force_empty
-rw-r--r-- 1 root root 0 May 19 19:03 memory.kmem.failcnt
-rw-r--r-- 1 root root 0 May 19 19:03 memory.kmem.limit_in_bytes
-rw-r--r-- 1 root root 0 May 19 19:03 memory.kmem.max_usage_in_bytes
-r--r--r-- 1 root root 0 May 19 19:03 memory.kmem.slabinfo
-rw-r--r-- 1 root root 0 May 19 19:03 memory.kmem.tcp.failcnt
-rw-r--r-- 1 root root 0 May 19 19:03 memory.kmem.tcp.limit_in_bytes
-rw-r--r-- 1 root root 0 May 19 19:03 memory.kmem.tcp.max_usage_in_bytes
-r--r--r-- 1 root root 0 May 19 19:03 memory.kmem.tcp.usage_in_bytes
-r--r--r-- 1 root root 0 May 19 19:03 memory.kmem.usage_in_bytes
-rw-r--r-- 1 root root 0 May 19 19:03 memory.limit_in_bytes
-rw-r--r-- 1 root root 0 May 19 19:03 memory.max_usage_in_bytes
-rw-r--r-- 1 root root 0 May 19 19:03 memory.memsw.failcnt
-rw-r--r-- 1 root root 0 May 19 19:03 memory.memsw.limit_in_bytes
-rw-r--r-- 1 root root 0 May 19 19:03 memory.memsw.max_usage_in_bytes
-r--r--r-- 1 root root 0 May 19 19:03 memory.memsw.usage_in_bytes
-rw-r--r-- 1 root root 0 May 19 19:03 memory.move_charge_at_immigrate
-r--r--r-- 1 root root 0 May 19 19:03 memory.numa_stat
-rw-r--r-- 1 root root 0 May 19 19:03 memory.oom_control
---------- 1 root root 0 May 19 19:03 memory.pressure_level
-rw-r--r-- 1 root root 0 May 19 19:03 memory.soft_limit_in_bytes
-r--r--r-- 1 root root 0 May 19 19:03 memory.stat
-rw-r--r-- 1 root root 0 May 19 19:03 memory.swappiness
-r--r--r-- 1 root root 0 May 19 19:03 memory.usage_in_bytes
-rw-r--r-- 1 root root 0 May 19 19:03 memory.use_hierarchy
-rw-r--r-- 1 root root 0 May 19 19:03 notify_on_release
-rw-r--r-- 1 root root 0 May 19 19:03 tasks

3.配置 cgroup 的策略为最大使用 20M 内存

[user1@iZ5waahoxw3q2bZ test_memory]$ cat memory.limit_in_bytes
9223372036854771712
[user1@iZ5waahoxw3q2bZ test_memory]$ sudo sh -c 'echo "20971520" > memory.limit_in_bytes'
[sudo] password for user1: 
[user1@iZ5waahoxw3q2bZ test_memory]$ cat memory.limit_in_bytes
20971520

4. 启动 1 个消耗内存的进程,每个进程占用 50MB 内存

[user1@iZ5waahoxw3q2bZ test_memory]$ stress -m 1 --vm-bytes 50M
stress: info: [25475] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd

5. 打开一个新的 shell 窗口 B 窗口,使用 pidstat 查看状态,红色为进程 id

[user1@iZ5waahoxw3q2bZ ~]$ pidstat -r -C stress -p ALL 1 10000
Linux 3.10.0-957.21.3.el7.x86_64 (iZ5waahoxw3q2bZ) 	05/19/2026 	_x86_64_	(2 CPU)

07:19:46 PM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
07:19:47 PM  1001     25475      0.00      0.00    7312    432   0.02  stress
07:19:47 PM  1001     25476 472988.12      0.00   58516  34808   1.93  stress

6. 打开一个新的 shell C 窗口,将进程 id 移动到crgoup策略

[user1@iZ5waahoxw3q2bZ memory]$ sudo sh -c 'echo 25476 >> test_memory/tasks'

7. 可以看到进程无法申请到足够内存退出

[user1@iZ5waahoxw3q2bZ test_memory]$ stress -m 1 --vm-bytes 50M
stress: info: [25475] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: FAIL: [25475] (415) <-- worker 25476 got signal 9
stress: WARN: [25475] (417) now reaping child worker processes
stress: FAIL: [25475] (451) failed run completed in 16s

可以看到进程消失了

07:20:13 PM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
^C

Average:      UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command

实操三、使用 cgroups 对CPU进行控制

1.创建内存的 cgroup,很简单我们进入到 cgroup 的内存控制目录 /sys/fs/cgroup/cpu,我们创建目录 test_cpu,可以看到系统会自动为我们创建 cgroup 的 cpu 策略

Shell
root@139-159-150-152:/sys/fs/cgroup/cpu# cd /sys/fs/cgroup/cpu
root@139-159-150-152:/sys/fs/cgroup/cpu# mkdir test_cpu
root@139-159-150-152:/sys/fs/cgroup/cpu# ll test_cpu
total 0
drwxr-xr-x 2 root root 0 Mar 12 14:54 ./
dr-xr-xr-x 9 root root 0 Mar 10 14:13 ../
-rw-r--r-- 1 root root 0 Mar 12 14:54 cgroup.clone_children
-rw-r--r-- 1 root root 0 Mar 12 14:54 cgroup.procs
-r--r--r-- 1 root root 0 Mar 12 14:54 cpuacct.stat
-rw-r--r-- 1 root root 0 Mar 12 14:54 cpuacct.usage
-r--r--r-- 1 root root 0 Mar 12 14:54 cpuacct.usage_all
-r--r--r-- 1 root root 0 Mar 12 14:54 cpuacct.usage_percpu
-r--r--r-- 1 root root 0 Mar 12 14:54 cpuacct.usage_percpu_sys
-r--r--r-- 1 root root 0 Mar 12 14:54 cpuacct.usage_percpu_user
-r--r--r-- 1 root root 0 Mar 12 14:54 cpuacct.usage_sys
-r--r--r-- 1 root root 0 Mar 12 14:54 cpuacct.usage_user
-rw-r--r-- 1 root root 0 Mar 12 14:54 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 Mar 12 14:54 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 Mar 12 14:54 cpu.shares
-r--r--r-- 1 root root 0 Mar 12 14:54 cpu.stat
-rw-r--r-- 1 root root 0 Mar 12 14:54 cpu.uclamp.max
-rw-r--r-- 1 root root 0 Mar 12 14:54 cpu.uclamp.min
-rw-r--r-- 1 root root 0 Mar 12 14:54 notify_on_release
-rw-r--r-- 1 root root 0 Mar 12 14:54 tasks

2. 打开新的 shell 窗口 B 窗口,使用 stress 模拟一个任务,cpu 使用率为 100

stress -c 1

3. 可以看到 cpu 的使用率为 100%

4. 打开新的 shell 窗口 C 窗口,我们设置 cproup 的 cpu 使用率为 30%,cpu 使用率 的计算公式 cfs_quota_us/cfs_period_us 1)cfs_period_us:cfs_period_us 表示一个 cpu 带宽,单位为微秒。系统总 CPU 带 宽 ,默认值 100000。 2)cfs_quota_us:cfs_quota_us 表示 Cgroup 可以使用的 cpu 的带宽,单位为微秒。 cfs_quota_us 为-1,表示使用的 CPU 不受 cgroup 限制。cfs_quota_us 的最小值为1ms(1000),最大值为 1s。 所以我们将 cfs_quota_us 的值设置为 30000 ,从理论上讲就可以限制 test_cpu 控 制的进程的 cpu 利用率最多是 30% 。

cd /sys/fs/cgroup/cpu
echo 30000 > test_cpu/cpu.cfs_quota_us 

5. 我们可以看到进程的 PID 为 62577,我们将该进程放到 tasks 文件进行控制 

cd /sys/fs/cgroup/cpu

echo 62577 > test_cpu/tasks

6. B 窗口中可以看到我们监控的 cpu 的使用率由100%降低为30%

感谢你的观看,期待我们下次再见!

更多推荐