Cgroup使用进阶

About

在我的前面两篇文章中,分别介绍了cgroup的一些基本概念,和如何去管理层次结构和control group还有如何附加子系统。但是到目前为止仍旧没有触及cgroup中最核心的东西也就是资源限制。前面的文章中仅仅说的是如何把子系统附加到某个层次上。至于如何设置子系统来限制资源,如何针对某些进程来限制都还没有涉及。那么本篇博文谈的就是这两点。

Setting Parameters

当我们将一个子系统附加到一个层次中,我们必须去调节对应子系统的参数才能够达到资源限制的目的。给某个子系统设置参数需要用到cgset命令,但是需要注意一个问题就是,使用cgset的权限。不是哪个用户都可以使用cgset对某一个control group下的子系统设置参数。在使用cgcreate命
令创建control group的时候有一个-t和-a选项,这两个可以指定用户可以修改control group中的子系统参数。具体细节可以参考我的上篇博文

先来看下cgset的语法

cgset -r parameter=value path_to_cgroup
path_to_cgroup 是一个相对于root cgroup的一个路径
例如: /cgroup/cpu_and_mem 这个cgroup,并且已经挂载,要想调节这个
cgroup的参数,那么path_to_cgroup就是/ 也可以省略,表示就是cpu_and_mem这个root cgroup自身。
如果是要设置参数的control group是 /cgroup/cpu_and_mem/subgroup
那么path_to_group就是/subgroup

下面是使用cgset设置参数的一个例子:

此时系统上已经挂载了一个/cgroup/cpu_and_mem的root group了
下面这是用来调节subgroup这个control group的最大内存使用量
cgset -r memory.limit_in_bytes=10240000 /subgroup

我们也可以拷贝一个control group的参数到另外一个control group中,操作方式如下:

将subgroup中的子系统参数,拷贝到subgroup2中。
cgset --copy-from /subgroup /subgroup2 

关于每个子系统中的参数的含义我将会在下篇博文中根据实际例子来解释其作用。

Displaying Parameters of Control Groups

cgget命令可以用来查看某个control group中的子系统的参数,也可以使用cat通过文件的方式来查看。cgget显示参数的用法如下:

syntax:
cgget -r parameter list_of_cgroups

example:
cgget -r cpuset.cpus -r memory.limit_in_bytes /subgroup /subgroup2
结果如下
/subgroup:
cpuset.cpus: 
memory.limit_in_bytes: 1024000

/subgroup2:
cpuset.cpus: 
memory.limit_in_bytes: 9223372036854775807

Moving a Process to a Control Group

调节完子系统的参数后基本上就可以达到资源限制的作用了,但是对谁做限制呢?如果我们调节的是root group中的子系统参数,那么将会对整个系统的所有进程做资源限制。这或许不是我们想要的效果,你可以看下每个control group目录下都有一个tasks文件,这个文件中放的是要限制的进程pid,如果是root group那么这个文件中放的是系统上所有进程的pid,如果
是一个刚创建的control group则这个文件是空的。原理搞清楚了,实现起来就简单了,只要将要限制的进程pid,添加到这个文件中就可以实现对这个进程的资源限制了,cgroup同时也提供了一个命令来帮助我们完成这个操作,这个命令叫做cgclassify。语法如下

cgclassify -g subsystems:path_to_cgroup pidlist

下面是一个使用cgclassify来添加进程到指定contrl group中下面是把1251进程添加到subgroup这个control group中
cgclassify -g cpuset:/subgroup 1251
也可以
echo 1251 > /cgroup/cpu_and_mem/subgroup

The cgred Service

考虑一个场景,如果我要对一个vsftpd进程做限制,那么如果使用上面提到的方法来对vsftpd进程做限制,那么存在一个问题就是,每次系统重启都需要重新设置,因为进程的PID发生了变化。好在红帽给我们提供了一个cgred的服务,是随着libcgroup的安装而安装的。通过cgred可以自动帮我们去设置。我们只需要在配置文件中书写规则即可。

配置文件为/etc/cgrules.conf,其文件格式有以下两种:
两种syntax
user subsystems control_group
user:command subsystems control_group
下面是一些设置案例:

maria devices /usergroup
表示任何属于maria这个用户的进程,访问设备子系统的时候都受/usergroup
这个cgroup关于devices子系统的影响。
maria:ftp devices /usergroup/staff/ftp
表示当maria用户使用ftp命令产生的进程会自动移动到包含device子系统的/usergroup/staff/ftp control group中。

关于cgred的配置文件语法还有更多的话题可以谈,再次就介绍到这里为止了。

Starting a Process in a Control Group

上面的谈到的是如何把一个进程移动到某个control group的子系统下,那么如何在进程启动的时候就将其添加到control group中的呢,cgroup提供了一个cgexec命令用来达到这个目的,先来看下这个命令的语法规则:

cgexec -g subsystems:path_to_cgroup command arguments
下面是一个例子,在subgroup这个control group中,执行wget命令:
cgexec -g memory:/subgroup wget http://www.redhat.com

当然除了使用cgexec外,还可以有另外一个方法来在某个control group中执行指定进程。

把当前进程添加到control group中,那么很自然其子进程也是属于这个control group中的
[root@localhost cpu_and_mem]# echo $$ > /cgroup/cpu_and_mem/subgroup/tasks
[root@localhost cpu_and_mem]# wget http://www.redhat.com
但是这种方法存在一个问题就是当wget退出后,当前进程仍然还是属于cgroup中.下面是一种更好的办法:
sh -c "echo \$$ > /cgroup/cpu_and_mem/subgroup/tasks && wget http://www.redhat.com"

Obtaining Information About Control Groups

Finding a Process

寻找一个进程是属于哪个cgroup的,可以运行下面的命令
ps -O cgroup或者是你想指定指定PID进程是属于哪个cgroup的可以运行下面的命令cat /proc/PID/cgroup

Finding a Subsystem

寻找某个子系统的挂载点(也就是所在层次)可以运行下面的命令:
lssubsys -m subsystems

Finding Hierarchies

寻找当前系统上存在的层次可以运行下面的命令:
tree /cgroup

Finding Control Groups

寻找当前系统上存在的control groups(包括root group),可以运行下面的命令:

[root@localhost ~]# lscgroup 
cpuset,memory:/
©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值