cgroup 介绍 与使用

简介:

一.cgroup介绍

  1. Cgroups是control groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源(如:cpu,memory,IO等等)的机制。最初由google的工程师提出,后来被整合进Linux内核。Cgroups也是LXC为实现虚拟化所使用的资源管理手段,可以说没有cgroups就没有LXC。
  2. Cgroups最初的目标是为资源管理提供的一个统一的框架,既整合现有的cpuset等子系统,也为未来开发新的子系统提供接口。现在的cgroups适用于多种应用场景,从单个进程的资源控制,到实现操作系统层次的虚拟化(OS Level Virtualization)。Cgroups提供了一下功能:
    1).限制进程组可以使用的资源数量(Resource limiting )。比如:memory子系统可以为进程组设定一个memory使用上限,一旦进程组使用的内存达到限额再申请内存,就会出发OOM(out of memory)。
    2).进程组的优先级控制(Prioritization )。比如:可以使用cpu子系统为某个进程组分配特定cpu share。
    3).记录进程组使用的资源数量(Accounting )。比如:可以使用cpuacct子系统记录某个进程组使用的cpu时间
    4).进程组隔离(Isolation)。比如:使用ns子系统可以使不同的进程组使用不同的namespace,以达到隔离的目的,不同的进程组有各自的进程、网络、文件系统挂载空间。
    5).进程组控制(Control)。比如:使用freezer子系统可以将进程组挂起和恢复。


Cgroups相关概念及其关系

  1. 相关概念
    1).任务(task)。在cgroups中,任务就是系统的一个进程。
    2).控制族群(control group)。控制族群就是一组按照某种标准划分的进程。Cgroups中的资源控制都是以控制族群为单位实现。一个进程可以加入到某个控制族群,也从一个进程组迁移到另一个控制族群。一个进程组的进程可以使用cgroups以控制族群为单位分配的资源,同时受到cgroups以控制族群为单位设定的限制。
    3).层级(hierarchy)。控制族群可以组织成hierarchical的形式,既一颗控制族群树。控制族群树上的子节点控制族群是父节点控制族群的孩子,继承父控制族群的特定的属性。
    4).子系统(subsytem)。一个子系统就是一个资源控制器,比如cpu子系统就是控制cpu时间分配的一个控制器。子系统必须附加(attach)到一个层级上才能起作用,一个子系统附加到某个层级以后,这个层级上的所有控制族群都受到这个子系统的控制。


  1. 相互关系
    1).每次在系统中创建新层级时,该系统中的所有任务都是那个层级的默认 cgroup(我们称之为 root cgroup ,此cgroup在创建层级时自动创建,后面在该层级中创建的cgroup都是此cgroup的后代)的初始成员。
    2).一个子系统最多只能附加到一个层级。
    3).一个层级可以附加多个子系统
    4).一个任务可以是多个cgroup的成员,但是这些cgroup必须在不同的层级。
    5).系统中的进程(任务)创建子进程(任务)时,该子任务自动成为其父进程所在 cgroup 的成员。然后可根据需要将该子任务移动到不同的 cgroup 中,但开始时它总是继承其父任务的cgroup。


  1. Cgroups子系统介绍

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



二.使用

#yum install libcgroup
#cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

配置文件
#cat /etc/cgconfig.conf

  • mount {
  • cpuset = /cgroup/cpuset;
  • memory = /cgroup/memory;
  • net_cls = /cgroup/net_cls;
  • freezer = /cgroup/freezer;
  • }
  • group httpd {
  • memory {
  • memory.limit_in_bytes = 10M;
  • }
  • }

配置介绍

  • group name {
  • [permissions]
  • controller {
  • param name = param value;
  • }
  • …} 
    name: 指定cgroup的名称
    permissions:可选项,指定cgroup对应的挂载点文件系统的权限,root用户拥有所有权限。
    controller:子系统的名称
    param name 和 param value:子系统的属性及其属性值

#cat /etc/cgrules.conf
auser:ab memory httpd

用户或@组:命令 子系统 cgroup名称
@auser:ab memory httpd



#systemctl restart cgconfig.service
#systemctl restart cgred.service

配置是限制auser用户 执行ab时,当使用内存超过10M时,进程就会被杀。(默认配置)



内核相关的配置
由于memory subsystem比较耗资源,所以内核专门添加了一个参数cgroup_disable=memory来禁用整个memory subsystem,这个参数可以通过GRUB在启动系统的时候传给内核,加了这个参数后内核将不再进行memory subsystem相关的计算工作,在系统中也不能挂载memory subsystem。
上面提到的CONFIG_MEMCG_SWAP和CONFIG_MEMCG_KMEM都是扩展功能,在使用前请确认当前内核是否支持,

这里CONFIG_MEMCG_SWAP和CONFIG_MEMCG_KMEM等于y表示内核已经编译了该模块,即支持相关功能
$cat /boot/config-uname -r|grep CONFIG_MEMCG (我也是醉了,新版51,这引号自带背影的)

CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
#CONFIG_MEMCG_SWAP_ENABLED is not set
CONFIG_MEMCG_KMEM=y

CONFIG_MEMCG_SWAP控制内核是否支持Swap 扩展,而CONFIG_MEMCG_SWAP_ENABLED(3.6以后的内核新加的参数)控制默认情况下是否使用Swap 扩展,由于Swap 扩展比较耗资源,所以很多发行版(比如ubuntu)默认情况下会禁用该功能(这也是上面那行被注释掉的原因),当然用户也可以根据实际情况,通过设置内核参数swapaccount=0或者1来手动禁用和启用Swap Extension。


测试

[auser@app ~]$ ab -c 10 -n 1000000 http://IP/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.90.177 (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
已杀死

#top 观察auser使用ab命令时候内存使用情况,当使用超过10M大概持续2到3秒时,会发现进程被杀死。

一旦设置了内存限制,将立即生效,并且当物理内存使用量达到limit的时候,memory.failcnt的内容会加1,但这时进程不一定就会被kill掉,内核会尽量将物理内存中的数据移到swap空间上去,如果实在是没办法移动了(设置的limit过小,或者swap空间不足),默认情况下,就会kill掉cgroup里面继续申请内存的进程。

当物理内存达到上限后,系统的默认行为是kill掉cgroup中继续申请内存的进程,那么怎么控制这样的行为呢?答案是配置memory.oom_control
这个文件里面包含了一个控制是否为当前cgroup启动OOM-killer的标识。如果写0到这个文件,将启动OOM-killer,当内核无法给进程分配足够的内存时,将会直接kill掉该进程;如果写1到这个文件,表示不启动OOM-killer,当内核无法给进程分配足够的内存时,将会暂停该进程直到有空余的内存之后再继续运行;同时,memory.oom_control还包含一个只读的under_oom字段,用来表示当前是否已经进入oom状态,也即是否有进程被暂停了。
#cat /cgroup/memory/httpd/memory.oom_control
oom_kill_disable 0
under_oom 0

#echo 0 > memory.swappiness 设置swappiness为0 禁止当前cgroup使用swap
当超过限额,会被直接杀掉,不会使用swap空间。

#echo 1 > /cgroup/memory/httpd/memory.oom_control 注意:不要vim编辑去写,直接echo 1进去,虽然有两行配置
oom_kill_disable等于1的时候内存达到限额的时候会暂停
当临时修改扩大内存时,进程又继续工作,当又不够时,就会再次暂停工作。


进程迁移

当一个进程从一个cgroup移动到另一个cgroup时,默认情况下,该进程已经占用的内存还是统计在原来的cgroup里面,不会占用新cgroup的配额,但新分配的内存会统计到新的cgroup中(包括swap out到交换空间后再swap in到物理内存中的部分)。
我们可以通过设置memory.move_charge_at_immigrate让进程所占用的内存随着进程的迁移一起迁移到新的cgroup中

enable: echo 1 > memory.move_charge_at_immigrate

disable:echo 0 > memory.move_charge_at_immigrate
注意: 就算设置为1,但如果不是thread group的leader,这个task占用的内存也不能被迁移过去。换句话说,如果以线程为单位进行迁移,必须是进程的第一个线程,如果以进程为单位进行迁移,就没有这个问题。
当memory.move_charge_at_immigrate为0时,就算当前cgroup中里面的进程都已经移动到其它cgropu中去了,由于进程已经占用的内存没有被统计过去,当前cgroup有可能还占用很多内存,当移除该cgroup时,占用的内存需要统计到谁头上呢?答案是依赖memory.use_hierarchy的值,如果该值为0,将会统计到root cgroup里;如果值为1,将统计到它的父cgroup里面。

相关参数:

1)force_empty :

当向memory.force_empty文件写入0时(echo 0 > memory.force_empty),将会立即触发系统尽可能的回收该cgroup占用的内存。该功能主要使用场景是移除cgroup前(cgroup中没有进程),先执行该命令,可以尽可能的回收该cgropu占用的内存,这样迁移内存的占用数据到父cgroup或者root cgroup时会快些。

memory.swappiness :

该文件的值默认和全局的swappiness(/proc/sys/vm/swappiness)一样,修改该文件只对当前cgroup生效,其功能和全局的swappiness一样

有一点和全局的swappiness不同,那就是如果这个文件被设置成0,就算系统配置的有交换空间,当前cgroup也不会使用交换空间。

2)memory.use_hierarchy:

该文件内容为0时,表示不使用继承,即父子cgroup之间没有关系;当该文件内容为1时,子cgroup所占用的内存会统计到所有祖先cgroup中。
如果该文件内容为1,当一个cgroup内存吃紧时,会触发系统回收它以及它所有子孙cgroup的内存。
注意: 当该cgroup下面有子cgroup或者父cgroup已经将该文件设置成了1,那么当前cgroup中的该文件就不能被修改。

3)memory.soft_limit_in_bytes:

有了hard limit(memory.limit_in_bytes),为什么还要soft limit呢?hard limit是一个硬性标准,绝对不能超过这个值,而soft limit可以被超越,既然能被超越,要这个配置还有啥用?先看看它的特点

当系统内存充裕时,soft limit不起任何作用
当系统内存吃紧时,系统会尽量的将cgroup的内存限制在soft limit值之下(内核会尽量,但不100%保证)
从它的特点可以看出,它的作用主要发生在系统内存吃紧时,如果没有soft limit,那么所有的cgroup一起竞争内存资源,占用内存多的cgroup不会让着内存占用少的cgroup,这样就会出现某些cgroup内存饥饿的情况。如果配置了soft limit,那么当系统内存吃紧时,系统会让超过soft limit的cgroup释放出超过soft limit的那部分内存(有可能更多),这样其它cgroup就有了更多的机会分配到内存。

从上面的分析看出,这其实是系统内存不足时的一种妥协机制,给次等重要的进程设置soft limit,当系统内存吃紧时,把机会让给其它重要的进程。

注意: 当系统内存吃紧且cgroup达到soft limit时,系统为了把当前cgroup的内存使用量控制在soft limit下,在收到当前cgroup新的内存分配请求时,就会触发回收内存操作,所以一旦到达这个状态,就会频繁的触发对当前cgroup的内存回收操作,会严重影响当前cgroup的性能。


CPU、内存、IO和网络都能通过cgroup进行管控。通过资源再分配合理的优化虚拟化或者容器。

未完待续


      本文转自潘阔 51CTO博客,原文链接:http://blog.51cto.com/pankuo/2044862,如需转载请自行联系原作者





相关文章
|
Docker 容器
Cgroup 驱动
Cgroup 驱动
85 0
|
存储 缓存 Linux
blkio cgroup
blkio 是 cgroup v1 中的一个子系统,使用 cgroup v1 blkio 子系统主要是为了减少进程之间共同读写同一块磁盘时相互干扰的问题。
475 1
|
容器
pid cgroup
pid cgroup 简介
138 0
cgroup
创建两个python进程,然后分别绑定在第0,1号CPU上.
cgroup
|
Linux 容器 Ubuntu
|
程序员 Linux KVM