Docker是如何使用Cgroups的

Cgroups用法

创建并挂载一个hierarchy

在新建的hierarchy上的cgroup的根节点中扩展出两个子cgroup

通过subsystem来限制cgroup中进程的资源

Docker中的Cgroups

环境说明:

[root@fqhnode01 ~]# uname -a
Linux fqhnode01 3.10.0-514.6.1.el7.x86_64
[root@fqhnode01 ~]# docker version
Client:
 Version:      1.18.1

创建并挂载一个hierarchy

[root@fqhnode01 home]# mkdir cgroups-test
[root@fqhnode01 home]# mount -t cgroup -o none,name=cgroups-test cgroups-test ./cgroups-test
[root@fqhnode01 home]# ll cgroups-test/
总用量 0
-rw-r--r--. 1 root root 0 111 12:31 cgroup.clone_children
--w--w--w-. 1 root root 0 111 12:31 cgroup.event_control
-rw-r--r--. 1 root root 0 111 12:31 cgroup.procs
-r--r--r--. 1 root root 0 111 12:31 cgroup.sane_behavior
-rw-r--r--. 1 root root 0 111 12:31 notify_on_release
-rw-r--r--. 1 root root 0 111 12:31 release_agent
-rw-r--r--. 1 root root 0 111 12:31 tasks

在新建的hierarchy上的cgroup的根节点中扩展出两个子cgroup

[root@fqhnode01 cgroups-test]# cd cgroups-test/
[root@fqhnode01 cgroups-test]# mkdir cgroup-1 cgroup-2
[root@fqhnode01 cgroups-test]# ls
cgroup-1  cgroup.clone_children  cgroup.procs          notify_on_release  tasks
cgroup-2  cgroup.event_control   cgroup.sane_behavior  release_agent
[root@fqhnode01 cgroups-test]# 
[root@fqhnode01 cgroups-test]# tree
.
├── cgroup-1
│   ├── cgroup.clone_children
│   ├── cgroup.event_control
│   ├── cgroup.procs
│   ├── notify_on_release
│   └── tasks
├── cgroup-2
│   ├── 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
2 directories, 17 files

可以看出,在一个cgroup的目录下创建文件夹时,系统Kernel会自动把该文件夹标记为这个cgroup的子cgroup,它们会继承父cgroup的属性。

几个文件功能说明:

tasks,标识该cgroup下面的进程ID。如果把一个进程ID写入了tasks文件,就是把该进程加入了这个cgroup中。
cgroup.procs 是树中当前cgroup中的进程组ID。如果是根节点,会包含所有的进程组ID。
cgroup.clone_children,默认值为0。如果设置为1,子cgroup会继承父cgroup的cpuset配置。
往一个cgroup中添加和移动进程
首先,查看一个进程目前所处的cgroup

[root@fqhnode01 cgroup-1]# echo $$
1019
[root@fqhnode01 cgroup-1]# cat /proc/1019/cgroup 
12:name=cgroups-test:/
11:devices:/
10:memory:/
9:hugetlb:/
8:cpuset:/
7:blkio:/
6:cpuacct,cpu:/
5:freezer:/
4:net_prio,net_cls:/
3:perf_event:/
2:pids:/
1:name=systemd:/user.slice/user-0.slice/session-1.scope

从name=cgroups-test:/可以看到当前进程($$)位于hierarchy cgroups-test:/的根节点上。

把进程移动到节点cgroup-1/中

[root@fqhnode01 cgroups-test]# cd cgroup-1/
[root@fqhnode01 cgroup-1]# cat tasks 
[root@fqhnode01 cgroup-1]# 
[root@fqhnode01 cgroup-1]# cat cgroup.procs 
[root@fqhnode01 cgroup-1]#

可以看到目前节点cgroup-1的tasks文件是空的。

[root@fqhnode01 cgroup-1]# echo $$ >> tasks
[root@fqhnode01 cgroup-1]# cat /proc/1019/cgroup 
12:name=cgroups-test:/cgroup-1
11:devices:/
10:memory:/
9:hugetlb:/
8:cpuset:/
7:blkio:/
6:cpuacct,cpu:/
5:freezer:/
4:net_prio,net_cls:/
3:perf_event:/
2:pids:/
1:name=systemd:/user.slice/user-0.slice/session-1.scope

[root@fqhnode01 cgroup-1]# cat cgroup.procs 
1019
1436
[root@fqhnode01 cgroup-1]# cat tasks 
1019
1437

可以看到,当前进程1019已经加入到cgroups-test:/cgroup-1中了。

需要注意的是,到目前为止,上面创建的hierarchy并没有关联到任何的subsystem,所以还是没有办法通过上面的cgroup节点来限制一个进程的资源占用。

通过subsystem来限制cgroup中进程的资源
系统已经默认为每一个subsystem创建了一个hierarchy,以memory的hierarchy为例子

#mount |grep memory
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)

可以看到memory subsystem的hierarchy的目录是/sys/fs/cgroup/memory。 这个目录就跟上面我们创建的目录类似,只不过它是系统默认创建的,已经和memory subsystem关联起来,可以限制其名下进程占用的内存。

安装stress工具

yum install stress.x86_64

不使用Cgroups限制,启动一个占用200M内存的stress进程

[root@fqhnode01 memory]# stress --vm-bytes 200m --vm-keep -m 1
测试结果如下,本机内存为2G,所以2G*10%=200M:
```shell
#top
 PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                     
 1851 root      20   0  212060 204796    132 R 96.3 10.0   0:18.27 stress  

使用Cgroups进行限制,仅允许使用100M内存
首先参照前面步骤,在memory 的根节点下新建一个cgroup节点test-limit-memory

[root@fqhnode01 memory]# cd /sys/fs/cgroup/memory
[root@fqhnode01 memory]# mkdir test-limit-memory

然后,设置该cgroup节点的最大内存占用为100M

[root@fqhnode01 memory]# cd test-limit-memory/
[root@fqhnode01 test-limit-memory]# cat memory.limit_in_bytes 
9223372036854771712
[root@fqhnode01 test-limit-memory]# echo "100m" >> ./memory.limit_in_bytes 
[root@fqhnode01 test-limit-memory]# 
[root@fqhnode01 test-limit-memory]# cat memory.limit_in_bytes 
104857600

然后,把当前进程移动到这个cgroup节点test-limit-memory中

[root@fqhnode01 test-limit-memory]# cat tasks 
[root@fqhnode01 test-limit-memory]# 
[root@fqhnode01 test-limit-memory]# echo $$ >> tasks 
[root@fqhnode01 test-limit-memory]# cat tasks 
1019
1878

最后,再次运行stress --vm-bytes 200m --vm-keep -m 1,测试结果如下:

 PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                     
 1881 root      20   0  212060  87924    132 R 37.0  4.3   0:12.05 stress  

观察显示内存占用最大值只能达到5%,也就是100m。 成功地使用Cgroups把stree进程的内存占用限制到了100m的范围之内。

最后说一下上面创建的/sys/fs/cgroup/memory/test-limit-memory文件会在重启之后被系统自动删除。 如果要删除一个cgroup,用umount命令。

Docker中的Cgroups

[root@fqhnode01 memory]# docker run -itd  -e is_leader=true -e node_name=aaa -m 128m 98c2ef0aa9bb
e19acd747074941e9062f2beb5163927b097296f31b7a0317ecb93387cc16466

docker 会自动在memory hierarchy的目录下新建一个cgroup节点

[root@fqhnode01 e19acd747074941e9062f2beb5163927b097296f31b7a0317ecb93387cc16466]# pwd
/sys/fs/cgroup/memory/docker/e19acd747074941e9062f2beb5163927b097296f31b7a0317ecb93387cc16466
[root@fqhnode01 e19acd747074941e9062f2beb5163927b097296f31b7a0317ecb93387cc16466]# cat memory.limit_in_bytes 
134217728
[root@fqhnode01 e19acd747074941e9062f2beb5163927b097296f31b7a0317ecb93387cc16466]# cat memory.usage_in_bytes 
66355200

memory.limit_in_bytes 内存限制
memory.usage_in_bytes 该cgroup中的进程已经使用的memory

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值