容器基础(三): 使用Cgroups进行资源限制

Linux Cgroups 

Linux Cgroups 是 Linux 内核中用来为进程设置资源限制的一个重要功能. Cgroups将进程进行分组, 然后对这一组进程进行统一的资源监控和限制。Cgroups当前有V1和V2版本,为了后续用于实现简单容器sdocker,这里只验证V1版本的cpu和memory子系统。

Linux可以通过如下命令来查看当前系统支持的cgroup子系统:

 1 linux: # cat /proc/cgroups
 2 #subsys_name    hierarchy       num_cgroups     enabled
 3 cpuset          11      1       1
 4 cpu             2       78      1
 5 cpuacct         2       78      1
 6 blkio           3       78      1
 7 memory          9       79      1
 8 devices         4       78      1
 9 freezer         8       1       1
10 net_cls         7       78      1
11 perf_event      5       1       1
12 net_prio        7       78      1
13 hugetlb         6       1       1
14 pids            10      86      1
15 linux: #

有的系统(debian8/suse12), cgroup.memory没有启用, 这时可能会影响到下面几个方面:

1. 在/sys/fs/cgroup/memory下建立目录失败, 提示readonly;
2. docker info里面也会有提示信息;
3. 使用kubeadm安装kubernetes时会提示错误;

解决办法, 在/etc/default/grub文件中增加如下选项(debian使用update_grub, suse使用grub2-mkconfig, 然后reboot):

1 linux: # cat /etc/default/grub  | grep cgroup_enable
2 GRUB_CMDLINE_LINUX="cgroup_enable=memory"
3 linux: #

Cgroup.CPU

对于Cgroup.CPU,限制cpu利用率主要通过修改下面两个文件来实现:

1 /sys/fs/cgroup/cpu/cpu.cfs_quota_us
2 /sys/fs/cgroup/cpu/cpu.cfs_period_us

把cpu.cfs_quota_us / cpu.cfs_period_us(默认100000)的值作为可以使用的CPU的百分比。使用方法举例如下(摘录自附录网页):

 1 Examples
 2 --------
 3 1. Limit a group to 1 CPU worth of runtime.
 4 
 5     If period is 250ms and quota is also 250ms, the group will get
 6     1 CPU worth of runtime every 250ms.
 7 
 8     # echo 250000 > cpu.cfs_quota_us /* quota = 250ms */
 9     # echo 250000 > cpu.cfs_period_us /* period = 250ms */
10 
11 2. Limit a group to 2 CPUs worth of runtime on a multi-CPU machine.
12 
13     With 500ms period and 1000ms quota, the group can get 2 CPUs worth of
14     runtime every 500ms.
15 
16     # echo 1000000 > cpu.cfs_quota_us /* quota = 1000ms */
17     # echo 500000 > cpu.cfs_period_us /* period = 500ms */
18 
19     The larger period here allows for increased burst capacity.
20 
21 3. Limit a group to 20% of 1 CPU.
22 
23     With 50ms period, 10ms quota will be equivalent to 20% of 1 CPU.
24 
25     # echo 10000 > cpu.cfs_quota_us /* quota = 10ms */
26     # echo 50000 > cpu.cfs_period_us /* period = 50ms */
27 
28     By using a small period here we are ensuring a consistent latency
29     response at the expense of burst capacity.

针对Cgroup.CPU进行测试,对于如下的cpu密集型程序, 启动后从top中可以看到cpu占用100%:

1 linux: # cat cpu.c
2 int main(void) {
3   for (; ;);
4 
5   return 0;
6 }
7 linux: #
1 PID USER      PR  NI    VIRT    RES    SHR S   %CPU  %MEM     TIME+ COMMAND
2 4033 root      20   0    4052    708    632 R 100.00 0.002   1:33.02 cpu

通过给cpu.cfs_quota_us赋值20000,同时把程序pid赋值给tasks文件,让程序只能使用1/5的cpu。

1 linux: # mkdir /sys/fs/cgroup/cpu/sdocker
2 linux: # mkdir /sys/fs/cgroup/cpu/sdocker/4033
3 linux: # echo 20000 > /sys/fs/cgroup/cpu/sdocker/4033/cpu.cfs_quota_us
4 linux: # echo 4033 > /sys/fs/cgroup/cpu/sdocker/4033/tasks

 设置后立即生效,top可以看到进程cpu占用率在20%左右波动:

1 PID USER      PR  NI    VIRT    RES    SHR S   %CPU  %MEM     TIME+ COMMAND
2 4033 root      20   0    4052    708    632 R 20.202 0.002   1:57.80 cpu

退出程序并清理cgroup资源:

1 linux: # kill -9 4033  
2 linux: # rmdir /sys/fs/cgroup/cpu/sdocker/4033/

 Cgroup.Memory

/sys/fs/cgroup/memory下定义了Cgroup.Memory子系统的相关文件, 各文件含义如下:

 1  cgroup.event_control       #用于eventfd的接口
 2  memory.usage_in_bytes      #显示当前已用的内存字节数
 3  memory.limit_in_bytes      #设置/显示当前限制的内存额度, 当usage_in_bytes超限时, 如果memory.swappiness配置可使用swap, kernel会优先把内存数据转移到swap空间, 最后若转移swap失败, 则根据memory.oom_control判断是否触发oom
 4  memory.failcnt             #显示内存使用量达到限制值的次数, 当usage_in_bytes超限时, 会触发该值增加
 5  memory.max_usage_in_bytes  #历史内存最大使用量
 6  memory.soft_limit_in_bytes #设置/显示当前限制的内存软额度
 7  memory.stat                #显示当前cgroup的内存使用情况
 8  memory.use_hierarchy       #设置/显示是否将子cgroup的内存使用情况统计到当前cgroup里面
 9  memory.force_empty         #触发系统立即尽可能的回收当前cgroup中可以回收的内存
10  memory.pressure_level      #设置内存压力的通知事件,配合cgroup.event_control一起使用
11  memory.swappiness          #设置和显示当前的swappiness
12  memory.move_charge_at_immigrate #设置当进程移动到其他cgroup中时,它所占用的内存是否也随着移动过去
13  memory.oom_control         #设置/显示oom controls相关的配置, 默认0启用
14  memory.numa_stat           #显示numa相关的内存

针对Cgroup.Memory进行测试,如下的测试代码通过不断分配内存来触发内存限制功能:

 1 linux: # cat memory.cpp
 2 #include <unistd.h>
 3 
 4 #include <csignal>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <cstring>
 8 #include <vector>
 9 using std::vector;
10 
11 vector<int *> g_mem_pointer;
12 
13 void sig_handler(int sig) {
14   printf("
%d handle
", sig);
15   for (auto p : g_mem_pointer) {
16     free(p);
17   }
18 
19   exit(-1);
20 }
21 
22 int main(void) {
23   unsigned total_mem = 0, chunk_size = 1024 * 1024;
24 
25   signal(SIGTERM, sig_handler);
26   signal(SIGINT, sig_handler);
27 
28   int *p;
29   while (1) {
30     if (NULL == (p = (int *)malloc(chunk_size))) {
31       printf("[-] malloc failed!
");
32       kill(getpid(), 15);
33     }
34 
35     memset(p, 0xff, chunk_size);
36     g_mem_pointer.push_back(p);
37     total_mem += chunk_size;
38     printf("[+] malloc size: %u
", total_mem);
39     sleep(10);
40   }
41 
42   return 0;
43 }
44 linux: #
memory.cpp

设置内存限制6m到memory.limit_in_bytes,同时把进程pid设置到tasks文件, 一段时间后可以看到进程oom-kill.

测试发现进程实际打印分配的总内存远远大于设置的内存上限时,  memory.usage_in_bytes中的数值才会慢慢趋近于memory.limit_in_bytes,即使设置memory.swappiness为0也如此;

1 linux:~ # mkdir /sys/fs/cgroup/memory/sdocker
2 linux:~ # mkdir /sys/fs/cgroup/memory/sdocker/5239
3 linux:~ # echo 6m > /sys/fs/cgroup/memory/sdocker/5239/memory.limit_in_bytes
4 linux:~ # cat /sys/fs/cgroup/memory/sdocker/5239/memory.limit_in_bytes
5 32768
6 linux:~ # echo 5239 > /sys/fs/cgroup/memory/sdocker/5239/tasks
7 linux:~ # rmdir /sys/fs/cgroup/memory/sdocker/5239

参考网址:

1 https://segmentfault.com/u/wuyangchun
2 https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt
3 https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt

Excellence, is not an act, but a habit.
作者:子厚.
出处:http://www.cnblogs.com/aios/
本文版权归作者和博客园共有,欢迎转载、交流、点赞、评论,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

原文地址:https://www.cnblogs.com/aios/p/10032990.html