利用内核cgroup机制轻松实现类似docker的系统资源管控
近几年,以docker为代表的容器技术异常火热,它的轻量、高效让人欣喜若狂,它被赋予了改变传统IT运维的使命。相信随着时间推移,以容器云为落地形式的产品将真正实现这一使命。
我们都知道docker能够实现资源的隔离和控制,正当打算引入docker来管理产品不同业务的资源占用时,发现它的隔离性是我们所不需要的,而我们都知道,docker底层实际上是利用了linux内核提供的namespace和cgroup机制,而前者是用于资源隔离的,后者是用于资源控制的。这时,我们想到了直接用cgroup来实现。下面先谈谈什么是cgroup,接着讲解如何使用cgroup来轻松实现对系统资源的管控:
首先,什么是cgroup:
cgroup是Linux内核提供的一种机制,这种机制可以根据特定的行为,把一系列系统任务及其子任务整合(或分隔)到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架。cgroups可以限制、记录、隔离进程组所使用的物理资源(包括:CPU、memory、IO等),为容器实现虚拟化提供了基本保证,是构建Docker等一系列虚拟化管理工具的基石。
cgroup提供了哪些功能:
1、资源限制(Resource Limitation):cgroups可以对进程组使用的资源总额进行限制。如设定应用运行时使用内存的上限,一旦超过这个配额就发出OOM(Out of Memory)。
2、优先级分配(Prioritization):通过分配的CPU时间片数量及硬盘IO带宽大小,实际上就相当于控制了进程运行的优先级。
3、资源统计(Accounting): cgroups可以统计系统的资源使用量,如CPU使用时长、内存用量等等,这个功能非常适用于计费。
4、进程控制(Control):cgroups可以对进程组执行挂起、恢复等操作。
对开发者来说,cgroup有哪些有趣的特点:
1、cgroups的API以一个伪文件系统的方式实现,即用户可以通过文件操作实现cgroups的组织管理。
2、cgroups的组织管理操作单元可以细粒度到线程级别,用户态代码也可以针对系统分配的资源创建和销毁cgroups,从而实现资源再分配和管理。
3、所有资源管理的功能都以“subsystem(子系统)”的方式实现,接口统一。
4、子进程创建之初与其父进程处于同一个cgroups的控制组。
本质上,cgroups是内核附加在程序上的一系列钩子(hooks),通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的。
好了,下面到主题了,cgroup有这么一些特性,怎么用起来呢,下面分步骤简要描述整个过程:
1、更新linux内核,加入对cgroup机制的支持
2、安装libcgroup,libcgroup是一个开源cgroup工具包,利用它可以更方便使用cgroup特性
(下载地址:https://launchpad.net/ubuntu/+source/libcgroup/0.41-8ubuntu1)
1)解压上面的压缩包
2)设置ac_default_prefix指定安装路径,接着执行./configure
3)make clean;make
4)make install
5)拷贝安装文件、脚本、配置到设备上,其中部分启动脚本,包括cgconfig、cgred存在于samples目录下
6)修改/etc/init.d/cgconfig、/etc/init.d/cgred等脚本运行出错问题
3、启动cgconfig、cgred守护服务
1)配置/etc/cgconfig.conf、/etc/cgrules.conf
#######/etc/cgconfig.conf(供cgconfig加载,用于mount挂载成cgroup文件系统)#######
#cgconfigparser -l cgconfig.conf
mount {
cpu = /sys/fs/cgroup;
memory = /sys/fs/cgroup;
cpuset = /sys/fs/cgroup;
cpuacct = /sys/fs/cgroup;
devices = /sys/fs/cgroup;
freezer = /sys/fs/cgroup;
blkio = /sys/fs/cgroup;
hugetlb = /sys/fs/cgroup;
}
group cgroup1{
perm{
admin{
uid=root;
gid=root;
}
task{
uid=root;
gid=root;
}
}
cpuset{
cpuset.cpus=2;
cpuset.mems=0;
}
cpu{
cpu.shares=1024;
}
memory{
memory.limit_in_bytes=40M;
}
blkio{
blkio.weight=1000;
}
}
group cgroup2{
perm{
admin{
uid=root;
gid=root;
}
task{
uid=root;
gid=root;
}
}
cpuset{
cpuset.cpus=2;
cpuset.mems=0;
}
cpu{
cpu.shares=512;
}
memory{
memory.limit_in_bytes=40M;
}
blkio{
blkio.weight=1000;
}
}
#########/etc/cgrules.conf(供cgred加载,用于控制不同名字进程加入指定cgroup,怎么样,这个是不是很叼!)########
#<user> <controllers> <destination>
#john cpu usergroup/faculty/john/
#john:cp cpu usergroup/faculty/john/cp
#@student cpu,memory usergroup/student/
*:test_cpu1.sh * cgroup1 #模拟测试cpu资源分配有效性
*:test_mem1.sh * cgroup1 #模拟测试内存资源分配有效性
*:test_blk1.sh * cgroup1 #模拟测试io资源分配有效性
*:test_cpuset.sh * cgroup1 #模拟测试cpu core分配有效性
*:test_blk2.sh * cgroup2 #模拟测试io资源分配有效性
*:test_cpu2.sh * cgroup2 #模拟测试cpu资源分配有效性
*:test_mem2.sh * cgroup2 #模拟测试内存资源分配有效性
2)使用/etc/init.d/cgconfig start、/etc/init.d/cgred start启动服务
3)启动成功之后可以使用多个命令查看cgroup信息,如lscgroup/lssubsys/cgget/等
4、到这里,就已经完成了基本环境的搭建,下一步就可以通过脚本模拟各种资源占用(包括cpu/内存/io/cpu core等)来测试cgroup
对应子系统有效性了
由于时间关系这里就先不描述具体的测试过程了,可以自行摸索下,有疑问可以留言
http://www.infoq.com/cn/articles/docker-kernel-knowledge-cgroups-resource-isolation/
http://www.ibm.com/developerworks/cn/linux/1506_cgroup/index.html#ibm-pcon
libcgroup:
http://libcg.sourceforge.net/html/index.html
libcgroup使用:
http://www.jianshu.com/p/dc3140699e79
https://access.redhat.com/documentation/zh-CN/Red_Hat_Enterprise_Linux/6/html/Resource_Management_Guide/
http://www.elmerzhang.com/2012/12/28/cgroups-learning-6-blkio-subsystem/
内核读写文件过程分析:
http://oenhan.com/linux-kernel-write
mmap和direct io区别:
http://www.cnblogs.com/zhaoyl/p/5901680.html