1.cgroup介绍
cgroup是control group的简称,它为Linux内核提供了一种任务聚集和划分的机制,通过一组参数集合将
一些任务组织成一个或多个子系统。
子系统是根据cgroup对任务的划分功能将任务按照一种指定的属性划分成的一个组,主要用来实现资源的控制。
在cgroup中,划分成的任务组以层次结构的形式组织,多个子系统形成一个数据结构中类似多根树的结构。
cgroup包含了多个孤立的子系统,每一个子系统代表单一的资源,目前,redhat默认支持10个子系统,
但默认只挂载了8个子系统,ubuntu 12.04 默认支持8个子系统,但默认只挂载了5个子系统。
1.1.CGroup 功能及组成
CGroup 是将任意进程进行分组化管理的 Linux 内核功能。CGroup 本身是提供将进程进行分组化管理的功能和接口的基础结构,
I/O 或内存的分配控制等具体的资源管理功能是通过这个功能来实现的。这些具体的资源管理功能称为 CGroup 子系统或控制器。
CGroup 子系统有控制内存的 Memory 控制器、控制进程调度的 CPU 控制器等。运行中的内核可以使用的 Cgroup 子系统由/proc/cgroup 来确认。
1.2.cgroup子系统介绍
当然也用户可以自定义子系统并进行挂载。
下面对每一个子系统进行简单的介绍:
1)blkio 设置限制每个块设备的输入输出控制。例如:磁盘,光盘以及usb等等。
2)cpu 使用调度程序为cgroup任务提供cpu的访问。
3)cpuacct 产生cgroup任务的cpu资源报告。
4)cpuset 如果是多核心的cpu,这个子系统会为cgroup任务分配单独的cpu和内存。
5)devices 允许或拒绝cgroup任务对设备的访问。
6)freezer 暂停和恢复cgroup任务。
7)memory 设置每个cgroup的内存限制以及产生内存资源报告。
8)net_cls 标记每个网络包以供cgroup方便使用。
9)ns 名称空间子系统。
10)perf_event 增加了对每group的监测跟踪的能力,即可以监测属于某个特定的group的所有线程以及运行在特定CPU上的线程,
此功能对于监测整个group非常有用,具体参见 http://lwn.net/Articles/421574/
1.3.CGroup 支持的文件种类
CGroup 支持的文件种类
文件名 R/W 用途
Release_agent RW 删除分组时执行的命令,这个文件只存在于根分组
Notify_on_release RW 设置是否执行 release_agent。为 1 时执行
Tasks RW 属于分组的线程 TID 列表
Cgroup.procs R 属于分组的进程 PID 列表。仅包括多线程进程的线程 leader 的 TID,这点与 tasks 不同
Cgroup.event_control RW 监视状态变化和分组删除事件的配置文件
1.4.CGroup 相关概念解释
任务(task)。在 cgroups 中,任务就是系统的一个进程;
控制族群(control group)。控制族群就是一组按照某种标准划分的进程。Cgroups 中的资源控制都是以控制族群为单位实现。
一个进程可以加入到某个控制族群,也从一个进程组迁移到另一个控制族群。
一个进程组的进程可以使用 cgroups 以控制族群为单位分配的资源,同时受到 cgroups 以控制族群为单位设定的限制;
层级(hierarchy)。控制族群可以组织成 hierarchical 的形式,既一颗控制族群树。
控制族群树上的子节点控制族群是父节点控制族群的孩子,继承父控制族群的特定的属性;
子系统(subsystem)。一个子系统就是一个资源控制器,比如 cpu 子系统就是控制 cpu 时间分配的一个控制器。
子系统必须附加(attach)到一个层级上才能起作用,一个子系统附加到某个层级以后,
这个层级上的所有控制族群都受到这个子系统的控制。
2.libcgroup安装
#安装
redhat系统:
yum install libcgroup
ubuntu系统:
sudo apt-get install cgroup-bin
#cgroup服务的启动和停止,重启:
service cgconfig start|stop|restart
#开机启动
chkconfig cgconfig on
#可以看到cgroup子系统
[root@node3 ~]# cat /etc/system-release Red Hat Enterprise Linux Server release 6.7 (Santiago)
Red Hat默认挂载八个子系统。可以通过配置文件修改挂载的子系统。
[root@dg1 ~]# ls /cgroup/ blkio cpu cpuacct cpuset devices freezer memory net_cls
#查看配置文件,可以看到mount了八个子系统
[root@node3 ~]# cat /etc/cgconfig.conf # # Copyright IBM Corporation. 2007 # # Authors:Balbir Singh <balbir@linux.vnet.ibm.com> # This program is free software; you can redistribute it and/or modify it # under the terms of version 2.1 of the GNU Lesser General Public License # as published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # See man cgconfig.conf for further details. # # By default, mount all controllers to /cgroup/<controller> mount { cpuset= /cgroup/cpuset; cpu= /cgroup/cpu; cpuacct= /cgroup/cpuacct; memory= /cgroup/memory; devices= /cgroup/devices; freezer= /cgroup/freezer; net_cls= /cgroup/net_cls; blkio= /cgroup/blkio; }
删除blkio = /cgroup/blkio;试试,看看啥效果
#删除之前,文件夹里有各种各样的配置文件
[root@node3 ~]# ll /cgroup/blkio/ total 0 -r--r--r-- 1 root root 0 Oct 21 05:15 blkio.io_merged -r--r--r-- 1 root root 0 Oct 21 05:15 blkio.io_queued -r--r--r-- 1 root root 0 Oct 21 05:15 blkio.io_service_bytes -r--r--r-- 1 root root 0 Oct 21 05:15 blkio.io_serviced -r--r--r-- 1 root root 0 Oct 21 05:15 blkio.io_service_time -r--r--r-- 1 root root 0 Oct 21 05:15 blkio.io_wait_time --w------- 1 root root 0 Oct 21 05:15 blkio.reset_stats -r--r--r-- 1 root root 0 Oct 21 05:15 blkio.sectors -r--r--r-- 1 root root 0 Oct 21 05:15 blkio.throttle.io_service_bytes -r--r--r-- 1 root root 0 Oct 21 05:15 blkio.throttle.io_serviced -rw-r--r-- 1 root root 0 Oct 21 05:15 blkio.throttle.read_bps_device -rw-r--r-- 1 root root 0 Oct 21 05:15 blkio.throttle.read_iops_device -rw-r--r-- 1 root root 0 Oct 21 05:15 blkio.throttle.write_bps_device -rw-r--r-- 1 root root 0 Oct 21 05:15 blkio.throttle.write_iops_device -r--r--r-- 1 root root 0 Oct 21 05:15 blkio.time -rw-r--r-- 1 root root 0 Oct 21 05:15 blkio.weight -rw-r--r-- 1 root root 0 Oct 21 05:15 blkio.weight_device --w--w--w- 1 root root 0 Oct 21 05:15 cgroup.event_control -rw-r--r-- 1 root root 0 Oct 21 05:15 cgroup.procs -rw-r--r-- 1 root root 0 Oct 21 05:15 notify_on_release -rw-r--r-- 1 root root 0 Oct 21 05:15 release_agent -rw-r--r-- 1 root root 0 Oct 21 05:15 tasks
#删除以后,重启一下,啥也没有了。
[root@node3 ~]# service cgconfig restart Stopping cgconfig service: [ OK ] Starting cgconfig service: [ OK ] [root@node3 ~]# ll /cgroup/blkio/ total 0
cgroup启动时,会读取配置文件/etc/cgconfig.conf的内容,根据其内容创建和挂载指定的cgroup子系统。
主要由mount和group两个section构成。
(1)mount section的语法格式如下:
mount { <controller> = <path>; ... }
#########################################
# controller:内核子系统的名称
# path:该子系统的挂载点
#########################################
举个例子:
mount { cpuset = /cgroup/red; }
上面定义相当于如下shell指令:
mkdir /cgroup/red mount -t cgroup -o cpuset red /cgroup/red
(2)group section的语法格式如下:
group <name> { [<permissions>] <controller> { <param name> = <param value>; … } … }
################################################################################
## name: 指定cgroup的名称
## permissions:可选项,指定cgroup对应的挂载点文件系统的权限,root用户拥有所有权限。
## controller:子系统的名称
## param name 和 param value:子系统的属性及其属性值
#################################################################################
举个例子:
mount { ## 定义需要创建的cgroup子系统及其挂载点,这里创建cpu与cpuacct(统计)两个cgroup子系统 cpu = /mnt/cgroups/cpu; cpuacct = /mnt/cgroups/cpu; } group daemons/www { ## 定义daemons/www(web服务器进程)组 perm { ## 定义这个组的权限 task { uid = root; gid = webmaster; } admin { uid = root; gid = root; } } cpu { ## 定义cpu子系统的属性及其值,即属于词组的任务的权重为1000 cpu.shares = 1000; } } group daemons/ftp { ## 定义daemons/ftp(ftp进程)组 perm { task { uid = root; gid = ftpmaster; } admin { uid = root; gid = root; } } cpu { ## 定义词组的任务的权重为500 cpu.shares = 500; } }
上面配置文件定义相当于执行了如下shell命令:
mkdir /mnt/cgroups/cpu mount -t cgroup -o cpu,cpuacct cpu /mnt/cgroups/cpu mkdir /mnt/cgroups/cpu/daemons mkdir /mnt/cgroups/cpu/daemons/www chown root:root /mnt/cgroups/cpu/daemons/www/* chown root:webmaster /mnt/cgroups/cpu/daemons/www/tasks echo 1000 > /mnt/cgroups/cpu/daemons/www/cpu.shares mkdir /mnt/cgroups/cpu/daemons/ftp chown root:root /mnt/cgroups/cpu/daemons/ftp/* chown root:ftpmaster /mnt/cgroups/cpu/daemons/ftp/tasks echo 500 > /mnt/cgroups/cpu/daemons/ftp/cpu.shares
3.具体演示
#每个子系统下面的配置文件是用来控制相应的资源使用。
3.1控制进程使用cpu资源
跑脚本消耗cpu
x=0 while [ True ];do x=$x+1 done;
#top查看cpu使用率,可以看到基本上百分百了。
[root@node3 ~]# top Cpu(s): 24.8%us, 0.1%sy, 0.0%ni, 75.1%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 29676 root 20 0 106m 2240 1532 R 100.0 0.0 0:23.67 bash
#下面用cgroup控制这个进程使用的cpu资源
mkdir -p /cgroup/cpu/foo/ #新建一个控制组foo echo 50000 > /cgroup/cpu/foo/cpu.cfs_quota_us
#将cpu.cfs_quota_us设为50000,相对于cpu.cfs_period_us的100000是50%
echo 29676 > /cgroup/cpu/foo/tasks
--29676是进程pid,添加到控制的任务列表中
#再次查看,cpu使用率为百分之五十了。
[root@node3 ~]# top Cpu(s): 12.6%us, 0.0%sy, 0.0%ni, 87.4%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 29676 root 20 0 106m 3076 1532 R 49.9 0.0 4:59.09 bash
#cpu控制组foo下面还有其他的控制,还可以做更多其他的关于cpu的控制
[root@node3 ~]# ls /cgroup/cpu/foo/ cgroup.event_control cgroup.procs cpu.cfs_period_us cpu.cfs_quota_us cpu.rt_period_us cpu.rt_runtime_us cpu.shares cpu.stat notify_on_release tasks
3.2控制进程使用内存资源
耗内存的脚本,内存不断增长
x="a" while [ True ];do x=$x$x done;
[root@node3 ~]# top top - 05:30:37 up 2 days, 2:00, 3 users, load average: 0.40, 0.39, 0.23 Tasks: 189 total, 2 running, 187 sleeping, 0 stopped, 0 zombie Cpu(s): 12.8%us, 0.2%sy, 0.0%ni, 86.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 7940312k total, 927724k used, 7012588k free, 89528k buffers Swap: 16383996k total, 0k used, 16383996k free, 146444k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 29676 root 20 0 617m 225m 1532 R 39.9 4.4 6:02.21 bash 29676 root 20 0 617m 338m 1532 R 49.9 4.4 6:12.61 bash
#用cgroups控制这个进程的内存资源
mkdir -p /cgroup/memory/foo echo 1048576 > /cgroup/memory/foo/memory.limit_in_bytes #分配1MB的内存给这个控制组 echo 29676 > /cgroup/memory/foo/tasks --29676是进程pid
等一会,脚本就会报错,无法分配脚本所需要的内存,然后被kill掉
[root@node3 ~]# while [ True ];do > > x=$x$x > > done; -bash: xrealloc: cannot allocate 18446744071562068096 bytes (323584 bytes allocated)
#被干掉了。
[root@node3 ~]# ps -ef|grep 29676 root 9391 3252 0 05:38 pts/1 00:00:00 grep 29676
因为这是强硬的限制内存,当进程试图占用的内存超过了cgroups的限制,会触发out of memory,导致进程被kill掉。
实际情况中对进程的内存使用会有一个预估,然后会给这个进程的限制超配50%比如,除非发生内存泄露等异常情况,才会因为cgroups的限制被kill掉。也可以通过配置关掉cgroups oom kill进程,通过memory.oom_control来实现(oom_kill_disable 1),但是尽管进程不会被直接杀死,但进程也进入了休眠状态,无法继续执行,仍让无法服务。
3.21关于内存的控制,还有以下配置文件
是关于虚拟内存的控制,以及权值比重式的内存控制等。
3.3控制进程io资源
#执行耗io的脚本
dd if=/dev/sda of=/dev/null &
通过iotop看io占用情况,磁盘速度到了169M/s
10271 be/4 root 169.71 M/s 0.00 B/s 0.00 % 0.00 % dd if=/dev/sda of=/dev/null
下面用cgroups控制这个进程的io资源
mkdir -p /cgroup/blkio/foo echo '8:0 1048576' > /cgroup/blkio/foo/blkio.throttle.read_bps_device
#8:0对应主设备号和副设备号,可以通过ls -l /dev/sda查看
echo 30252 > /cgroup/blkio/foo/tasks
再通过iotop看,确实将读速度降到了1M/s
10271 be/4 root 1014.36 K/s 0.00 B/s 0.00 % 0.00 % dd if=/dev/sda of=/dev/null
对于io还有很多其他可以控制层面和方式,如下
[root@node3 ~]# ls /cgroup/blkio/foo/ blkio.io_merged blkio.io_serviced blkio.reset_stats blkio.throttle.io_serviced blkio.throttle.write_bps_device blkio.weight cgroup.procs blkio.io_queued blkio.io_service_time blkio.sectors blkio.throttle.read_bps_device blkio.throttle.write_iops_device blkio.weight_device notify_on_release blkio.io_service_bytes blkio.io_wait_time blkio.throttle.io_service_bytes blkio.throttle.read_iops_device blkio.time cgroup.event_control tasks
注:进程重启之后(pid会重新分配),需要重新加入到相应的tasks配置文件里才能生效。
cgroup在控制进程使用的资源还是很方便的,也很有效。
版权声明:本文为博主原创文章,未经博主允许不得转载。
cgroup cpu io memory