Linux cgroup
全文基于 CentOS 7.4
cgroup 是 Linux kernel 的一项功能,用来做资源限制的
systemd 是管理进程的
cgroup 层级系统+ systemd 可以把资源管理设置从进程级别移至应用程序级别
本文首先将介绍如何在systemd 中对应用做资源限制
然后介绍如何手动配置 cgroup
systemd 中 cgroup 的默认层级
默认情况下,systemd 会在cgroup下自动创建 slice、scope 和 service 单位的层级
- name.service
一个或一组进程 - name.scope
一组外部创建的进程 - parent-name.slice
一组按层级排列的单位。slice 并不包含进程
子层标识父的名称
使用 systemd-cgls
可以查看
1 | ├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 21 |
slice 是个逻辑分组,service、scope才是进程运行的地方
在systemd 中使用 cgroup
首先systemd 启动进程分为临时、永久两种方式
临时:
1 | systemd-run --unit=name --scope --slice=slice_name command |
使用systemd 管理进程
创建一个测试例子,来验证cgroup 对cpu的限制
1 | tee /usr/lib/systemd/system/test.service<<EOF |
这样启动后通过top
可观察到cpu占用为100%
设置资源限制
使用命令去修改 cgroup
1 | systemctl set-property --runtime test CPUQuota=10% |
如果不添加 runtime
参数,这个资源限制会被持久化到文件
1 | [root@localhost ~]# cat /etc/systemd/system/test.service.d/50-CPUQuota.conf |
这时候可直接观察到cpu占用降低到10%
这里列下常用配置
1 | [Service] |
更多详细配置参考修改 CGROUP
cgroup = v1
cgroup 的手动配置
内核使用文件系统来配置cgroup
hierarchy(层级)
通过虚拟的文件系统,维护了一个树
描述了cgroup
之间的从属关系,这种结构意味着配置是可以继承的
通过写入树下的文件,对cgroup
配置进行修改
这里只展示创建 cgroup 的层级关系,把进程添加到里面去(不包含资源限制)
创建
1 | # 创建目录,并且挂载为 cgroup 类型 |
注意到 -o none
意味着这个挂载后目录是虚拟的
创建子cgroup
只需要在cgroup-test
中 创建目录
1 | [root@localhost cgroup-test]# mkdir cgroup-1 |
cgroup中添加进程
系统所有进程都默认挂在根节点上
添加进程通过向 tasks
写入PID
1 | echo $$ >> cgroup-1/tasks |
这样就可以加入到 cgroup-1
中
一个进程可以加入到多个
hierarchy
中
之前提到systemd
维护的层,在文件系统里/sys/fs/cgroup
下面
像/sys/fs/cgroup/systemd
、/sys/fs/cgroup/cpu
这些目录都是cgroup的层级
subsystem
资源控制的模块,每个模块下会有一个cgroup的hierarchy
通过在不同的hierarchy中对文件进行配置达到资源限制的效果
查看系统支持的模块
1 | yum install -y libcgroup-tools |
这些模块会对指定的资源做限制,配置路径在/sys/fs/cgroup/<cpu>
资源限制
之前在systemd
里面对CPU做了限制,那么再去看下真正生效的地方
那么查看文件路径可以通过systemd-cgls
找到
1 | └─system.slice |
在 /sys/fs/cgroup/cpu/system.slice/test.service/
下
1 | # cat tasks |
cpu.cfs_period_us: 指cgroup对资源调度周期 (微秒)
cpu.cfs_quota_us: 在一个周期(cpu.cfs_period_us定义),可以占用cpu的时间
一个周期内能占用多少cpu = cpu.cfs_quota_us / cpu.cfs_period_us
也就是设置的10%
然后设置个内存限制看看systemctl set-property --runtime test MemoryLimit=128M
就可以在下面路径看到
1 | cat /sys/fs/cgroup/memory/system.slice/test.service/memory.limit_in_bytes |
systemd 里面参数和内核中配置对应关系
systemd option | cgroup |
---|---|
CPUShares | cpu.shares |
CPUQuota | cpu.cfs_quota_us |
MemoryLimit | memory.limit_in_bytes |
Docker
docker 会给每个容器创建 cgroup,以cpu
为例就是在/sys/fs/cgroup/cpu/docker/