Linux Cgroups 提供了对一组进程及将来子进程的资源限制、控制和统计的能力,这些资源包括 CPU、内存、存储、网络等。通过 Cgroups,可以方便地限制某个进程的资源占用,并且可以实时地监控进程的监控和统计信息。
Cgoups 中的 3 个组件
cproup
cgroup 是对进程分组管理的一种机制,一个 cgroup 包含一组进程,并可以在这个 cgroup 上增加 Linux subsystem 的各种参数配置,将一组进程和一组 subsystem 的系统参数关联起来。
subsystem
subsystem 是一组资源控制的模块,一般包含如下几项:
- cpu 设置 cgroup 中进程的 CPU 被调度的策略。
- devices 控制 cgroup 中进程对设备的访问。
- freezer 用于挂起和恢复 cgroup 中的进程。
- memory 用于控制 cgroup 中进程的内存占用。
每个 subsystem 会关联到定义了相应限制的 cgroup 上,并对这个 cgroup 中的进程做相应的限制和控制。
hierarchy
hierarchy 的功能是把一组 cgroup 串成一个树状的结构,一个这样的树便是一个 hierarchy,通过这种树状结构,Cgroups 可以做到继承。
三个组件相互的关系
- 系统在创建了新的 hierarchy 之后,系统中所有的进程都会加入这个 hierarchy 的 cgroup 根节点,这个 cgroup 根节点是 hierarchy 默认创建的。
- 一个 subsystem 只能附加到一个 hierarchy 上面。
- 一个 hierarchy 可以附加多个 subsystem。
- 一个进程可以作为多个 cgroup 的成员,但是这些 cgroup 必须在不同的 hierarchy 中。
- 一个进程 fork 出子进程时,子进程是和父进程在同一个 cgroup 中的,也可以根据需要将其移动到其他 cgroup 中。
怎么调用 Kernel 才能配置 Cgroups 呢?
Kernel 为了使对 Cgroups 的配置更直观,是通过一个虚拟的树状文件系统配置 Cgroups 的,通过层级的目录虚拟 cgroup 树。
如何操作 Cgroups?
- 首先,创建并挂载一个 hierarchy(cgroup 树)
- 挂载后系统会在这个目录生成一些默认文件,如 task 文件,task 标识该 cgroup 下面的进程 ID,如果把一个进程 ID 写到 tasks 文件中,便会将相应的进程加入到这个 cgroup 中。
- 然后,在刚刚创建好的 hierarchy 上的 cgroup 根节点中扩展出新的 cgroup。
- 在一个 cgroup 的目录下创建文件夹时,Kernel 会把文件夹标记为这个 cgroup 的子 cgroup,它们会继承父 cgroup 的属性。
- 在 cgroup 中添加和移动进程。
- 一个进程在一个 Cgroups 的 hierarchy 中,只能在一个 cgroup 节点上存在,系统的所有进程都会默认在根节点上存在,可以将进程移动到其他 cgroup 节点,只需要将进程 ID 写到移动到的 cgroup 节点的 tasks 文件中即可。
- 通过 subsystem 限制 cgroup 中进程的资源。
- 其实系统默认已经为每个 subsystem 创建了一个默认的 hierarchy,比如 memory 的 hierarchy。我们可以通过在 memory 的 hierarchy 中创建 cgroup,限制进程占用的内存。
Docker 是如何使用 Cgroups 的?
Docker 通过为每个容器创建 cgroup,并通过 cgroup 去配置资源限制和资源监控。