Cgroup的管理问题:
一般来说,Cgroup的设计在一般情况下还是没什么问题的,除了操作上的用户体验不是很好,但基本满足我们的一般需求了。
只是有个叫Tejun Heo的同学非常不爽,他在Linux社区里对cgroup吐了一把槽,还引发了内核组的各种讨论。
对于Tejun Heo同学来说,cgroup设计的相当糟糕。他给出了些例子:
大意就是说,如果有多种层级关系,也就是说有多种对进程的分类方式,比如,我们可以按用户来分,分成Professor和Student,同时,也有按应用类似来分的,比如WWW和NFS等。那么,当一个进程即是Professor的,也是WWW的,那么就会出现多层级正交的情况,从而出现对进程上管理的混乱。另外,一个case是,如果有一个层级A绑定cpu,而层级B绑定memory,还有一个层级C绑定cputset,而有一些进程有的需要AB,有的需要AC,有的需要ABC,管理起来就相当不易。
hierarchy may be collapsed from leaf towards root when viewed from specific controllers. For example, a given configuration might not care about how memory is distributed beyond a certain level while still wanting to control how CPU cycles are distributed.
当我们通过指定的控制器来观察时,层级可能会从叶子到根折叠。打个比方,一个配置可能不在意内存如何分配超过一定水平,但想要控制cpu周期分配。
层级操作起来比较麻烦,而且如果层级变多,更不易于操作和管理,虽然那种方式很好实现,但是在使用上有很多的复杂度。你可以想像一个图书馆的图书分类问题,你可以有各种不同的分类,分类和图书就是一种多对多的关系。
总体来说,基于层级的Cgroup就是不灵活,树的深度可能是无限的,这就导致实际操作中管理非常繁琐。
就我个人觉得,上面说的如此复杂的进程管理几乎用不到,上面的场景光管理本身就很复杂了。至于用户体验,封装一下即可。
Unified hierachy特性
不过,基于上述原因,在kernel 3.16中正式加入了unified hierarchy特性,这个特性目前仍然在开发,所以如果想显式开启该特性需要__DEVEL__sane_behavior通过看名字,我们也能发现这个特性仍然在开发。
1 |
mount -t cgroup -o __DEVEL__sane_behavior cgroup $MOUNT_POINT
|
在之前的cgroup hierarchy中,我们知道一个hierarchy可以绑定一个子系统,也可以同时绑定12个子系统(越来越多了)。
如果我们开启__DEVEL__sane_behavior特性,我们看到cgroup.controllers 存在的子系统,在unified hierarchy中,系统会把所有子系统都挂载到根层级下,只有leaf节点可以存在tasks,非叶子节点只进行资源控制。
1 |
# mount -t cgroup -o __DEVEL__sane_behavior cgroup /sys/fs/cgroup |
2 |
# cat /sys/fs/cgroup/cgroup.controllers |
3 |
cpuset cpu cpuacct memory devices freezer net_cls blkio perf_event net_prio hugetlb |
现在我们在root cgroup下面创建parent与child,根层级的cgroup.subtree_control 控制parents的cgroup.controllers
1 |
# mkdir /sys/fs/cgroup/parent |
2 |
# mkdir /sys/fs/cgroup/parent/child |
3 |
# echo "+memory +cpu" > /sys/fs/cgroup/cgroup.subtree_control |
4 |
# cat /sys/fs/cgroup/parent/cgroup.controllers |
5 |
cpu memory |
如此往复,上级的cgroup.subtree_control控制下级的cgroup.controllers。
如果我指定根层级的cgroup.subtree_control 可以使能memory与cpu两个子系统,也就是说parents中可以控制memory、cpu两个子系统。而child如果没有指定子系统,是不能控制memory与cpu的。
举个例子:
01 |
# A(b,m) - B(b,m) - C (b) |
02 |
# \ - D (b) - E |
03 |
|
04 |
# 下面的命令中, +表示enable, -表示disable |
05 |
|
06 |
# 在B上的enable blkio |
07 |
# echo +blkio > A/cgroup.subtree_control |
08 |
|
09 |
# 在C和D上enable blkio |
10 |
# echo +blkio > A/B/cgroup.subtree_control |
11 |
|
12 |
# 在B上enable memory |
13 |
# echo +memory > A/cgroup.subtree_control |
上面的语句中,b代表blkio,m代表memory,A是根,在这个结构中ACD都拥有进程.
比如:
- C控制blkio的限制,但是memory不受限,共享B。
- E比较特殊,如果没有指定子系统,那么blkio受D限制,memory受B限制。
具体操作方式在上面parents、child已声明。
特点:
- cgroup只有上级控制下级,本层的cgroup.controllers文件是个只读的,其中的内容就看上级的subtree_control里有什么了。为什么呢?因为比如你想对D限制cpu.share,你把层级挂到D的话,和D平级的C就有问题了,它没法设置权重。所以肯定要挂到父节点。
- cgroup的文件夹关系是一个包含关系。即,B设置了memory资源配额。那么BCDE共享B的memory资源。CDE其实包含在B中。
- 只有leaf节点可以存在tasks,非叶子节点只进行资源控制。因此:任何被配置过subtree_control的目录都不能绑定进程,根结点除外。所以,A,C,D,E可以绑上进程,但是B不行。如果该cgroup中已有进程,那么只有在关联的组没有包含进程的时候,cgroup.subtree_control文件能被用来改变控制器的设置。
总结:
个人理解,这个新的控制方式是,先让cgroup形成一个树,因为Cgroup的资源管理就是一个层次的结构,总体来看就是一颗树。然后往其中的节点来加入子系统,以提供它的下一级资源分配的功能。比如在B中添加了memory层级,C和D的内存配额就可以控制了。
按耗子大叔的说法,这种方式干净的区分开了两个事,一个是进程的分组,一个是对分组的资源控制。确实如此,因为Cgroup代表的是进程分组,子系统用于资源控制。
以上内容参考自:
http://coolshell.cn/articles/17049.html
http://lzz5235.github.io/2015/03/02/cgroup-2.html
http://events.linuxfoundation.org/sites/events/files/slides/2014-KLF.pdf
转载请注明:旅途@KryptosX » 下一代Cgroup——unified hierarchy