一张图看懂什么是 cgroups
1、术语
1.1、cgroups(Linux control groups)
Control groups, usually referred to as cgroups, are a Linux kernel feature which allow processes to be organized into hierarchical groups whose usage of various types of resources can then be limited and monitored. The kernel’s cgroup interface is provided through a pseudo-filesystem called cgroupfs. Grouping is implemented in the core cgroup kernel code, while resource tracking and limits are implemented in a set of er-resource-type subsystems (memory, CPU, and so on).
cgroups
是一种 Linux 内核功能,它允许将进程组织成分层组,然后可以限制和监视对各种类型资源的使用。
在文件 /proc/[pid]/cgroup
中可以看到具有相应 PID 的进程所属的控制组(结构如:hierarchy-ID:controller-list:cgroup-path)。
5:cpuacct,cpu,cpuset:/daemons
1.2、subsystem(resource controllers)
A subsystem is a kernel component that modifies the behavior of the processes in a cgroup. Various subsystems have been implemented, making it possible to do things such as limiting the amount of CPU time and emory available to a cgroup, accounting for the CPU time used by a cgroup, and freezing and resuming execution of the processes in a cgroup. Subsystems are sometimes also known as resource controllers (or simply, controllers).
subsystem
是修改 cgroup
中进程行为的内核组件,有时也称为 resource controllers
。内核中已经实现的 subsystem
如下:
- cpu 子系统,主要限制进程的 cpu 使用率。
- cpuacct 子系统,可以统计 cgroups 中的进程的 cpu 使用报告。
- cpuset 子系统,可以为 cgroups 中的进程分配单独的 cpu 节点或者内存节点。
- memory 子系统,可以限制进程的 memory 使用量。
- blkio 子系统,可以限制进程的块设备 io。
- devices 子系统,可以控制进程能够访问某些设备。
- net_cls 子系统,可以标记 cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。
- freezer 子系统,可以挂起或者恢复 cgroups 中的进程。
- ns 子系统,可以使不同 cgroups 下面的进程使用不同的 namespace。
通过文件 /proc/cgroups
可以查看当前操作系统中支持的 subsystem
以及当前的状态:
root@DESKTOP-6MVDBD1:/sys/fs/cgroup# cat /proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset 4 1 1
cpu 8 1 1
cpuacct 8 1 1
blkio 6 1 1
memory 3 1 1
devices 10 84 1
freezer 7 1 1
net_cls 9 1 1
perf_event 5 1 1
net_prio 9 1 1
hugetlb 0 1 0
pids 2 1 1
rdma 13 1 1
其中:
- subsys_name 代表 subsystem 的名字。
- hierachy 代表当前 subsystem 唯一关联的 hierarchy 的 ID。
- num_cgroups 代表在该 hierachy 中使用该子系统的 cgroup 的数量。
- enabled 为 1 代表该 subsystem 已开启。
1.3、hierarchy
The cgroups for a controller are arranged in a hierarchy. This hierarchy is defined by creating, removing, and renaming subdirectories within the cgroup filesystem. At each level of the hierarchy, attributes (e.g. limits) can be defined. The limits, control, and accounting provided by cgroups generally have effect throughout the subhierarchy underneath the cgroup where the attributes are defined. Thus, for example, the imits placed on a cgroup at a higher level in the hierarchy cannot be exceeded by descendant cgroups.
控制器的 cgroup
按层次结构排列。此层次结构是通过在 cgroup
文件系统中创建、删除和重命名子目录来定义的。在 hierarchy
的每个级别,都可以定义属性(例如限制)。 cgroup
提供的限制、控制和记帐通常会在定义属性的 cgroup
下的整个子层级中产生影响。因此,放置在层次结构中更高级别的 cgroup
上的限制不能被后代 cgroup
超过。
内核使用 hierarchy
来表示一个 cgroup
对某一个或者某几个 subsystem
的资源限制。cgroup
结构体可以组织成一颗树的形式,每一棵 cgroup
结构体组成的树称之为一个 hierarchy
。cgroups层级结构可以 attach 一个或者几个 subsystem
,当前层级结构可以对其 attach 的 subsystem
进行资源的限制。每一个 subsystem
只能被 attach 到一个 hierarchy
。
cgroup的文件系统通常在 /sys/fs/cgroup/
,通过查看 cgroup
文件系统可以看到所有的 hierarchy
。
root@DESKTOP-6MVDBD1:/sys/fs/cgroup# ls -al /sys/fs/cgroup/
total 0
drwxr-xr-x 16 root root 320 Jun 19 15:36 .
drwxr-xr-x 10 root root 0 Jun 19 15:36 ..
dr-xr-xr-x 2 root root 0 Jun 19 15:36 blkio
dr-xr-xr-x 2 root root 0 Jun 19 15:36 cpu
dr-xr-xr-x 2 root root 0 Jun 19 15:36 cpuacct
dr-xr-xr-x 2 root root 0 Jun 19 15:36 cpuset
dr-xr-xr-x 2 root root 0 Jun 19 15:36 devices
dr-xr-xr-x 2 root root 0 Jun 19 15:36 freezer
dr-xr-xr-x 2 root root 0 Jun 19 15:36 hugetlb
dr-xr-xr-x 2 root root 0 Jun 19 15:36 memory
dr-xr-xr-x 2 root root 0 Jun 19 15:36 net_cls
dr-xr-xr-x 2 root root 0 Jun 19 15:36 net_prio
dr-xr-xr-x 2 root root 0 Jun 19 15:36 perf_event
dr-xr-xr-x 2 root root 0 Jun 19 15:36 pids
dr-xr-xr-x 2 root root 0 Jun 19 15:36 rdma
dr-xr-xr-x 2 root root 0 Jun 19 15:36 unified
1.4、css_set(cgroups subsystem set)
上面这个图从整体结构上描述了进程与 cgroups
之间的关系。最下面的 P
代表一个进程。每一个进程的描述符中有一个指针指向了一个辅助数据结构 css_set
。 指向某一个 css_set
的进程会被加入到当前 css_set
的进程链表中。一个进程只能隶属于一个 css_set
,一个 css_set
可以包含多个进程,隶属于同一 css_set
的进程受到同一个 css_set
所关联的资源限制。
上图中的 M×N Linkage
说明的是 css_set
通过辅助数据结构可以与 cgroups
节点进行多对多的关联。但是 cgroups
的实现不允许 css_set
同时关联同一个 hierarchy
下多个节点。 这是因为 cgroups
对同一种资源不允许有多个限制配置。
一个 css_set
关联多个 hierarchy
的节点时,表明需要对当前 css_set
下的进程进行多种资源的控制。而一个 cgroups
节点关联多个 css_set
时,表明多个 css_set
下的进程列表受到同一份资源的相同限制。
1.5、关于 v1 和 v2
Although cgroups v2 is intended as a replacement for cgroups v1, the older system continues to exist (and for compatibility reasons is unlikely to be emoved). Currently, cgroups v2 implements only a subset of the controllers available in cgroups v1. The two systems are implemented so that oth v1 controllers and v2 controllers can be mounted on the same system. Thus, for example, it is possible to use those controllers that are supported under version 2, while also using version 1 controllers where version 2 does not yet support those controllers. The only restriction here s that a controller can’t be simultaneously employed in both a cgroups v1 hierarchy and in the cgroups v2 hierarchy.
虽然 cgroups v2打算作为 cgroups v1的替代品,但是旧系统仍然存在(并且由于兼容性原因不太可能被删除)。目前,cgroups v2只实现 cgroups v1中可用控制器的一个子集。这两个系统的实现使得 v1控制器和 v2控制器都可以安装在同一个系统上。因此,例如,可以使用版本2支持的那些控制器,同时也可以使用版本2尚不支持那些控制器的版本1控制器。这里唯一的限制是控制器不能同时在 cgroups v1层次结构和 cgroups v2中使用
2、实现机制
2.1、VFS(Virtual File System)
VFS 是一个内核抽象层,能够隐藏具体文件系统的实现细节,从而给用户态进程提供一套统一的 API 接口。VFS 使用了一种通用文件系统的设计,具体的文件系统只要实现了 VFS 的设计接口,就能够注册到 VFS 中,从而使内核可以读写这种文件系统。 这很像面向对象设计中的抽象类与子类之间的关系,抽象类负责对外接口的设计,子类负责具体的实现。其实,VFS本身就是用 c 语言实现的一套面向对象的接口。
cgroups 通过实现 VFS 的通用文件系统模型,把维护 cgroups 层级结构的细节,隐藏在 cgroups 文件系统的这些实现函数中。
3、一些实践
3.1、Docker
相信大多数人都没有读过 Docker 的源代码,但是通过这篇文章,可以估计 Docker 在实现不同的 Container 之间资源隔离和控制的时候,是可以创建比较复杂的 cgroups 节点和配置文件来完成的。然后对于同一个 Container 中的进程,可以把这些进程 PID 添加到同一组 cgroups 子节点中已达到对这些进程进行同样的资源限制。
3.2、创建 hierarchy
Linux中,用户可以使用mount命令挂载 cgroups 文件系统,格式为:mount -t cgroup -o subsystems name /cgroup/name
,其中 subsystems 表示需要挂载的 cgroups 子系统, /cgroup/name 表示挂载点,如上文所提,这条命令同时在内核中创建了一个cgroups 层级结构。
比如挂载 cpuset, cpu, cpuacct, memory 4个subsystem到/cgroup/cpu_and_mem 目录下,就可以使用:
mount -t cgroup -o remount,cpu,cpuset,memory cpu_and_mem /cgroup/cpu_and_mem
GPU 资源限制
TODO
附录
- https://man7.org/linux/man-pages/man7/cgroups.7.html
- https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cgroups.html
- https://tech.meituan.com/2015/03/31/cgroups.html
- https://lwn.net/Articles/606925/
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 nz_nuaa@163.com