前言
Linux Cgroups
提供了对一组进程及将来子进程的资源限制、控制和统计的能力,这些资源包括CPU
、内存、存储、网络等.
概念
tasks: 在
cgroups
中,任务就是系统的一个进程.
cgroup(control group): 一组按照某种标准划分的进程.
hierarchy: 把一组cgroup
串成一个树状的结构, 可以做到继承. 比如系统对一组定时的任务进程通过cgroup1
限制了CPU
的使用率,然后其中有一个定时dump
日志的进程还需要限制磁盘IO
,为了避免限制了磁盘IO
之后影响到其他进程,就可以创建cgroup2
,使其继承于cgroup1
井限制磁盘的IO
,这样cgroup2
便继承了cgroup1
中对CPU
使用率的限制,并且增加了磁盘IO
的限制而不影响到cgroup1
中的其他进程.
subsystem: 一个子系统就是一个资源控制器.
他们直接的相互关系如下:
1. 每次在系统中创建新层级时,该系统中的所有任务都是那个层级的默认
cgroup
(称之为root cgroup
,此cgroup
在创建层级时自动创建,后面在该层级中创建的cgroup
都是此cgroup
的后代)的初始成员.
2. 一个子系统最多只能附加到一个层级.
3. 一个层级可以附加多个子系统.
4. 一个任务可以是多个cgroup
的成员,但是这些cgroup
必须在不同的层级.
5. 系统中的进程创建子进程时,该子任务自动成为其父进程所在cgroup
的成员。然后可根据需要将该子任务移动到不同的cgroup
中,但开始时它总是继承其父任务的cgroup
.
如下所示:
CPU 和 Memory 两个子系统有自己独立的层级系统, 而又通过 Task 取得关联关系, 该task
既有CPU
的限制又有Memory
的限制.
本机支持的subsystem
root@nicktming:~# cd /sys/fs/cgroup/
root@nicktming:/sys/fs/cgroup# ls
systemd
root@nicktming:/sys/fs/cgroup# apt-get install cgroup-bin
root@nicktming:/sys/fs/cgroup# lssubsys -a
cpuset
cpu
cpuacct
memory
devices
freezer
blkio
perf_event
hugetlb
root@nicktming:/sys/fs/cgroup# ls
blkio cpu cpuacct cpuset devices freezer hugetlb memory perf_event systemd
cgroup
root@nicktming:~# mkdir cgroup && cd cgroup
root@nicktming:~/cgroup# mkdir demo
root@nicktming:~/cgroup# mount -t cgroup -o none,name=demo demo ./demo
root@nicktming:~/cgroup# ls ./demo
cgroup.clone_children cgroup.event_control cgroup.procs cgroup.sane_behavior notify_on_release release_agent tasks
root@nicktming:~/cgroup# wc -l ./demo/cgroup.procs
80 ./demo/cgroup.procs
root@nicktming:~/cgroup# wc -l ./demo/tasks
95 ./demo/tasks
cgroup.clone_children:
cpuset
的subsystem
会读取这个配置文件,如果这个值是1 (默认是0 ), 子cgroup
才会继承父cgroup
的cpuset
的配置.
cgroup.procs: 树中当前节点cgroup
中的进程组ID
,现在的位置是在根节点,这个文件中会有现在系统中所有进程组的ID
.
tasks: 标识该cgroup
下面的进程ID
,如果把一个进程ID
写到tasks
文件中,便会将相应的进程加入到这个cgroup
中.
创建和删除子cgroup
root@nicktming:~/cgroup# cd demo/
root@nicktming:~/cgroup/demo# mkdir cgroup1
root@nicktming:~/cgroup/demo# ls cgroup1/
cgroup.clone_children cgroup.event_control cgroup.procs notify_on_release tasks
root@nicktming:~/cgroup/demo# mkdir cgroup2
root@nicktming:~/cgroup/demo# tree
.
|-- cgroup1
| |-- cgroup.clone_children
| |-- cgroup.event_control
| |-- cgroup.procs
| |-- notify_on_release
| `-- tasks
|-- cgroup2
| |-- cgroup.clone_children
| |-- cgroup.event_control
| |-- cgroup.procs
| |-- notify_on_release
| `-- tasks
|-- cgroup.clone_children
|-- cgroup.event_control
|-- cgroup.procs
|-- cgroup.sane_behavior
|-- notify_on_release
|-- release_agent
`-- tasks
root@nicktming:~/cgroup/demo# sh -c "echo $$ > cgroup1/tasks"
root@nicktming:~/cgroup/demo# cat cgroup1/tasks
11749
14172
root@nicktming:~/cgroup/demo# cat cgroup2/tasks
// 删除子cgroup 直接删除其文件夹即可
root@nicktming:~/cgroup/demo# rmdir cgroup2
// 如果子cgroup中tasks中有进程的时候删除不了, 必须把进程移到别的cgroup中才可以删除
root@nicktming:~/cgroup/demo# rmdir cgroup1
rmdir: failed to remove ‘cgroup1’: Device or resource busy
// 将该进程从cgroup1移到demo cgroup中
root@nicktming:~/cgroup/demo# sh -c "echo 11749 > tasks"
root@nicktming:~/cgroup/demo# cat cgroup1/tasks
root@nicktming:~/cgroup/demo# rmdir cgroup1
root@nicktming:~/cgroup/demo# tree
.
|-- cgroup.clone_children
|-- cgroup.event_control
|-- cgroup.procs
|-- cgroup.sane_behavior
|-- notify_on_release
|-- release_agent
`-- tasks
subsystem
memory
可以限制
cgroup
中所有进程所能使用的物理内存总量等等.
root@nicktming:/sys/fs/cgroup/memory# ls
cgroup.clone_children memory.kmem.failcnt memory.kmem.tcp.max_usage_in_bytes memory.numa_stat memory.usage_in_bytes
cgroup.event_control memory.kmem.limit_in_bytes memory.kmem.tcp.usage_in_bytes memory.oom_control memory.use_hierarchy
cgroup.procs memory.kmem.max_usage_in_bytes memory.kmem.usage_in_bytes memory.pressure_level notify_on_release
cgroup.sane_behavior memory.kmem.slabinfo memory.limit_in_bytes memory.soft_limit_in_bytes release_agent
memory.failcnt memory.kmem.tcp.failcnt memory.max_usage_in_bytes memory.stat tasks
memory.force_empty memory.kmem.tcp.limit_in_bytes memory.move_charge_at_immigrate memory.swappiness
了解一下几个比较重要的概念
memory.usage_in_bytes #显示当前已用的内存
memory.limit_in_bytes #设置/显示当前限制的内存额度
memory.failcnt #显示内存使用量达到限制值的次数
memory.max_usage_in_bytes #历史内存最大使用量
memory.swappiness #设置和显示当前的swappiness
memory.oom_control #设置/显示oom controls相关的配置
加入cgroup限制
当物理内存达到上限后,系统的默认行为是
kill
掉cgroup
中继续申请内存的进程. 通过memory.oom_control
来控制.
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# cat memory.oom_control
oom_kill_disable 0 // 0表明该进程达到其limit时会被kill, 1表明会暂停该进程
under_oom 0 // 0表明未进入oom状态, 1表明该进程被暂停
例子 oom_kill_disable = 0
root@nicktming:~# cat memory.c
#include
#include
#include
#include
#define MB (1024 * 1024)
int main(int argc, char *argv[])
{
char *p;
int i = 0;
while(1) {
p = (char *)malloc(MB);
memset(p, 0, MB);
printf("%dM memory allocated\n", ++i);
sleep(1);
}
return 0;
}
root@nicktming:/sys/fs/cgroup/memory# mkdir test-limit-memory && cd test-limit-memory
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# sh -c "echo $$ > tasks"
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# sh -c "echo 5M > memory.limit_in_bytes"
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# cd /root
// 可以看到在加入5M的限制后 运行程序在申请5M内存时候被killed.
root@nicktming:~# gcc memory.c -o memory
root@nicktming:~# ./memory
1M memory allocated
2M memory allocated
3M memory allocated
4M memory allocated
Killed
例子 oom_kill_disable = 1
------------------------------------打开终端0-------------------------------
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# sh -c "echo 0 > memory.swappiness"
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# sh -c "echo 1 >> memory.oom_control"
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# cat memory.oom_control
oom_kill_disable 1
under_oom 0
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# cd /root
// 运行到申请5M的时候会暂停该进程
root@nicktming:~# ./memory
1M memory allocated
2M memory allocated
3M memory allocated
4M memory allocated
------------------------------------打开终端1-------------------------------
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# cat memory.oom_control
oom_kill_disable 1
under_oom 1
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# sh -c "echo 15M > memory.limit_in_bytes"
------------------------------------打开终端0-------------------------------
// 该进程继续运行
root@nicktming:~# ./memory
1M memory allocated
2M memory allocated
3M memory allocated
4M memory allocated
5M memory allocated
6M memory allocated
7M memory allocated
8M memory allocated
9M memory allocated
10M memory allocated
11M memory allocated
12M memory allocated
13M memory allocated
14M memory allocated
------------------------------------打开终端1-------------------------------
// 重新把oom_kill_disable打开
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# sh -c "echo 0 >> memory.oom_control"
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# cat memory.oom_control
oom_kill_disable 0
under_oom 0
// 可以看到该进程超过内存限制的次数
root@nicktming:/sys/fs/cgroup/memory/test-limit-memory# cat memory.failcnt
85194
------------------------------------打开终端0-------------------------------
// 由于oom_kill_disable被设置为0, 所以该进程被kill.
root@nicktming:~# ./memory
1M memory allocated
2M memory allocated
3M memory allocated
4M memory allocated
5M memory allocated
6M memory allocated
7M memory allocated
8M memory allocated
9M memory allocated
10M memory allocated
11M memory allocated
12M memory allocated
13M memory allocated
14M memory allocated
Killed
参考
1. https://segmentfault.com/a/1190000006917884
2. https://www.ibm.com/developerworks/cn/linux/1506_cgroup/
3. 自己动手写docker.(基本参考此书,加入一些自己的理解,加深对docker
的理解)
全部内容
1. [mydocker]---环境说明
2. [mydocker]---urfave cli 理解
3. [mydocker]---Linux Namespace
4. [mydocker]---Linux Cgroup
5. [mydocker]---构造容器01-实现run命令
6. [mydocker]---构造容器02-实现资源限制01
7. [mydocker]---构造容器02-实现资源限制02
8. [mydocker]---构造容器03-实现增加管道
9. [mydocker]---通过例子理解存储驱动AUFS
10. [mydocker]---通过例子理解chroot 和 pivot_root
11. [mydocker]---一步步实现使用busybox创建容器
12. [mydocker]---一步步实现使用AUFS包装busybox
13. [mydocker]---一步步实现volume操作
14. [mydocker]---实现保存镜像
15. [mydocker]---实现容器的后台运行
16. [mydocker]---实现查看运行中容器
17. [mydocker]---实现查看容器日志
18. [mydocker]---实现进入容器Namespace
19. [mydocker]---实现停止容器
20. [mydocker]---实现删除容器
21. [mydocker]---实现容器层隔离
22. [mydocker]---实现通过容器制作镜像
23. [mydocker]---实现cp操作
24. [mydocker]---实现容器指定环境变量
25. [mydocker]---网际协议IP
26. [mydocker]---网络虚拟设备veth bridge iptables
27. [mydocker]---docker的四种网络模型与原理实现(1)
28. [mydocker]---docker的四种网络模型与原理实现(2)
29. [mydocker]---容器地址分配
30. [mydocker]---网络net/netlink api 使用解析
31. [mydocker]---网络实现
32. [mydocker]---网络实现测试