基本概念
namespace:隔离进程组之间的资源
cgroup:对一组进程进行统一的资源监控和限制,进程按组进行管理的机制
cgroup的构成:
- subsystem:对应内核模块,用于对进程组进行操作。
- hierarchy:一棵cgroup树,用于进程分组。
其他:
- 在任意一个hierarchy内包含linux系统的所有process。
- 在同一个hierarchy内,process属于唯一的process group。但process可以存在于不同的hierarchy中。
- hierarchy会对应若干不同的subsystem(可以为0),一个subsystem只能关联一个hierarchy。systemd没有对应的subsystem。
process -> process group(cgroup) -> hierarchy
树节点 -> 树
Subsystem
subsystem name
subsystem关联hierarchy id:如果为0,无绑定/cgroup v2绑定/未被内核开启
num of cgroups:关联hierarchy内进程组个数
enabled:是否开启,通过内核参数cgroup_disable调整
详细
cpu (since Linux 2.6.24; CONFIG_CGROUP_SCHED)
用来限制cgroup的CPU使用率。
cpuacct (since Linux 2.6.24; CONFIG_CGROUP_CPUACCT)
统计cgroup的CPU的使用率。
cpuset (since Linux 2.6.24; CONFIG_CPUSETS)
绑定cgroup到指定CPUs和NUMA节点。
memory (since Linux 2.6.25; CONFIG_MEMCG)
统计和限制cgroup的内存的使用率,包括process memory, kernel memory, 和swap。
devices (since Linux 2.6.26; CONFIG_CGROUP_DEVICE)
限制cgroup创建(mknod)和访问设备的权限。
freezer (since Linux 2.6.28; CONFIG_CGROUP_FREEZER)
suspend和restore一个cgroup中的所有进程。
net_cls (since Linux 2.6.29; CONFIG_CGROUP_NET_CLASSID)
将一个cgroup中进程创建的所有网络包加上一个classid标记,用于tc和iptables。 只对发出去的网络包生效,对收到的网络包不起作用。
blkio (since Linux 2.6.33; CONFIG_BLK_CGROUP)
限制cgroup访问块设备的IO速度。
perf_event (since Linux 2.6.39; CONFIG_CGROUP_PERF)
对cgroup进行性能监控
net_prio (since Linux 3.3; CONFIG_CGROUP_NET_PRIO)
针对每个网络接口设置cgroup的访问优先级。
hugetlb (since Linux 3.5; CONFIG_CGROUP_HUGETLB)
限制cgroup的huge pages的使用量。
pids (since Linux 4.3; CONFIG_CGROUP_PIDS)
限制一个cgroup及其子孙cgroup中的总进程数。
使用
1 | # 挂载一颗和cpuset subsystem关联的cgroup树到/sys/fs/cgroup/cpuset |
查看进程对应的cgroup
proc/[pid]/cgroup
hierarchy id : subsystems : 进程在hierarchy中的相对路径
创建管理cgroup
cgroup目录
cgroup.clone_children
这个文件只对cpuset subsystem 有影响,当该文件的内容为1时,新创建的cgroup将会继承父cgroup的配置,即从父cgroup里面拷贝配置文件来初始化新cgroup,可以参考这里cgroup.procs
当前cgroup中的所有进程ID,系统不保证ID是顺序排列的,且ID有可能重复notify_on_release
该文件的内容为1时,当cgroup退出时(不再包含任何进程和子cgroup),将调用release_agent里面配置的命令。新cgroup被创建时将默认继承父cgroup的这项配置。release_agent
里面包含了cgroup退出(移出)时将会执行的命令,系统调用该命令时会将相应cgroup的相对路径当作参数传进去。 注意:这个文件只会存在于root cgroup下面,其他cgroup里面不会有这个文件。tasks
当前cgroup中的所有线程ID,系统不保证ID是顺序排列的创建子cgroup
新建子文件夹
添加进程
在一颗cgroup树里面,一个进程必须要属于一个cgroup。
新创建的子进程将会自动加入父进程所在的cgroup
从一个cgroup移动一个进程到另一个cgroup时,只要有目的cgroup的写入权限就可以了,系统不会检查源cgroup里的权限。
用户只能操作属于自己的进程,不能操作其他用户的进程,root账号除外
打印当前shell pid
echo $$
1 | sh -c 'echo 1421 > ../cgroup.procs' |
将pid写入,即是进程加入cgroup。pid不可在文件中删除,只可以被转移。因为 在一颗cgroup树里面,一个进程必须要属于一个cgroup
Pid Subsystem
pids.current: 表示当前cgroup及其所有子孙cgroup中现有的总的进程数量
pids.max: 当前cgroup及其所有子孙cgroup中所允许创建的总的最大进程数量
通过写入pids.max限制成功
- 子孙cgroup中的pids.max大小不能超过父cgroup中的大小
- 子cgroup中的进程数不仅受自己的pids.max的限制,还受祖先cgroup的限制
pids.current > pids.max 出现的情况:
- 设置pids.max时,将其值设置的已经比pids.current小
- pids.max只会在当前cgroup中的进程fork、clone的时候生效,将其他进程加入到当前cgroup时,不会检测pids.max
Memory Subsystem
1 | cgroup.event_control #用于eventfd的接口 |
设置了内存限制立即生效 –> 物理内存使用量达到limit –> memory.failcnt +1 –> 内核会尽量将物理内存中的数据移到swap空间上去 –> 设置的limit过小,或者swap空间不足 –> kill掉cgroup内继续申请内存的进程(默认行为)
详细链接
CPU Subsystem
cfs_period_us:时间周期长度
cfs_quota_us:在一个周期长度内所能使用的CPU时间数
cpu.shares:
- 针对所有的CPU的相对值,默认值是1024
- 仅在CPU忙时起作用
- 无法精确的控制CPU使用率,因为cgroup会动态变化
limit_in_cores = cfs_period_us / cfs_quota_us