在云计算领域中,我们经常会在一个物理上部署多个应用或者多个虚拟机,而这些应用或者虚拟机可能属于不同的客户。那么如何隔离这些应用之间的资源争用,让每个客户都能发挥自己所购买的物理资源呢,这就是cgrouop能发挥作用的地方了。

CGroup介绍

CGroup是Linux内核提供的可以限制、隔离进程组 (process groups) 所使用的物理资源 (如 cpu memory i/o 等等)。 全称是Control Groups,从2.6.24 内核引入,并不是全新创造的,而是将进程管理从 cpuset 中剥离出来。CGroups 是管理虚拟化资源手段。
CGroup 提供了一个虚拟文件系统,是进行分组管理和各子系统设置的接口。所以要使用 CGroup,必须挂载 CGroup 文件系统。通过挂载选项指定使用哪个子系统。
  1. CGroup 相关概念

    任务(task):任务就是系统的一个进程;
    控制群(control group):控制群是一组按照某种标准划分的进程。Cgroup的资源控制都是以控制群为单位实现。一个进程可以加入到某个控制群,也可以迁移到另一个控制群。
    层级(hierarchy):控制群可以组织成 hierarchical 的树形式。控制群树上的子节点控制群是父节点控制群的孩子,继承父控制族群的特定的属性;
    子系统(subsystem):子系统是一个资源控制器,比如 cpu 子系统就是控制 cpu 时间分配的控制器。子系统必须附加(attach)到一个层级上才能起作用,一个子系统附加到某个层级以后,这个层级上的所有控制群都受到这个子系统的控制。

  2. 相互关系

    在系统中创建新层级时,系统中的所有任务都是那个层级的默认 cgroup(称为root cgroup。
    一个子系统最多只能附加到一个层级;
    一个层级可以附加多个子系统;
    一个任务可以是多个 cgroup 的成员,但是这些 cgroup 必须在不同的层级;
    系统中的进程的子进程,自动成为其父进程所在 cgroup 的成员。可根据需要将该子任务移动到不同的 cgroup 中,开始会继承其父任务的 cgroup。
    CGroup 层级图如下图:

    当前系统准备了9个子系统,以下是每个子系统的详细说明:
    blkio设置限制每个块设备的输入输出控制。
    cpu 使用调度程序为cgroup任务提供cpu的访问。
    cpuacct 产生cgroup任务的cpu资源报告。
    cpuset 为cgroup任务分配单独的cpu和内存。
    devices 允许或拒绝cgroup任务对设备的访问。
    freezer 暂停和恢复cgroup任务。
    memory 设置每个cgroup的内存限制以及产生内存资源报告。
    net_cls 标记每个网络包以。
    ns 名称空间子系统。

  3. 安装使用

    需要安装libcap-devel libcgroup
    启用cgroup命令:service cgconfig restart
    查看已存在子系统:lssubsys –am
    清除所有挂载点内部文件:cgclear #,相当于service cgconfig stop
    默认配置文件/etc/cgconfig.conf:主要包含了两个主要类型:mount和group。mount是指创建以及挂载哪些层次为虚拟文件系统,并附上子系统的层次结构。
    Cgroup默认挂载点(CentOS):/cgroup

  4. 常用命令

    cgclassify –将运行的任务移动到一个或者多个cgroup,例如:cgclassify -g cpu:yy [pid]
    cgclear --删除层级中的所有cgroup。
    cgconfigparser --解析cgconfig.conf文件和并挂载层级。
    cgcreate -- cgcreate在层级中创建新cgroup。
    cgdelete -- cgdelete命令删除指定的cgroup。
    cgexec – 这个命令是cgroup启动的cgexec命令在指定的cgroup中运行任务。例如:cgexec -g "blkio:foo" dd if=/dev/zero of=/dev/null &。如果不使用那就手动把进程号写入到tasks中吧。
    cgget -- cgget命令查看cgroup组里面设置的资源的限制。
    cgrulesengd --在 cgroup 中发布任务。
    cgset -- cgset 命令为 cgroup 设定参数。路径相对于根的/cgroup,如果想设置根的参数使用gset命令。
    lscgroup --命令列出层级中的 cgroup。
    lssubsys --命令列出包含指定子系统的层级,使用-am参数可以看到未挂载的所有子系统。。

  5. CPU限制

    cfs_quota_us和cfs_period_us
    在多核情况下cfs_quota_us是可以大于 cfs_period_us 的。有 n 个核时,一个控制组中的进程自然最多就能用到 n 倍的 cpu 时间
    cpu.rt_period_us和cpu.rt_runtime_us
    cpu.rt_period_us、cpu.rt_runtime_us 对应的是实时进程的限制。
    cpu.stat
    cpu.stat是资源限制的统计。nr_periods、nr_throttled 就是总共经过的周期,和其中受限制的周期。throttled_time 就是总共被控制组掐掉的 cpu 使用时间。
    cpu.shares
    cpu.shares也是限制 cpu 使用的。与 cpu.cfs_quota_us、cpu.cfs_period_us 有挺大区别。cpu.shares 不是限制绝对的 cpu 时间,而是控制各个组之间的配额。
    cpuset
    cpuset 子系统就是处理进程可以使用的 cpu 核心和内存节点,以及其他一些相关配置。这部分的很多配置都和 NUMA 有关。其中 cpuset.cpus、cpuset.mems 就是用来限制进程可以使用的 cpu 核心和内存节点的。
    cpuacct.stat
    cpuacct 子系统有资源统计的功能,用来做 cpu 资源统计。cpuacct.stat 统计了该控制组中进程用户态和内核态的 cpu 使用量,单位是 jiffies、cpu 滴答数。内核时钟频率可以用 getconf CLK_TCK 来获取,通常是 100,将将看到的值除以这个值就可以换算成秒。

  6. 内存限制

    如果内存使用超过了cgroups的限制,会触发out of memory,导致进程被kill掉。
    可以通过配置关掉cgroups oom kill进程,通过memory.oom_control来实现(oom_kill_disable 1),但是尽管进程不会被直接杀死,但进程也进入了休眠状态,无法继续执行,仍让无法服务

  7. IO限制

    echo '5:0 1048576' > /cgroup/blkio/yy/blkio.throttle.read_bps_device #其中5:0对应主设备号和副设备号,可以通过ls -l /dev/sda查看
    数字1048576表示多少字节。
    blkio.throttle.read_bps_device
    blkio.throttle.read_iops_device
    blkio.throttle.write_bps_device
    blkio.throttle.write_iops_device
    blkio.weight
    blkio.weight_device
    以上用来控制进程磁盘 io 的。带“throttle”的是节流阀,将流量限制在绝对值下,而“weight”就是分配 io 的权重。类似和 cpu 子系统的 quota 和 shares,一种是绝对限制,另一种是相对限制。blkio.weight_device 是分设备的。写入时,前面再加上设备号即可。

  8. 常见问题

    cgroup change of group failed
    答:进程无法切换到指定的cgroup,一般都是配置的参数有问题。例如在单核情况下cfs_quota_us是不能大于 cfs_period_us。下层的资源不能超过上层。具体的说,就是下层的 cpu.cfs_period_us 值不能小于上层的值,cpu.cfs_quota_us 值不能大于上层的值。
    此外如何使用了CPUSET,则必须设置cpuset.cpus 和 cpuset.mems。
    Some subsystems have mandatory parameters that must be set before you can move a task into a cgroup which uses any of those subsystems. For example, before you move a task into a cgroup which uses the cpuset subsystem, the cpuset.cpus and cpuset.mems parameters must be defined for that cgroup.
    cgroups can't be listed: Cgroup is not mounted
    答:cgroup文件系统未挂载,cgclear会导致文件系统卸载。重新执行
    #mount -t cgroup cgroup /sys/fs/cgroup

  9. 参考链接

    http://www.jianshu.com/p/dc3140699e79