cgroup 的功能在于将一台计算机上的资源(CPU,memory,network)进行分片,来防止进程间不利的资源抢占。

术语

cgroup:关联一组 task 和一组 subsystem 的配置参数。 一个 task 对应一个进程,cgroup 是资源分片的最小单位。
subsystem:资源管理器,一个 subsystem 对应一项资源的管理,如 cpu, cpuset,memroy 等。
hirearchy:关联一个到多个 subsystem 和一组属性结构的 cgroup 。和 cgroup 不同,hirearchy 包含的是可管理的 subsystem 而非具体参数。

由此可见,cgroup 对资源的管理是一个树形结构,类似进程。
相同点:分层结构,子进程 / cgroup 继承父进程 / cgroup。
不同点: 进程是一个单根树状结构(pid = 0 为根),而 cgroup 整体来看是一个多树的森林结构(hirearchy 为根)。

一个典型的 hirearchy 挂载目录如下:

/cgroup/
├── blkio                           <--------------- hierarchy/root cgroup                   
│   ├── blkio.io_merged             <--------------- subsystem parameter
... ...
│   ├── blkio.weight
│   ├── blkio.weight_device
│   ├── cgroup.event_control
│   ├── cgroup.procs
│   ├── lxc                         <--------------- cgroup
│   │   ├── blkio.io_merged         <--------------- subsystem parameter
│   │   ├── blkio.io_queued
... ... ...
│   │   └── tasks                   <--------------- task list
│   ├── notify_on_release
│   ├── release_agent
│   └── tasks
...

subsystem 列表:

blkio — 块存储配额 >> this subsystem sets limits on input/output access to and from block devices such as physical drives (disk, solid state, USB, etc.).

cpu — CPU时间分配限制 >> this subsystem uses the scheduler to provide cgroup tasks access to the CPU.

cpuacct — CPU资源报告 >> this subsystem generates automatic reports on CPU resources used by tasks in a cgroup.

cpuset — CPU绑定限制 >> this subsystem assigns individual CPUs (on a multicore system) and memory nodes to tasks in a cgroup.

devices — 设备权限限制 >> this subsystem allows or denies ac
cess to devices by tasks in a cgroup.

freezer — cgroup停止/恢复 >> this subsystem suspends or resumes tasks in a cgroup.

memory — 内存限制 >> this subsystem sets limits on memory use by tasks in a cgroup, and generates automatic reports on memory resources used by those tasks.

net_cls — 配合tc进行网络限制 >> this subsystem tags network packets with a class identifier (classid) that allows the Linux traffic controller (tc) to identify packets originating from a particular cgroup task.

net_prio — 网络设备优先级 >> this subsystem provides a way to dynamically set the priority of network traffic per network interface.

ns — 资源命名空间限制 >> the namespace subsystem.

cgroup 操作准则与方法

操作准则
1. 一个 hirearchy 可以由多个 subsystem。
eg.

mount -t cgroup -o cpu,cpuacct,memoy cpu_and_mem /cgroup/cpu_and_mem
  1. 一个已经挂载的 subsystem 只能被再次挂载在一个空的 hirearchy 上。(已经 mount 一个 subsystem 的 hirearchy 不能挂载在一个已经被其他 hirearchy 挂载的 subsystem)
  1. 每个 task 只能在同一个 hirearchy 的唯一一个 cgroup 里(不能再同一个个 hirearchy 下有超过一个 cgroup 的 tasks 里同时哟这个进程的 pid)
  1. 子进程在被 fork 出时自动继承父进程所在 cgroup,但是 fork 之后可以按需调整到其他 cgroup。
  1. 其他
    限制一个 task 的唯一方法就是将其加入到一个 cgroup 的 task 里。
    多个 subsystem 可以挂载到一个 hirearchy 里,然后通过不同的 cgroup 中的 subsystem 参数来对不同的 task 进行限额。
    如果一个 hirearchy 有太多 subsystem,可以考虑重构,将 subsystem 挂到独立的 hirearchy;相应的,可以将多个 hirearchy 合并成一个 hirearchy。
    因为可以之挂载少量 subsystem,可以实现只对 task 单个方面的限额;同时一个 task 可以被加到多个 hirearchy 中,从而实现对多个资源的控制。

操作方法

挂载 subsystem
利用 cgconfig 服务及其配置文件 /etc/config.conf- 服务启动时自动挂载

subsystem = /cgroup/hirearchy;

命令行操作

mount -t cgroup -o subsystem name /cgroup/name

取消挂载

umount /cgroup/name

eg
挂载 cpuset,cpu,cpuacct,memory 4 个 subsystem 到 /cgroup/cpu_and_mem 目录(hirearchy)

mount -t cgroup -o cpuset,cpu,cpuacct,memory cpu_and_mem cgroup/cpu_and_mem

or

mount {
    cpuset = /cgroup/cpu_and_mem;
    cpu = /cgroup/cpu;
    cpuacct = /cgroup/apu_and_mem;
    memory = /cgroup/cpu_and_mem;
}

新建 / 删除 cgroup
利用 cgroup 服务及其配置文件 /etc/cgconfig.conf- 服务启动时自动挂载

group <name> {
    [<permissions>] <controller> { <param name> = <param value>;
        ...
    }
    ...
}

命令行操作
新建1 cgcreate -t uid:gid -a uid:gid -g subsystem:path
新建2 mkdir /cgroup/hirearchy/name/child_name
删除1 cgdelete subsystems:path (使用 -r 递归删除)
删除2 rm -rf /cgroup/hirearchy/name/child_name (cgconfig server not running)

权限管理
利用 cgroup 服务及其配置文件 /etc/config.conf- 服务启动时自动挂载

perm {
    task {
        uid = <task user>;
        gid = <task group>;
    }
    admin {
      uid = <admin name>;
      gid = <admin group>;
    }
}

命令行操作 chown
eg

group daemons {
      cpuset {
          cpuset.mems = 0;
          cpuset.cpus = 0;
      }
  }
  group daemons/sql {
      perm {
          task {
              uid = root;
              gid = sqladmin;
          } admin {
              uid = root;
              gid = root;
          }
      }
      cpuset {
          cpuset.mems = 0;
          cpuset.cpus = 0;
      }
  }

or

mkdir -p /cgroup/red/daemons/sql
chown root:root /cgroup/red/daemons/sql/*
chown root:sqladmin /cgroup/red/daemons/sql/tasks
echo 0 > /cgroup/red/daemons/cpuset.mems
echo 0 > /cgroup/red/daemons/cpuset.cpus
echo 0 > /cgroup/red/daemons/sql/cpuset.mems
echo 0 > /cgroup/red/daemons/sql/cpuset.cpus

cgroup 参数设定

命令行1 cgset -r parameter=value path_to_cgroup
命令行2 cgset --copy-from path_to_source_cgroup path_to_target_cgroup
文件 echo value > path_to_cgroup/parameter

eg

cgset -r cpuset.cpus=0-1 group1
cgset --copy-from group1/ group2/
echo 0-1 > /cgroup/cpuset/group1/cpuset.cpus

添加 task

命令行添加进程 cgclassify -g subsystem:path_to_cgroup pidlist
文件添加进程 echo pid > path_tocgroup/tasks
在 cgroup 中启动进程 cgexec -g subsystem:path_to_cgroup command arguments
在 cgroup 中启动服务 echo 'CGROUP_DAEMON="subsystem:control_group"' >> /etc/sysconfig/<service>
利用 cgrulesengd 服务初始化,在配置文件 /etc/cgrules.conf 中

user<:command> subsystems control_group

其中:
+用户user的所有进程的subsystems限制的group为control_group
+<:command>是可选项,表示对特定命令实行限制
+user可以用@group表示对特定的 usergroup 而非user
+可以用*表示全部
+%表示和前一行的该项相同

eg

cgclassify -g cpu,memory:group1 1701 1138
  echo -e "1701\n1138" |tee -a /cgroup/cpu/group1/tasks /cgroup/memory/group1/tasks
  cgexec -g cpu:group1 lynx http://www.redhat.com
  sh -c "echo \$$ > /cgroup/lab1/group1/tasks && lynx http://www.redhat.com"

subsystem 配置

blkio - BLOCK IO 限制

common

blkio.io_serviced - 报告CFQ scheduler统计的此cgroup对特定设备的IO操作(read, write, sync, or async)次数 - device_types:node_numbers operation number

blkio.io_service_bytes - 报告CFQ scheduler统计的此cgroup对特定设备的IO操作(read, write, sync, or async)数据量 - device_types:node_numbers operation bytes

blkio.io_service_time - 报告CFQ scheduler统计的此cgroup对特定设备的IO操作(read, write, sync, or async)时间(单位ns) - device_types:node_numbers operation time

Proportional weight division 策略 - 按比例分配block io资源

blkio.weight - 100-1000的相对权重,会被blkio.weight_device的特定设备权重覆盖

blkio.weight_device - 特定设备的权重 - device_types:node_numbers weight

I/O throttling (Upper limit) 策略 - 设定IO操作上限

每秒读/写数据上限 
blkio.throttle.read_bps_device - device_types:node_numbers bytes_per_second blkio.throttle.write_bps_device - device_types:node_numbers bytes_per_second

每秒读/写操作次数上限 
blkio.throttle.read_iops_device - device_types:node_numbers operations_per_second blkio.throttle.write_iops_device - device_types:node_numbers operations_per_second

每秒具体操作(read, write, sync, or async)的控制 blkio.throttle.io_serviced - device_types:node_numbers operation operations_per_second blkio.throttle.io_service_bytes - device_types:node_numbers operation bytes_per_second

cpu - CPU 使用时间限额

CFS(Completely Fair Scheduler)策略 - CPU最大资源限制

cpu.cfs_period_us, cpu.cfs_quota_us - 必选 - 二者配合,前者规定时间周期(微秒)后者规定cgroup最多可使用时间(微秒),实现task对单个cpu的使用上限(cfs_quota_us是cfs_period_us的两倍即可限定在双核上完全使用)。

cpu.stat - 记录cpu统计信息,包含 nr_periods(经历了几个cfs_period_us), nr_throttled (cgroup里的task被限制了几次), throttled_time (cgroup里的task被限制了多少纳秒)

cpu.shares - 可选 - cpu轮转权重的相对值

RT(Real-Time scheduler)策略 - CPU最小资源限制

cpu.rt_period_us, cpu.rt_runtime_us
二者配合使用规定cgroup里的task每cpu.rt_period_us(微秒)必然会执行cpu.rt_runtime_us(微秒)

cpuacct - CPU 资源报告

cpuacct.usage - cgroup中所有task的cpu使用时长(纳秒)
cpuacct.stat - cgroup中所有task的用户态和内核态分别使用cpu的时长
cpuacct.usage_percpu - cgroup中所有task使用每个cpu的时长

memory - 内存限制

memory.usage_in_bytes - 报告内存限制byte
memory.memsw.usage_in_bytes - 报告cgroup中进程当前所用内存+swap空间
memory.max_usage_in_bytes - 报告cgoup中的最大内存使用
memory.memsw.max_usage_in_bytes - 报告最大使用到的内存+swap
memory.limit_in_bytes - cgroup - 最大内存限制,单位k,m,g. -1代表取消限制
memory.memsw.limit_in_bytes - 最大内存+swap限制,单位k,m,g. -1代表取消限制

以上就是 cgroup 的简单介绍。