Cgroup 简介

Cgroupcontrol group的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组(process group)所使用的物理资源(如:cpu,memory,IO等等)。

使用 cgroup,系统管理员可耕具体地控制对系统资源的分配、优先顺序、拒绝、管理和监控。可更好地根据任务和拥护分配硬件资源,提高总体效率。

Cgroup 最初由google的工程师提出,后来被整合进Linux内核。Cgroup 也是LXC(Linux container)为实现虚拟化所使用的资源管理工具。最初的 Docker 版本其实就是在LXC上集成一些工具集,后来才重新设计自己的虚拟化层,发布了libcontainer

如何管理cgroup

Cgroup 是分层管理的,类似进程,且子 cgroup 会继承其上级 cgroup 的一些属性。但这两个模式也有不同。

Linux 进程模式

Linux 系统中的所有进程都是通用父进程 init 的子进程 ,该进程在引导时由内核执行并启动其它进程(这些进程会按顺序启动其子进程)。因为所有进程都归结到一个父进程,所以 Linux 进程模式是一个单一层级结构,或者树结构。

另外,init 之外的每个 Linux 进程都会继承其父进程的环境(比如 PATH 变量)和某些属性(比如打开文件描述符)。

Cgroup 模式

Cgroup 与进程在以下方面类似:

  • 它们是分级的
  • 子 cgroup 会集成其 cgroup 的某些属性

根本的不同是在某个系统中可同时存在不同的分级 cgroup。如果 Linux 进程模式是进程的单一树模式,那么 cgroup 模式是一个或者更多任务的独立、未连接树(例如:进程)。

需要多个独立 cgroup 分级,因为每个分级都会附加到一个或者多个子系统中。

子系统

以 RedHat6 为例,系统提供9个 cgroup 子系统,根据名称和功能列出如下。

  • blkio: 这个子系统为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB等等)。
  • cpu: 这个子系统使用调度程序提供对 CPU 的 cgroup 任务访问。
  • cpuacct: 这个子系统自动生成 cgroup 中任务所使用的 CPU 报告。
  • cpuset: 这个子系统为 cgroup 中的任务分配独立 CPU(在多核系统)和内存节点。
  • devices: 这个子系统可允许或者拒绝 cgroup 中的任务访问设备。
  • freezer: 这个子系统挂起或者恢复 cgroup 中的任务。
  • memory: 这个子系统设定 cgroup 中任务使用的内存限制,并自动生成由那些任务使用的内存资源报告。
  • net_cls: 这个子系统使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 cgroup 中生成的数据包。
  • ns: 命名空间子系统。

子系统、层级、控制组群和任务的关系

在 cgroup 术语中系统进程称为任务。

Rule 1

任何单一子系统(比如 cpu)最多可附加到一个层级中。

结果是,cpu 子系统永远无法附加到两个不同的层级。

Rule 2

单一层级可附加一个或者多个子系统

结果是,cpu 和 memory 子系统(或者任意数目的子系统)都可附加到单一层级中,只要每个子系统不再附加到另一个层级即可。

Rule 3

每次在系统中创建新层级时,该系统中的所有任务都是那个层级的默认 cgroup(我们称之为 root cgroup)的初始成员。任何创建的单一层级,该系统中的每个任务都可以是那个层级中唯一一个 cgroup 的成员。单一任务可以是在多个 cgroup 中,只要每个 cgroup 都在不同的层级中即可。只要某个任务成为同一层级中第二个 cgroup 成员,就会将其从那个层级的第一个 cgroup 中删除。

一个任务永远不会同时位于同一层级的不同 cgroup 中。

结果是,如果 cpu 和 memory 子系统都附加到名为 cpu_and_mem的层级中,且 net_cls 子系统是附加到名为 net 的层级中,那么运行的 httpd 进程可以是 cpu_and_mem 中任意 cgroup 的成员,同时也是 net 中任意 cgroup 的成员。

httpd 进程所在 cpu_and_mem 中的 cgroup 可将其 CPU 时间限制为分配给其它进程时间的一半,并将其内存用量限制为最多 1024MB。另外,net中的 cgroup 还可将其传输速率限制为 30MB/s。

首次创建层级时,该系统中的每个任务都至少是一个 cgroup 的成员,即 root cgroup。因此每当使用 cgroup 时,每个系统任务总是至少在一个 cgroup 中。

Rule 4

系统中的任意进程(任务)都将自己分支创建子进程(任务)。该子任务自动成为其父进程所在 cgroup 的成员。然后可根据需要将该子任务移动到不同的 cgroup 中,但开始时它总是继承其父任务的 cgroup(进程术语中称其为“环境”)。

cpu_and_mem 层级中名为 halt_cpu_1gb_max 的 cgroup 成员的任务,以及 net 层级中 cgroup trans_rate_30 的成员。当 httpd 进程将其自身分为几个分支时,其子进程会自动成为 half_cpu_1gb_max cgroup 和 trans_rate_30 cgroup 的成员。它会完全继承其父任务所属的同一 cgroup。

此后,父任务和子任务就彼此完全独立:更改某个任务所属 cgroup 不会影响到另一个。同样更改父任务的 cgroup 也不会以任何方式影响其子任务。总之:所有子任务总是可继承其父任务的同一 cgroup 的成员关系,但之后可更改或者删除那些成员关系。

资源管理实施

  • 因为某个任务可属于任一层级中的单一 cgroup,所以只有一个方法可让单一子系统限制或者影响任务。这是合理的:是一个功能,而不是限制。
  • 可以将几个子系统分组在一起以便它们可影响单一层级中的所有任务。因为该层级中的 cgroup 有不同的参数设定,因此会对那些任务产生不同的影响。
  • 有时可能需要重构层级。例如:从附加了几个子系统的层级中删除一个子系统,并将其附加到不同的层级中。
  • 反正,如果从不同层级中分离子系统的需求降低,则可以删除层级并将其子系统附加到现有层级中。
  • 这个设计允许简单的 cgroup 使用,比如为单一层级中的具体任务设定几个参数 ,单一层级可以是只附加了 cpu 和 memory 子系统的层级。
  • 这个设计还允许高精度配置:系统中的每个任务(进程)都可以是每个层级的成员,每个层级都有单一附加的子系统。这样的配置可让系统管理员绝对控制每个单一任务的所有参数。