此前的文章中,我们介绍了 docker 赖以实现资源隔离与限制的原理:
在文章中,我们提到了 Linux 用来管理和限制 Linux 进程组资源使用的 CGroup 机制。本文我们就来详细介绍一下。
2006 年,Google 工程师在开源社区发起了一个用来管理和限制进程资源使用的项目,名为“process containers”,2007 年,Linux 内核团队将其改名为 cgroup 纳入到 Linux 内核 feature 项目中。在 2008 年 1 月发布的 Linux 2.6.24,这一功能被合并到了内核中。到 Linux 4.5 版本内核,CGroup v2 被合并到内核,这是一次在使用方式上的重大更新。
CGroup 一般也被称为“cgroups”,是 control groups 的简称。
CGroup 机制的功能就是对 linux 的一组进程进行包括 CPU、内存、磁盘 IO、网络等在内的资源使用进行限制、管理和隔离。
CGroup 的主要功能有:
CGroup 对进程组资源的限制是通过子系统来实现的,这样做的好处是可以便于新的功能的增加。目前已有的子系统有:
CGroup 是通过树的结构形式来进行组织的,每一棵 cgroup 结构体组成的树称之为一个 cgroups 层级结构(cgroups hierarchy)。
如图所示,Group Hierarchy A 和 Group Hierarchy B 分别代表了 cgroups 的一个层级。在一个 cgroups 层级上,都可以 attach 一个或几个 cgroup 子系统,而被 attach 的 cgroups 子系统就可以对当前层级包含的一组进程进行相应的资源限制。
那么,cgroup 节点和它们管理的进程是如何关联的呢?这依赖于该节点的控制任务列表,进程被添加到某个节点的控制任务列表中,便实现了该节点对相应进程的控制。一个 cgroup 节点的控制列表可以包含多个进程,而一个进程又可以被添加到多个 cgroup 节点的控制列表中,这样便实现了 cgroup 节点与被管理的进程之间多对多的对应关系。
通过命令 mount -t cgroup
就可以查看当前的所有 linux cgroups 子系统与挂载点:
例如我们要对某一组进程的 cpu 资源进行限制,那么我们就执行:
cd /sys/fs/cgroup/cpu
mkdir test_limit
cd test_limit
查看创建后的目录,可以看到,目录中已经生成了一系列文件。
接下来我们就可以来对进程进行 CPU 利用率的限制了。
首先我们写一个 C 语言的程序,用来将 CPU 跑到 100%:
int main() {
int i=0;
for (;;) i++;
return 0;
}
运行这个进程,我们观察到 CPU 利用率确实达到了 100%。
接着我们执行下面的命令:
# 限制该组进程 CPU 总利用率到 20%
echo 20000 > /sys/fs/cgroup/cpu/test_limit/cpu.cfs_quota_us
# 向任务控制列表中添加需要被限制的 pid
echo 23732 >> /sys/fs/cgroup/cpu/test_limit/tasks
可以看到,在完成上述命令的执行后,可以看到,cpu 利用率很快就被成功限制到了 20%。
其他资源的限制方法与此是完全类似的。