使用 Cgroup

Cgconfig服务

要使用 cgroup,首先要确认系统中已安装 libcgroup软件包。(RedHat系)

1
# yum install libcgroup

cgconfig.conf文件

cgconfig.conf 文件包含两个主要类型的条目 ——— mount 和 group。挂载条目生成并挂载层级并将其作为虚拟文件系统,同时将子系统附加到那些层级中

1
2
3
4
5
6
7
8
9
10
11
12
# cat /etc/cgconfig.conf
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;
}

挂载子系统的备选方法是使用 shell 命令:

1
2
# mkdir /cgroup/cpu
# mount -t cgroup -o cpu cpu /cgroup/cpu

组群条目使用一下语法设定子系统参数:

1
2
3
4
5
6
7
8
group <name>
[<permissions>]
<controller> {
<param name> = <param value>;
...
}
...
}

e.g. 为 sql 守护进程创建 cgroup,可为 sqladmin 组群中的用户在 cgroup 中添加任务,并让 root 用户修改子系统参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
group daemons/sql {
perm {
task {
uid = root;
gid = sqladmin;
} admin {
uid = root;
gid =root;
}
} cpu {
cpu.shares = 100;
}
}

以上配置对等的 shell 命令为:

1
2
3
4
# mkdir -p /cgroup/cpu/daemons/sql
# chown root:root /cgroup/cpu/daemons/sql/*
# chown root:sqladmin /cgfroup/cpu/daemons/sql/tasks
# echo 100 > /cgroup/cpu/daemons/sql/cpu.shares

在现有层级中附加或删除子系统

要在现有层级中添加子系统,从现有层级中取消层级或者将其移动到不同的层级中,请作为 root 编辑 /etc/cgconfig.conf 文件的 mount 部分,当 cgconfig 下次重启时,它会根据您指定的层级识别那些子系统。

使用 mount 命令挂载时加上 remount 参数,并列出新的子系统列表即可。

1
# mount -t cgroup -o remount,cpu,cpuset,... cpu_and_mem

卸载层级

直接使用 umount 即可卸载层级。不过需要注意的是:如果该层级目前为空(即它只包含 root cgroup),则在卸载它时会取消激活该层级。如果该层级包含任意其他 cgroup,该层级在内核中仍保持活跃,即使不再挂载它也是如此。

要删除层级,请确定您在卸载该层级前删除所有子 cgroup,或者使用 cgclear命令,它可在层级非空时也可取消激活层级。

cgroup操作

cgcreate

语法: cgcreate -t uid:gid -a uid:gid -g subsystems:path

  • -t(可选):指定用户(使用用户 ID,uid)和组群(使用组群 ID,gid)以便让这个 cgroup 拥有 tasks 伪文件。这个用户可在该 cgroup 中添加任务。
  • -a(可选):指定用户(使用用户ID,uid)和组群(使用组群ID,gid)以便这个 cgroup 拥有 tasks 外的所有伪文件。这个用户可修改这个 cgroup 中的任务对系统资源的访问。
  • -g:指定在其中创建 cgroup 的层级,格式为与那些层级关联的用逗号分开的 subsystems 列表。如果这个列表中的子系统在不同的层级中,则要在每个层级中都创建该组群。层级列表后是一个冒号,然后是与该层级有关的子组群 path。不要在该 path 中包含层级挂载点。

e.g. 在 cpu_and_mem 层级中一同挂载 cpu 和 memory 子系统的系统,并将 net_cls 控制器挂载到名为 net 的另一个层级中。

1
# cgcreate -g cpu,net_cls:/test-subgroup

备用方法

1
# mkdir /cgroup/hierarchy/name/child_name

cgdelete

使用 cgdelete 删除 cgroup,其语法与 cgcreate 类似。

cgdelete subsystems:path

-r 递归删除所有子组群

e.g.

1
# cgdelete cpu,net_cls:/test-subgroup

cgset

在可修改相关的 cgroup 的用户账户中 运行 cgset 命令设置子系统参数。

cgset -r parameter=value path_to_cgroup

parameter: 是要设定的参数,该参数与给定 cgroup 的目录中的文件对应。

value: 是为参数设定的值

path_to_cgroup: 是到相对该层级 root 的 cgroup 路径。

–copy-from path_to_source_cgroup path_to_target_cgroup: 将一个 cgroup 中的参数复制到另一个现有 cgroup 中。

备用方法

要直接在 cgroup 中设置参数,可使用 echo 命令将值插入相关子系统伪文件中。

1
# echo 0-1 > /cgroup/cpuset/group1/cpuset.cpus

cgclassify

cgclassify -g subsystems:path_to_cgroup pidlist

subsystems: 是用逗号分开的子系统列表,或者 * 启动与所有可用子系统关联的层级中的进程。

path_to_cgroup: 是到其层级中的 cgroup 的路径。

pidlist: 是用空格分开的进程识别符(PID)列表。

e.g. 将 PID 为 1701 和 1138 的进程移动到 cgorup 中的 group1/:# cgclassify -g cpu,memory:group1 1701 1138

备用方法

# echo 1701 > /cgroup/lab1/group/tasks

cgred

Cgred 是一个守护进程,它可根据在 /etc/cgrules.conf 中设定的参数将任务移动到 cgroup 中,条目可以使用以下两种格式之一:

  • user hierarchies control_group
  • user:command hierarchies control_group

e.g.

maria devices /usergroup/staff

这个条目指定任何属于名为 maria 用户的进程根据在 /usergroup/staff cgroup 中指定的参数访问设备子系统。

maria:ftp devices /usergroup/staff/ftp

该条目现在指定核实名为 maria 的用户使用 ftp 命令 ,自动将该进程移动到包含 devices 子系统的层级中的 /usergroup/staff/ftp cgroup 中。

/etc/cgrules.conf

@:当在 user 使用前缀时,代表是一个组群而不是一个单独用户。例如: @admins 是 admins 组群中的所有用户。

*: 代表“所有”。

%: 代表与以上行中项目相同的项目。

cgexec

cgexec -g subsystems:path_to_cgroup command arguments

subsystems:是用逗号分开的子系统列表或者 * 启动与所有可用子系统关联的层级的进程。

path_to_cgroup:是到与该层级相关的 cgroup 的路径。

commond:是要运行的命令。

arguments:是该命令所有参数。

–sticky:将所有子进程放在同一 cgroup 中。

备用方法

# echo $$ > /cgroup/lab1/group1/tasks

请注意:**退出用户后,现有 shell 中仍在 group1 cgroup 中。因此更好的方法应为:

# sh -c "echo \$$ > /cgroup/lab1/group1/tasks && USER

在控制组群中启动服务

您可在某个 cgroup 中启动某些服务。在 cgroup 中启动的服务必须:

  • 使用 /etc/sysconfig/servicename 文件
  • 使用 /etc/init.d/functions 的 daemon()功能启动该服务

要在某个 cgroup 中启动合格服务,请在 /etc/sysconfig 中编辑其文件,使该文件包含如下条目:CGROUP_DAEMON=”subsystem:control_group”

e.g. CGROUP_DAEMON="cpuset:daemons/sql"

获得有关控制组群的信息

查找某个进程

$ ps -O cgroup

$ cat /proc/PID/cgroup

查找子系统

$ cat /proc/cgroups

$ lssubsys -m subsystems

查找层级

$ tree /cgroup/

查找控制组群

$ lscgroup

$ lscgroup cpuset:adminusers

显示控制组群的参数

$ cgget -r parameter list_of_cgroups

其中 parameter 是包含子系统值的伪文件,list_of_cgroups 是用空格分开的 cgorup 列表。

cgclear

cgclear 命令将破坏所有层级中的所有 cgroup。如果没有在配置文件中保存这些层级,将无法再次构建它们。