利用cgroup限制cpu和memory利用率

Posted lichenyangyixin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用cgroup限制cpu和memory利用率相关的知识,希望对你有一定的参考价值。

  我们环境使用的Linux内核版本是4.4,已支持cgroup,只要在内核配置中选上cgroup,并勾选自己想要的配置(general setup->control group support->)

网上有各种资料介绍cgroup,这里我就不详述了,直接mount cgoup

mkdir cgroup
mkdir cgroup/cpu
mkdir cgroup/memory
mount -t cgroup -ocpu cpu cgroup/cpu
mount -t cgroup -omemory memory cgroup/memory > /dev/util 2>&1

mkdir cgroup/cpu/cgroup0

1、限制cpu利用率

  通过cfs_period_us和cpu.cfs_quota_us配合实现,cfs_period_us默认值是100ms,代表周期时间是100ms,cpu.cfs_quota_us是进程在100ms周期内所能占用的最大时间,可以设置为95ms,即cpu利用率是95%,注意这个单个cpu的利用率;对于多核系统,如果想设置95%利用率,cpu.cfs_quota_us应该是N*cfs_period_us*95%,N是cpu的核数,通过cat proc/cpuinfo查看(CpuNum=`cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c | awk -F ‘ ‘ ‘print $1‘`)

#set cpu ratio 98%
cfs_quota_us=`expr $CpuNum \* $cfs_period_us \* 98 / 100`
echo $cfs_quota_us > /cgroup/cpu/cgroup0/cpu.cfs_quota_us
echo $rcSPid > /cgroup/cpu/cgroup0/cgroup.procs

  对于运行了实时进程的环境来说,需要根据cpu.rt_period_us设置cpu.rt_runtime_us,cpu.rt_period_us是实时进程的周期时间,默认1s;cpu.rt_runtime_us是在一个周期时间内,实时进程占用的最大时间,默认是0;一开始没有注意到这个,我们的环境一配置上cgroup,就会异常导致重启,后来发现是rt_runtime_us为0;可以设置成内核默认值950ms(cat /proc/sys/kernel/sched_rt_runtime_us),或者再cgroup的内核配置中去掉sched_rt项。这样RT进程就不会被cgroup限制,即cgroup0目录下没有cpu.rt_runtime_us这一项

  将cpu利用率设置好之后,才可以将需要限制的进程pid加入cgroup.procs;由于我们环境中的进程由rcS中起的,因此只需要将一开始只需要将rcS的pid加入cgroup.procs,后续创建的子进程都会被自动加入到cgroup.procs中(获取pid rcSPid=`ps -o pid,comm | grep -o "[0-9]*.rcS" | grep -o [0-9]*`)

2、限制memory利用率

  为了避免某些进程的bug导致内存泄露,可以使用memory.limit_in_bytes限制cgroup0组中所有进程所能使用的最大内存,单位是字节;由于我们环境中的进程由rcS中起的,因此只需要将一开始只需要将rcS的pid加入cgroup.procs,后续创建的子进程都会被自动加入到cgroup.procs中。我的环境设置memory.limit_in_bytes为MemFree-200M(留下200M给内核使用已足够)

MemFree=`cat /proc/meminfo | grep ‘MemFree‘ | awk -F ‘ ‘ ‘print $2‘`
MemRatioKB=`expr $MemFree - 204800`
MemRatio=`expr $MemRatioKB \* 1024`#config memory ratio

mkdir cgroup/memory/cgroup0 > /dev/util 2>&1
echo $MemRatio >
/cgroup/memory/cgroup0/memory.limit_in_bytes
  进程占用的内存超出设置的阈值,会怎么样呢?会被kill!!如果你不想被kill,那就要置memory.oom_control为1,这样在进展占用内存超出阈值时,进程会被加入等待队列直到有内存分配给他;
#disable kill
echo 1 >
cgroup/memory/cgroup0/memory.oom_control

memory目录下其他项:

cgroup.event_control #用于eventfd的接口
memory.usage_in_bytes #显示当前已用的内存
memory.limit_in_bytes #设置/显示当前限制的内存额度
memory.failcnt #显示内存使用量达到限制值的次数
memory.max_usage_in_bytes #历史内存最大使用量
memory.soft_limit_in_bytes #设置/显示当前限制的内存软额度
memory.stat #显示当前cgroup的内存使用情况
memory.use_hierarchy #设置/显示是否将子cgroup的内存使用情况统计到当前cgroup里面
memory.force_empty #触发系统立即尽可能的回收当前cgroup中可以回收的内存
memory.pressure_level #设置内存压力的通知事件,配合cgroup.event_control一起使用
memory.swappiness #设置和显示当前的swappiness
memory.move_charge_at_immigrate #设置当进程移动到其他cgroup中时,它所占用的内存是否也随着移动过去
memory.oom_control #设置/显示oom controls相关的配置
memory.numa_stat #显示numa相关的内存

附上cpu利用率消耗程序和内存消耗程序,也是参考别人的。

1、cpu消耗,入参是创见的进程个数,(一个进程消耗一个cpu核)

int main(int argc, char *argv[])
pid_t pid;
int i, pn=4;
if(argc==2)
pn=atoi(argv[1]);

for(i=0;i<pn;i++)
pid=fork();
if(pid<=0)break;

if(pid<0)
printf("fork() error\n");
return -1;
else if(pid==0)
//sub process works
for(;;);
else
//wait for the sub process‘s termination
wait(NULL);

return 0;

2、内存消耗

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MB (1024 * 1024 * 1024)

int main(int argc, char *argv[])

char *p;
int i = 0;
system("cat /cgroup/cpu/cgroup0/cgroup.procs");
while(1)
p = (char *)malloc(MB);
memset(p, 0, MB);
printf("%dG memory allocated\n", ++i);
sleep(1);

return 0;

以上是关于利用cgroup限制cpu和memory利用率的主要内容,如果未能解决你的问题,请参考以下文章

Docker容器之Cgroup资源配置!

Docker容器之Cgroup资源配置!

Docker容器之Cgroup资源配置!

Docker 容器CPU设置

Docker基础 Linux内核之Cgroups

docker-限制CPU使用