[mydocker]---Linux Cgroup

前言

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.

如下所示:

[mydocker]---Linux Cgroup_第1张图片
hierarchy-subsystem-cgroup-task.png

CPUMemory 两个子系统有自己独立的层级系统, 而又通过 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: cpusetsubsystem 会读取这个配置文件,如果这个值是1 (默认是0 ), 子cgroup 才会继承父cgroupcpuset 的配置.
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限制

当物理内存达到上限后,系统的默认行为是killcgroup中继续申请内存的进程. 通过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的理解)

全部内容

[mydocker]---Linux Cgroup_第2张图片
mydocker.png

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]---网络实现测试

你可能感兴趣的:([mydocker]---Linux Cgroup)