Linux Cgroups

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

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

 linux: # cat /proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset
cpu
cpuacct
blkio
memory
devices
freezer
net_cls
perf_event
net_prio
hugetlb
pids
linux: #

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

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

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

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

Cgroup.CPU

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

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

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

 Examples
--------
. Limit a group to CPU worth of runtime. If period is 250ms and quota is also 250ms, the group will get
CPU worth of runtime every 250ms. # echo > cpu.cfs_quota_us /* quota = 250ms */
# echo > cpu.cfs_period_us /* period = 250ms */ . Limit a group to CPUs worth of runtime on a multi-CPU machine. With 500ms period and 1000ms quota, the group can get CPUs worth of
runtime every 500ms. # echo > cpu.cfs_quota_us /* quota = 1000ms */
# echo > cpu.cfs_period_us /* period = 500ms */ The larger period here allows for increased burst capacity. . Limit a group to % of CPU. With 50ms period, 10ms quota will be equivalent to % of CPU. # echo > cpu.cfs_quota_us /* quota = 10ms */
# echo > cpu.cfs_period_us /* period = 50ms */ By using a small period here we are ensuring a consistent latency
response at the expense of burst capacity.

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

 linux: # cat cpu.c
int main(void) {
for (; ;); return ;
}
linux: #
 PID USER      PR  NI    VIRT    RES    SHR S   %CPU  %MEM     TIME+ COMMAND
root R 100.00 0.002 :33.02 cpu

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

 linux: # mkdir /sys/fs/cgroup/cpu/sdocker
linux: # mkdir /sys/fs/cgroup/cpu/sdocker/
linux: # echo > /sys/fs/cgroup/cpu/sdocker//cpu.cfs_quota_us
linux: # echo > /sys/fs/cgroup/cpu/sdocker//tasks

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

 PID USER      PR  NI    VIRT    RES    SHR S   %CPU  %MEM     TIME+ COMMAND
root R 20.202 0.002 :57.80 cpu

退出程序并清理cgroup资源:

 linux: # kill -
linux: # rmdir /sys/fs/cgroup/cpu/sdocker//

Cgroup.Memory

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

  cgroup.event_control       #用于eventfd的接口
memory.usage_in_bytes #显示当前已用的内存字节数
memory.limit_in_bytes #设置/显示当前限制的内存额度, 当usage_in_bytes超限时, 如果memory.swappiness配置可使用swap, kernel会优先把内存数据转移到swap空间, 最后若转移swap失败, 则根据memory.oom_control判断是否触发oom
memory.failcnt #显示内存使用量达到限制值的次数, 当usage_in_bytes超限时, 会触发该值增加
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相关的配置, 默认0启用
memory.numa_stat #显示numa相关的内存

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

 linux: # cat memory.cpp
#include <unistd.h> #include <csignal>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
using std::vector; vector<int *> g_mem_pointer; void sig_handler(int sig) {
printf("\n%d handle\n", sig);
for (auto p : g_mem_pointer) {
free(p);
} exit(-);
} int main(void) {
unsigned total_mem = , chunk_size = * ; signal(SIGTERM, sig_handler);
signal(SIGINT, sig_handler); int *p;
while () {
if (NULL == (p = (int *)malloc(chunk_size))) {
printf("[-] malloc failed!\n");
kill(getpid(), );
} memset(p, 0xff, chunk_size);
g_mem_pointer.push_back(p);
total_mem += chunk_size;
printf("[+] malloc size: %u\n", total_mem);
sleep();
} return ;
}
linux: #

memory.cpp

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

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

 linux:~ # mkdir /sys/fs/cgroup/memory/sdocker
linux:~ # mkdir /sys/fs/cgroup/memory/sdocker/
linux:~ # echo 6m > /sys/fs/cgroup/memory/sdocker//memory.limit_in_bytes
linux:~ # cat /sys/fs/cgroup/memory/sdocker//memory.limit_in_bytes linux:~ # echo > /sys/fs/cgroup/memory/sdocker//tasks
linux:~ # rmdir /sys/fs/cgroup/memory/sdocker/

参考网址:

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

容器基础(三): 使用Cgroups进行资源限制的更多相关文章

  1. linux(centos8):使用cgroups做资源限制

    一,什么是cgroups? 1,cgroups是资源的控制组,它提供了一套机制用于控制一组特定进程对资源的使用.     cgroups绑定一个进程集合到一个或多个限制资源使用的子系统上. 2, cg ...

  2. docker容器基础

    一.docker容器基础6种名称空间:UTS.MOunt.IPC.PID.User.Net (1) Linux Namespaces:namespace 系统调用参数 隔离内容 内核版本  UTS   ...

  3. C++ 顺序容器基础知识总结

    0.前言 本文简单地总结了STL的顺序容器的知识点.文中并不涉及具体的实现技巧,对于细节的东西也没有提及.一来不同的标准库有着不同的实现,二来关于具体实现<STL源码剖析>已经展示得全面细 ...

  4. Bootstrap <基础三十>Well

    Well 是一种会引起内容凹陷显示或插图效果的容器 <div>.为了创建 Well,只需要简单地把内容放在带有 class .well 的 <div> 中即可.下面的实例演示了 ...

  5. day 53-1 Django基础三之视图函数

    Django基础三之视图函数   本节目录 一 Django的视图函数view 二 CBV和FBV 三 使用Mixin 四 给视图加装饰器 五 Request对象 六 Response对象 一 Dja ...

  6. day 67 Django基础三之视图函数

    Django基础三之视图函数   本节目录 一 Django的视图函数view 二 CBV和FBV 三 使用Mixin 四 给视图加装饰器 五 Request对象 六 Response对象 一 Dja ...

  7. Django基础三之路由、视图、模板

    Django基础三之路由.视图.模板 目录 Django基础三之路由.视图.模板 1. Django 请求和返回周期 1.1 路由层之路由匹配 1.2 有名分组 1.3 无名分组 2. 反射解析 3. ...

  8. Python全栈开发【基础三】

    Python全栈开发[基础三]  本节内容: 函数(全局与局部变量) 递归 内置函数 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 def 函数名(参数): ... 函数体 . ...

  9. Bootstrap <基础三十二>模态框(Modal)插件

    模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动.子窗体可提供信息.交互等. 如果您想要单独引用该插件的功能,那么您需要引用  ...

随机推荐

  1. java循环作业0912

    题目一:一张纸的厚度大约是0.08mm,对折多少次之后能达到珠穆朗玛峰的高度(8848.13米)? double a = 0.08; double h =0; int i=0; for(i=1;h&l ...

  2. html 固定长度 超出长度 显示省略号

    a{         width: 80px;/* 要显示文字的宽度 */         float: left;/* 左对齐,不设置的话只在IE下好用 */         overflow: h ...

  3. css的基础用法(下)

    定位: <html> <head> <meta charset="utf-8" /> <title>定位</title> ...

  4. 菜鸟笔记 -- Chapter 6.2.5 代码块

    6.2.5  代码块 在编程过程中我们通常会遇到如下这种形式的程序: package democlass; public class CodeBlock { { System.out.println( ...

  5. cc++面试------17道经典面试题目分析

    以下是C/C++面试题目,共计17个题目,其中涵盖了c的各种基础语法和算法, 以函数接口设计和算法设计为主.这17个题目在C/C++面试方面已经流行了多 年,大家需要抽时间掌握好,每一个题目后面附有参 ...

  6. 汇编:汇编语言实现冒泡排序(loop指令实现)

    ;=============================== ;循环程序设计 ;loop指令实现 ;冒泡排序 ;for(int i=0;i<N;i++){ ; for(int h=0;j&l ...

  7. CentOS 7.4使用yum源安装php7.2

    1.如果之前已经安装我们先卸载一下 yum -y remove php* 2.由于linux的yum源不存在php7.x,所以我们要更改yum源 rpm -Uvh https://dl.fedorap ...

  8. PHP令人困惑的strtotime

    经常会有人被strtotime结合-1 month, +1 month, next month的时候搞得很困惑, 然后就会觉得这个函数有点不那么靠谱, 动不动就出问题. 用的时候就会很慌… 比如:今天 ...

  9. hadoop生态搭建(3节点)-07.hive配置

    # http://archive.apache.org/dist/hive/hive-2.1.1/ # ================================================ ...

  10. python学习之控制流2

    配置环境:python 3.6 python编辑器:pycharm 代码如下: #!/usr/bin/env python #-*- coding: utf-8 -*- # 控制流语句: # if语句 ...