与Linux namespace对比来看,Linux namespace用来限制进程的运行范围或者运行环境的可见性,比如:uts限制进程读取到的hostname、mnt限制进程读取到的文件系统视图、net限制进程可以访问的网络范围等;而CGroups则是用来限制进程的资源配给,比如:磁盘IO读写速率、内存使用限制、CPU时间限制等,从而避免争抢和挤压。
既然CGroups是用来管理进程的资源配给的,那么CGroups的概念最少应该涉及到进程和资源两部分:
除了进程和资源以外,还需要将两者结合起来,并且提供有效的管理手段:
/sys/fs/cgroup/memory
目录或者/sys/fs/cgroup/cpu,cpuacct
目录都可以理解为一个hierarchy。
/sys/fs/cgroup/memory
下的cgroup***只能***使用memory一种,而/sys/fs/cgroup/cpu,cpuacct
***只能***使用cpu和cpuacct的组合。可以理解为:同一个hierarchy上的所有进程都以相同的手段限制资源,差别在于cgroup与cgroup之间的资源阈值。核心概念中的前三个都比较简单,稍微难以理解的可能就是hierarchy了。简单来说,hierarchy可以理解为subsystem的分组,组团对进程进行限制,至于限制量多少,cgroup说了算~
上图中有两颗hierarchy树:hierarchy-a和hierarchy-b,两颗树上的task(进程)完全相同,两颗树上的subsystem不能存在交集,两颗树上的cgroup分组方式相互独立,互不影响。hierarchy-a上的cgroup必须同时使用cpu和cpuacct两种subsystem,此时cpu和cpuacct是一个整体。而hierarchy-b上只能使用memory一种subsystem。
进程fork出新的子进程时,子进程与父进程处于同一cgroup,受到相同的subsystem限制。之后子进程可以被添加到其他cgroup,父进程不受影响,父子进程相互独立。
### 查看当前系统中的hierarchy ###
[root@localhost ~]# mount --type cgroup
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/memory type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,memory)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,blkio)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,hugetlb)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,freezer)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,net_prio,net_cls)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,devices)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuset)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuacct,cpu)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,perf_event)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,pids)
### 尝试创建另一个hierarchy,失败,因为:从上面的结果来看,系统默认的hierarchy已经包含了所有的subsystem ###
[root@localhost ~]# mount --type cgroup --options cpu cpu cgroups/
mount: cpu is already mounted or /root/cgroups busy
### 尝试创建一个不与任何subsystem关联的hierarchy ###
[root@localhost ~]# mount --type cgroup --options none,name=cgroup-1 cgroup-1 cgroups/cgroup-1/
### 创建cgroup-1之后,系统会自动创建必要的配置文件 ###
[root@localhost ~]# ll cgroups/cgroup-1/
total 0
-rw-r--r--. 1 root root 0 Feb 26 14:57 cgroup.clone_children
--w--w--w-. 1 root root 0 Feb 26 14:57 cgroup.event_control
-rw-r--r--. 1 root root 0 Feb 26 14:57 cgroup.procs
-r--r--r--. 1 root root 0 Feb 26 14:57 cgroup.sane_behavior
-rw-r--r--. 1 root root 0 Feb 26 14:57 notify_on_release
-rw-r--r--. 1 root root 0 Feb 26 14:57 release_agent
-rw-r--r--. 1 root root 0 Feb 26 14:57 tasks
CGroup系统没有提供任何系统调用接口,而是通过vfs实现类似文件系统的操作方式来进行管理,比如上述这些自动生成的文件。因为没有关联任何subsystem,这些文件都是一些通用文件,文件的基本含义如下:
1
时表示继承上级cgroup的cpuset配置。1
,当cgroup退出时系统将调用release_agent文件中的命令。除了上述通用文件之外,每个subsystem都有自己独特的配置文件和配置格式,比如:
### 查看系统memory subsystem对应的配置文件 ###
[root@localhost ~]# ll /sys/fs/cgroup/memory/
total 0
-rw-r--r--. 1 root root 0 Feb 27 13:27 cgroup.clone_children
--w--w--w-. 1 root root 0 Feb 27 13:27 cgroup.event_control
-rw-r--r--. 1 root root 0 Feb 27 13:27 cgroup.procs
-r--r--r--. 1 root root 0 Feb 27 13:27 cgroup.sane_behavior
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.failcnt
--w-------. 1 root root 0 Feb 27 13:27 memory.force_empty
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.kmem.failcnt
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.kmem.limit_in_bytes
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.kmem.max_usage_in_bytes
-r--r--r--. 1 root root 0 Feb 27 13:27 memory.kmem.slabinfo
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.kmem.tcp.failcnt
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.kmem.tcp.limit_in_bytes
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.kmem.tcp.max_usage_in_bytes
-r--r--r--. 1 root root 0 Feb 27 13:27 memory.kmem.tcp.usage_in_bytes
-r--r--r--. 1 root root 0 Feb 27 13:27 memory.kmem.usage_in_bytes
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.limit_in_bytes
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.max_usage_in_bytes
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.memsw.failcnt
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.memsw.limit_in_bytes
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.memsw.max_usage_in_bytes
-r--r--r--. 1 root root 0 Feb 27 13:27 memory.memsw.usage_in_bytes
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.move_charge_at_immigrate
-r--r--r--. 1 root root 0 Feb 27 13:27 memory.numa_stat
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.oom_control
----------. 1 root root 0 Feb 27 13:27 memory.pressure_level
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.soft_limit_in_bytes
-r--r--r--. 1 root root 0 Feb 27 13:27 memory.stat
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.swappiness
-r--r--r--. 1 root root 0 Feb 27 13:27 memory.usage_in_bytes
-rw-r--r--. 1 root root 0 Feb 27 13:27 memory.use_hierarchy
-rw-r--r--. 1 root root 0 Feb 27 13:27 notify_on_release
-rw-r--r--. 1 root root 0 Feb 27 13:27 release_agent
-rw-r--r--. 1 root root 0 Feb 27 13:27 tasks
### 接触挂载 ###
[root@localhost ~]# umount cgroups/cgroup-1/
### 自动生成的配置文件在umount之后自动删除 ###
[root@localhost ~]# ll cgroups/cgroup-1/
total 0
hierarchy创建之后,默认会与一个顶层cgroup,也就是该hierarchy的root cgroup。在root cgroup下创建新目录,也就是创建了下级cgroup,项cgroup中加入task,配置对应的subsystem参数,也就限制了task中的进行访问与subsystem对应的系统资源的访问。
### 在/sys/fs/cgroup/cpu创建cgroup-c ###
[root@localhost ~]# mkdir /sys/fs/cgroup/cpu/cgroup-c
### 系统自动生成对应的配置文件,说明cgroup创建成功 ###
[root@localhost ~]# ll /sys/fs/cgroup/cpu/cgroup-c
total 0
-rw-r--r--. 1 root root 0 Feb 27 15:14 cgroup.clone_children
--w--w--w-. 1 root root 0 Feb 27 15:14 cgroup.event_control
-rw-r--r--. 1 root root 0 Feb 27 15:14 cgroup.procs
-r--r--r--. 1 root root 0 Feb 27 15:14 cpuacct.stat
-rw-r--r--. 1 root root 0 Feb 27 15:14 cpuacct.usage
-r--r--r--. 1 root root 0 Feb 27 15:14 cpuacct.usage_percpu
-rw-r--r--. 1 root root 0 Feb 27 15:14 cpu.cfs_period_us
-rw-r--r--. 1 root root 0 Feb 27 15:14 cpu.cfs_quota_us
-rw-r--r--. 1 root root 0 Feb 27 15:14 cpu.rt_period_us
-rw-r--r--. 1 root root 0 Feb 27 15:14 cpu.rt_runtime_us
-rw-r--r--. 1 root root 0 Feb 27 15:14 cpu.shares
-r--r--r--. 1 root root 0 Feb 27 15:14 cpu.stat
-rw-r--r--. 1 root root 0 Feb 27 15:14 notify_on_release
-rw-r--r--. 1 root root 0 Feb 27 15:14 tasks
### 每个cgroup还可以继续创建下级cgroup,下级会继承上级的一些配置项 ###
[root@localhost ~]# ll /sys/fs/cgroup/cpu/cgroup-c/cgroup-c-1
total 0
-rw-r--r--. 1 root root 0 Feb 27 15:17 cgroup.clone_children
--w--w--w-. 1 root root 0 Feb 27 15:17 cgroup.event_control
-rw-r--r--. 1 root root 0 Feb 27 15:17 cgroup.procs
-r--r--r--. 1 root root 0 Feb 27 15:17 cpuacct.stat
-rw-r--r--. 1 root root 0 Feb 27 15:17 cpuacct.usage
-r--r--r--. 1 root root 0 Feb 27 15:17 cpuacct.usage_percpu
-rw-r--r--. 1 root root 0 Feb 27 15:17 cpu.cfs_period_us
-rw-r--r--. 1 root root 0 Feb 27 15:17 cpu.cfs_quota_us
-rw-r--r--. 1 root root 0 Feb 27 15:17 cpu.rt_period_us
-rw-r--r--. 1 root root 0 Feb 27 15:17 cpu.rt_runtime_us
-rw-r--r--. 1 root root 0 Feb 27 15:17 cpu.shares
-r--r--r--. 1 root root 0 Feb 27 15:17 cpu.stat
-rw-r--r--. 1 root root 0 Feb 27 15:17 notify_on_release
-rw-r--r--. 1 root root 0 Feb 27 15:17 tasks
### 删除cgroup时,需要先删除下级cgroup ###
[root@localhost ~]# rmdir /sys/fs/cgroup/cpu/cgroup-c/
rmdir: failed to remove ‘/sys/fs/cgroup/cpu/cgroup-c/’: Device or resource busy
### 直接删除对应的目录即可 ###
[root@localhost ~]# rmdir /sys/fs/cgroup/cpu/cgroup-c/cgroup-c-1/
[root@localhost ~]# rmdir /sys/fs/cgroup/cpu/cgroup-c
[root@localhost ~]# ll /sys/fs/cgroup/cpu/cgroup-c
ls: cannot access /sys/fs/cgroup/cpu/cgroup-c: No such file or directory
### 数据结构:hierarchy_id:subsystem:cgroup_path ###
[root@localhost ~]# cat /proc/$$/cgroup
11:perf_event:/
10:blkio:/
9:freezer:/
8:pids:/
7:hugetlb:/
6:memory:/
5:cpuacct,cpu:/
4:devices:/
3:net_prio,net_cls:/
2:cpuset:/
1:name=systemd:/user.slice/user-0.slice/session-1.scope
cgroup_path表示从root cgroup(/)开始的路径,比如
/user.slice/user-0.slice/session-1.scope
表示的实际位置为:/sys/fs/cgroup/systemd/user.slice/user-0.slice/session-1.scope
这一篇先简单介绍到这里,主要为了理解cgroups的几个核心概念,具体subsystem的详细配置方法这里就不再继续研究了。