Linux cgroup介绍
为什么要有cgroupLinux系统中经常有个需求就是希望能限制某个或者某些进程的分配资源。也就是能完成一组容器的概念,在这个容器中,有分配好的特定比例的cpu时间,IO时间,可用内存大小等。于是就出现了cgroup的概念,cgroup就是controller group,可用来限制、记录、隔离进程组的物理资源,最初由google的工程师提出,后来被整合进Linux内核中。cgroup的功能cgr
本文参考网上一些资料,结合实际应用,简要介绍一下cgroup。
为什么要有cgroup
Linux系统中经常有个需求就是希望能限制某个或者某些进程的分配资源。也就是能完成一组容器的概念,在这个容器中,有分配好的特定比例的cpu时间,IO时间,可用内存大小等。于是就出现了cgroup的概念,cgroup就是controller group,可用来限制、记录、隔离进程组的物理资源,最初由google的工程师提出,后来被整合进Linux内核中。
cgroup的功能
cgroup是将任意进程进行分组化管理的Linux内核功能。cgroup本身提供将进程进行分组化管理的功能和接口的基础结构。实现 cgroups 的主要目的是为不同用户层面的资源管理提供一个统一化的接口。从单个任务的资源控制到操作系统层面的虚拟化,cgroups 提供了五大功能:
- 资源限制(Resource limiting ):比如memory子系统可以为进程组设定一个memory使用上限,进程组使用的内存达到限额再申请内存,就会出发OOM(out of memory)
- 优先级控制(Prioritization):比如可以使用cpu子系统为某个进程组分配cpu share
- 资源统计(Accounting ):比如使用cpuacct子系统记录某个进程组使用的cpu时间
- 进程组隔离(Isolation):比如使用ns子系统可以使不同的进程组使用不同的namespace,以达到隔离的目的,不同的进程组有各自的进程、网络、文件系统挂载空间
- 进程组控制(Control):比如使用freezer子系统可以将进程组挂起和恢复
cgroup相关概念
Task(任务): task就是表示系统的一个进程。
Cgroup(控制组): 资源控制的单位,表示一整个任务组,每个任务组被划分相应的资源,包含了一个或者多个子系统。一个任务既可以加入到这个 cgroup 中,也可以迁移到另外一个 cgroup 中去。
Subsystem(子系统): 一个资源调度器(Resource Controller,控制着CPU,内存,访问,输入输出等资源和权限。
Hierarchy(层级树):一种操作系统的组织结构,可以理解为是一个 cgroup 树,将 cgroup 串成树状结构,通过虚拟端口暴露给用户。
subsystem
用于控制cgroup中的进程行为的内核组件,可以在/proc/cgroups查看所有支持的subsystem,subsystem也别称为resource controller;第二列为croup id;第三列为cgroup中进程数目。
#cat /proc/cgroups
subsys_name hierarchy num_cgroups enabled
cpuset 8 6 1
cpu 7 105 1
cpuacct 7 105 1
blkio 5 105 1
memory 3 327 1
devices 6 106 1
freezer 4 6 1
net_cls 2 6 1
perf_event 11 6 1
net_prio 2 6 1
hugetlb 9 6 1
pids 12 106 1
rdma 10 1 1
也可以通过lssubsys来查看。
hierarchy
由cgroup组成的层级树,每个hierarchy都对应一个cgroup虚拟文件系统,每个hierarchy都有系统上的所有task,此外低level的hierarchy不能超过高level设定的资源上限。每次在系统中创建新层级(hierarchy)时,该系统中的所有任务都是那个层级的默认cgroup(我们称之为root cgroup,此cgroup在创建层级时自动创建,后面在该层级中创建的cgroup都是此cgroup的后代)的初始成员;
cgroup文件系统接口
cgroup以文件的方式提供应用接口,我们可以通过 mount 命令来查看 cgroups 默认的挂载点。系统默认会挂载cgroup,路径为/sys/fs/cgroup,查看当前系统挂载的cgroup,可以看到在默认路径下挂载了所有的子系统。后续可以直接使用下述hierarchy作为父hierarchy。进程的cgroup可以在/proc/$pid/cgroup文件中查看。
#mount|grep cgroup
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,seclabel,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,perf_event)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,hugetlb)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,rdma)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpu,cpuacct)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,net_cls,net_prio)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuset)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,blkio)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,freezer)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,memory)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,pids)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,devices)
第一行的 tmpfs 说明 /sys/fs/cgroup 目录下的文件都是存在于内存中的临时文件。
第二行的挂载点 /sys/fs/cgroup/systemd 用于 systemd 系统对 cgroups 的支持。
其余的挂载点则是内核支持的各个子系统的根级层级结构。
需要注意的是,在使用 systemd 系统的操作系统中,/sys/fs/cgroup 目录都是由 systemd 在系统启动的过程中挂载的,并且挂载为只读的类型。换句话说,系统是不建议我们在 /sys/fs/cgroup 目录下创建新的目录并挂载其它子系统的。这一点与之前的操作系统不太一样。
看一下 /sys/fs/cgroup 目录及其子目录下都是些什么:
/sys/fs/cgroup 目录下是各个子系统的根目录。我们以 memory 子系统为例,看看 memory 目录下都有什么:
这些文件就是 cgroups 的 memory 子系统中的根级设置。比如 memory.limit_in_bytes 中的数字用来限制进程的最大可用内存,memory.swappiness 中保存着使用 swap 的权重等等。
既然 cgroups 是以这些文件作为 API 的,那么我就可以通过创建或者是修改这些文件的内容来应用 cgroups。具体该怎么做呢?比如我们怎么才能限制某个进程可以使用的资源呢?接下来我们就通过简单的 demo 来演示如何使用 cgroups 限制进程可以使用的资源。
查看进程所属的 cgroup
可以通过 /proc/[pid]/cgroup 来查看指定进程属于哪些 cgroup:
每一行包含用冒号隔开的三列,他们的含义分别是:
- cgroup 树的 ID, 和 /proc/cgroups 文件中的 ID 一一对应。
- 和 cgroup 树绑定的所有 subsystem,多个 subsystem 之间用逗号隔开。这里 name=systemd 表示没有和任何 subsystem 绑定,只是给他起了个名字叫 systemd。
- 进程在 cgroup 树中的路径,即进程所属的 cgroup,这个路径是相对于挂载点的相对路径。
可以使用cgroup-bin工具包中的cgexec来实现限制进程可以使用的资源。
cgroup相关规则
- 一个hierarchy可以有一个或多个subsystem,这个从/sys/fs/cgroup中可以看出来cpu和cpuacct可以同属于一个hierarchy,而memory则仅属于一个hierarchy;
- 一个subsystem不能挂载到一个已经挂载了不同subsystem的hierarchy上;
- 一个task不能同时存在于同一个hierarchy下的两个cgoup中,但可以存在于不同类型的hierarchy中;如下例中,在hierarchy memory中创建2个cgroup mem1和mem2,可以看到将当前bash进程写入到mem2/tasks之后,mem1/tasks中的内容就会被清空。
注:删除cgroup之前需要退出所有attach到该cgroup的进程,如下面的进程为bash,exit退出即可。
[root@ memory]# echo $$
9439
[root@ memory]# echo $$ > mem1/tasks
[root@ memory]# cat mem1/tasks
9439
9680
[root@ memory]# echo $$ > mem2/tasks
[root@ memory]# cat mem2/tasks
9439
9693
[root@ memory]# cat mem1/tasks
[root@ memory]#
相同类型subsystem的hierarchy为同一个hierarchy,如下例中创建一个包含memory subsystem的hierarchy,它与/sys/fs/cgroup下面的memory是一致的,在cgrp1中创建一个名为mem1的cgroup。在/sys/fs/cgroup/memory下可以看到新创建的mem1
[root@ cgroup]# mount -t cgroup -o memory mem cgrp1/
[root@ cgroup]# cd cgrp1/
[root@ cgrp1]# mkdir mem1
?子进程会继承父进程的hierarchy,但可以将子进程调整到其他cgroup。下例中可以看到子进程同样受到父进程hierarchy的限制
[root@ mem1]# echo $$
10928
[root@ mem1]# echo $$>tasks
[root@ mem1]# cat /proc/10928/cgroup
11:devices:/user.slice
10:perf_event:/
9:pids:/user.slice
8:freezer:/
7:cpuacct,cpu:/
6:hugetlb:/
5:memory:/mem1
4:cpuset:/
3:net_prio,net_cls:/
2:blkio:/
1:name=systemd:/user.slice/user-1000.slice/session-1.scope
[root@ mem1]# bash #创建一个子进程
[root@ mem1]# echo $$
11402
[root@ mem1]# cat /proc/11402/cgroup
11:devices:/user.slice
10:perf_event:/
9:pids:/user.slice
8:freezer:/
7:cpuacct,cpu:/
6:hugetlb:/
5:memory:/mem1
4:cpuset:/
3:net_prio,net_cls:/
2:blkio:/
1:name=systemd:/user.slice/user-1000.slice/session-1.scope
从上面可以看到,subsystem相同的hierarchy是被重复使用的;当创建一个新的hierarchy时,如果使用的subsystem被其他hierarchy使用,则会返回EBUSY错误。如/sys/fs/cgroup中已经在cpuset和memory中单独使用了名为cpuset和memory的subsystem,则重新创建一个包含了它们的hierarchy会返回错误。
[root@ cgroup]# mount -t cgroup -o cpuset,memory mem1 cgrp1/
mount: mem1 is already mounted or /cgroup/cgrp1 busy
可以创建没有subsystem的hierarchy,默认包含如下文件:
- tasks:包含了attach到该cgoup的pid。如上述例子中所示,将进程pid写入到该文件会将进程转移到该cgroup。(cgroupv2中移除了该文件,使用cgroup.procs)
- cgroup.procs:包含了线程的group id。将一个线程的group id写入该文件,会将该group下的所有线程转移到该cgroup。(cgroupv2中该文件的定义与cgroupv1中tasks文件的意义类似)
- notify_on_release:flag文件,用来判断是否执行release_agent
- release_agent:如果cgroup中使能notify_on_release,cgroup中的最后一个进程被移除,最后一个子cgroup也被删除时,cgroup会主动通知kernel。接收到消息的kernel会执行release_agent文件中指定的程序
[root@ cgroup]# mount -t cgroup -onone,name=cgrp1 mycgroup cgrp1/
[root@ cgroup]# cd cgrp1/
[root@ cgrp1]# ll
total 0
-rw-r--r--. 1 root root 0 Jan 2 23:54 cgroup.clone_children
--w--w--w-. 1 root root 0 Jan 2 23:54 cgroup.event_control
-rw-r--r--. 1 root root 0 Jan 2 23:54 cgroup.procs
-r--r--r--. 1 root root 0 Jan 2 23:54 cgroup.sane_behavior
-rw-r--r--. 1 root root 0 Jan 2 23:54 notify_on_release
-rw-r--r--. 1 root root 0 Jan 2 23:54 release_agent
-rw-r--r--. 1 root root 0 Jan 2 23:54 tasks
创建hierarchy 层级并挂载子系统
1.挂载一颗和所有subsystem关联的cgroup树到/sys/fs/cgroup
mount -t cgroup xxx /sys/fs/cgroup
2.挂载一颗和cpuset subsystem关联的cgroup树到/sys/fs/cgroup/cpuset
mkdir /sys/fs/cgroup/cpuset
mount -t cgroup -o cpuset xxx /sys/fs/cgroup/cpuset
3.挂载一颗与cpu和cpuacct subsystem关联的cgroup树到/sys/fs/cgroup/cpu,cpuacct
mkdir /sys/fs/cgroup/cpu,cpuacct
mount -t cgroup -o cpu,cpuacct xxx /sys/fs/cgroup/cpu,cpuacct
4.挂载一棵cgroup树,但不关联任何subsystem
mkdir /sys/fs/cgroup/systemd
mount -t cgroup -o none,name=systemd xxx /sys/fs/cgroup/systemd
cgconfig.conf
在使用yum install libcgroup安装了cgroups模块之后,在 /etc/cgconfig.conf 文件中会自动生成 cgroups 子系统的挂载点:
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;
}
上面的每一条配置都等价于展开的 mount 命令,例如mount -t cgroup -o cpuset cpuset /cgroup/cpuset。这样系统启动之后会自动把这些子系统挂载到相应的挂载点上。
参考文献
https://www.cnblogs.com/charlieroro/p/10180827.html
http://www.360doc.com/content/15/0316/13/21786663_455538198.shtml
https://www.jb51.net/article/146162.htm
https://blog.csdn.net/Fitz_q/article/details/108561537
更多推荐
所有评论(0)