1. 术语
- cgroup : A cgroup is a collection of processes that are bound to a set of limits or parameters defined via the cgroup filesystem.
- subsystem: 用于限制 cgroup 中进程的资源和行为,例如控制 CPU 和内存占用,甚至暂时冻结进程的运行。有时也被称为 resource controllers / controllers
- task : 接受 cgroup 限制的进程。在 cgroup v1 或 v2 的高级用法中,可以是线程。
- hierarchy: 由于 cgroup 是以 fs 的方式存放,因此多个 cgroup 可以构成层级结构,子级 cgroup 会继承父级的资源限制
2. cgroup v1 的例子
2.1. 新建子系统
新建用于限制进程内存的子系统。
由于 cgroup 是以 FS 的方式来创建和管理的,所以创建的方法是 mount。
通常来说,现代的系统启动时,systemd 会自动把所有支持的子系统(含 cpu、memory 等)挂载到 /sys/fs/cgroup ,因此这第一步通常是可以跳过的。
mount -t cgroup -o memory none /sys/fs/cgroup/memory
mount 的参数:
-t: 文件系统类型-o: 指定的 fs 支持的 options。cgroup fs 支持的 options 就是各种 subsystem 的名称,例如 cpu, memory- none: 对于 mount 命令,这里应该是 device 的名称,由于 cgroup fs 并不存在真实的设备,因此只是一个占位符罢了
2.2. 创建子 cgroup
在 memory 下新建一个 test
mkdir /sys/fs/cgroup/memory/test
执行成功后,系统会自动在 test 下新建一系列文件,每个文件负责存储一项配置,用于控制进程组的资源使用。
2.3. 修改资源限制,绑定进程
echo 1234567 > /sys/fs/cgroup/test/memory.limit_in_bytes
echo ${task_pid} > /sys/fs/cgroup/test/tasks
3. cgroup v2
v1 版本存在一些历史问题:各个子系统开发相对独立、不够协调,最终出现了许多不一致,给多层级的 cgroup 维护带来了极大的复杂性。这使得开发者社区最终决定研发 v2,并在 kernel v4.5 中正式 release。
当前的 linux 内核同时支持 cgroup v1 和 v2 ,且允许将它们同时挂载到一个 OS 中。这是因为截至目前 v2 并未包含所有 v1 的支持的子系统,以及出于后向兼容性的考虑。唯一的限制是,不允许同一个子系统同时被挂载到 v1 和 v2 中。
cgroup v1 允许各个子系统挂载到不同的层级中。从设计角度来说,这样是为了最大化配置的灵活性;但是在实践中发现,这种灵活性基本没有使用场景,反而徒增了 cgroup 系统的复杂性。因此在 v2 的设计中,所有的子系统都强制要求挂载到同一层级中。
此外,cgroup v2 只允许进程被绑定到叶子层级的 cgroup (No internal processes rule)。即,如果一个层级含有子 cgroup ,则该层级不可以有绑定的进程。这是为了解决在父子层级之间分配资源的难题。
在 cgroup v2 下,查看一个 cgroup 的绑定进程的文件不再是 tasks,而是 cgroup.procs。
4. 杂
通过 cat /proc/$pid/cgroup 查看一个进程的 cgroup。
与 namespace 合作,构成容器技术的基石。ns 负责隔离(FS、进程、网络),cgroup 负责限制(cpu、内存)
