在CentOS上使用CGroups隔离硬件资源

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

title: 在CentOS上使用CGroups隔离硬件资源
date: 2019-07-03 16:30:00
tags:

  • CGroups
  • docker
  • 资源隔离
    categories:
  • Linux

请添加图片描述

CGroups提供了进程级别的资源CPU、内存、网络和磁盘等分配机制也就是可以限制某一个或者某一组进程的资源使用。

为什么需要这么一种技术呢

如果你了解过docker那应该知道容器之间是相互安全隔离的它的底层实现就是采用的CGroups技术。资源隔离是必要的在同一台机器上运行着非常多的进程如果这台机器资源是共享给多个用户在使用你肯定不想因为某个用户的程序负载过大而影响到所有其它用户这就需要资源安全隔离避免发生级联错误。再一个也为了保持大家都公平的使用资源而不会出现一方过多或另一方过少的情况。

本文不介绍更深层次的实现原因会把重点放在CGroups使用层面下面会举个例子详细介绍。

限制CPU使用率

准备一段程序

将下面c代码保存到文件 cputime.c 之中。

void main() {
  unsigned int i, end;
  end = 1024 * 1024 * 1024; 
  for(i = 0; i < end; ) {
    i ++;
  }
}

用gcc命令进行文件编译如果没有这个命令则使用 yum install -y gcc* 进行安装即可。

gcc cputtime.c -o cputime

执行完上面的命令后会在当前目录生成新可执行文件 cputime到这里我们的测试程序就准备完了。

创建控制组

我们将创建一个名称为 cpu_cputime 的控制组在里面会自动生成cpu控制文件修改里面的参数就可以达到限制cpu资源的目的了。

sudo cgcreate -t tianmingxing:tianmingxing -g cpu:/cpu_cputime

命令执行之后可以在目录 /sys/fs/cgroup/cpu/cpu_cputime 下看到上面创建的控制组。

$ ll /sys/fs/cgroup/cpu/cpu_cputime/
total 0
-rw-rw-r-- 1 root         root         0 Jul  3 05:08 cgroup.clone_children
--w--w---- 1 root         root         0 Jul  3 05:08 cgroup.event_control
-rw-rw-r-- 1 root         root         0 Jul  3 05:08 cgroup.procs
-r--r--r-- 1 root         root         0 Jul  3 05:08 cpuacct.stat
-rw-rw-r-- 1 root         root         0 Jul  3 05:08 cpuacct.usage
-r--r--r-- 1 root         root         0 Jul  3 05:08 cpuacct.usage_percpu
-rw-rw-r-- 1 root         root         0 Jul  3 05:08 cpu.cfs_period_us
-rw-rw-r-- 1 root         root         0 Jul  3 05:08 cpu.cfs_quota_us
-rw-rw-r-- 1 root         root         0 Jul  3 05:08 cpu.rt_period_us
-rw-rw-r-- 1 root         root         0 Jul  3 05:08 cpu.rt_runtime_us
-rw-rw-r-- 1 root         root         0 Jul  3 05:08 cpu.shares
-r--r--r-- 1 root         root         0 Jul  3 05:08 cpu.stat
-rw-rw-r-- 1 root         root         0 Jul  3 05:08 notify_on_release
-rw-rw-r-- 1 tianmingxing tianmingxing 0 Jul  3 05:08 tasks

CPU参数配置

不建议直接修改上面列出的文件内容请使用下面的命令进行修改。

sudo cgset -r cpu.cfs_quota_us=10000000 cpu_cputime

如果要查询某个控制组下面的配置可以采用下面的命令

$ cgget -g cpu:cpu_cputime
cpu_cputime:
cpu.rt_period_us: 1000000
cpu.rt_runtime_us: 0
cpu.stat: nr_periods 686341
	nr_throttled 7886
	throttled_time 702560123598
cpu.cfs_period_us: 1000000
cpu.cfs_quota_us: 10000000
cpu.shares: 1024
......

参数介绍

cfs_quota_uscfs_period_us 参数单位是微秒其中前者是指一个周期内总的可用运行时间后者是指一个周期的长度它们可以配合起来限制CPU的运行时间下面列举几组例子让大家更容易理解。

  1. cpu.cfs_quota_us=250000cpu.cfs_period_us=250000 如果period为250ms且quota为250ms那么该控制组每250ms将获得1个CPU运行时间。
  2. cpu.cfs_quota_us=1000000cpu.cfs_period_us=500000 如果period为500ms且quota为1000ms那么该控制组每500ms将获得2个CPU运行时间。
  3. cpu.cfs_quota_us=10000cpu.cfs_period_us=50000 如果period为50ms且quota为10ms那么该控制组每50ms将获得1个CPU的20%运行时间。

设想一下在32核CPU下如果要限制某个进程占用8个CPU运行时间该怎么配置呢通过上面的例子举一反三思考一下相信可以得出答案。

核数配置
2核cgset -r cpu.cfs_quota_us=1000000 cpu_2c cgset -r cpu.cfs_period_us=500000 cpu_2c
4核cgset -r cpu.cfs_quota_us=2000000 cpu_4c cgset -r cpu.cfs_period_us=500000 cpu_4c
8核cgset -r cpu.cfs_quota_us=4000000 cpu_8c cgset -r cpu.cfs_period_us=500000 cpu_8c
16核cgset -r cpu.cfs_quota_us=8000000 cpu_16c cgset -r cpu.cfs_period_us=500000 cpu_16c

测试程序

不限制资源的情况下

使用 time 命令可以为我们报告程序执行消耗的时间其中的 real 就是我们真实感受到的时间。

$ time ./cputime

real	0m3.153s
user	0m3.152s
sys	0m0.001s

限制资源的情况下

将控制组限制为1个CPU的20%。

sudo cgset -r cpu.cfs_quota_us=10000 cpu_cputime
sudo cgset -r cpu.cfs_period_us=50000 cpu_cputime

然后我们再执行程序不过本次要在cgroup中运行应用程序

# 其实很简单把要执行的命令整体放到后面即可
sudo cgexec -g cpu:/cpu_cputime time ./cputime

real	0m10.681s
user	0m10.680s
sys	0m0.001s

如果以普通用户执行上面命令可能会提示权限不足等一些问题此时可以对控制组目录进行授权。

sudo chown -R tianmingxing:tianmingxing /sys/fs/cgroup/cpu/cpu_cputime

可以使用下面的命令检查程序是否在所需的cgroup中运行把pid替换成真实进程编号

$ ps -o cgroup [pid]
CGROUP
11:pids:/user.slice,10:devices:/user.slice,8:blkio:/user.slice,6:memory:/memory_4g,3:cpuacct,cpu:/cputime,1:name=systemd:/user.slice/user-1007.slice/session-7250.scope

从上面 cpu:/cputime 中可以看到这个进程确实是在我们定义的cgroup中运行。

限制内存

同样的像下面这样设置内存最大使用量11G这个值是由 1024 * 1024 * 1024 * 11 计算出来的你可以根据需求自己调整。

sudo cgcreate -t tianmingxing:tianmingxing -g memory:/memory_cputime
sudo cgset -r memory.limit_in_bytes=11811160064 memory_cputime

# 如果要查询内存所有参数设置可以使用下面的命令
$ cgget -g memory:memory_cputime
memory_cputime:
memory.kmem.tcp.max_usage_in_bytes: 0
memory.kmem.tcp.failcnt: 0
memory.kmem.tcp.usage_in_bytes: 0
memory.kmem.tcp.limit_in_bytes: 9223372036854771712
memory.memsw.failcnt: 0
memory.limit_in_bytes: 11811160064
memory.memsw.max_usage_in_bytes: 11811291136
memory.memsw.usage_in_bytes: 11809599488
memory.kmem.max_usage_in_bytes: 0
memory.kmem.failcnt: 0
memory.kmem.usage_in_bytes: 0
......

小结

  1. 可以通过 top 系统命令并查看 %CPU%MEM 列确认目标进程资源是否真的被限制住了这个百分比只表示单核如果机器是多核就乘以核数。
  2. 如果某个控制组已经应用在一个进程上了那再次使用该控制组将中断原先的进程你可以通过创建多个控制组来解决这个问题。
  3. 其它资源的限制方法和上面是类似的大家可以尝试一下本文不再赘述。

参考文献

  1. http://www.manongjc.com/article/7475.html
  2. https://www.linuxjournal.com/content/everything-you-need-know-about-linux-containers-part-i-linux-control-groups-and-process
  3. https://tech.meituan.com/2015/03/31/cgroups.html
  4. https://www.ibm.com/developerworks/cn/linux/1506_cgroup/index.html
  5. https://www.cnblogs.com/sparkdev/p/8052522.html
  6. https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: centos