浅谈Linux Cgroups机制

来源:浅谈Linux Cgroups机制 - 知乎 (zhihu.com)

1. Cgroups简介

1.1 功能和定位

Cgroups全称Control Groups,是Linux内核提供的物理资源隔离机制,通过这种机制,可以实现对Linux进程或者进程组的资源限制、隔离和统计功能。

比如可以通过cgroup限制特定进程的资源使用,比如使用特定数目的cpu核数和特定大小的内存,如果资源超限的情况下,会被暂停或者杀掉。

Cgroup是于2.6内核由Google公司主导引入的,它是Linux内核实现资源虚拟化的技术基石,LXC(Linux Containers)和docker容器所用到的资源隔离技术,正是Cgroup。

1.2 相关概念介绍

  • 任务(task): 在cgroup中,任务就是一个进程。
  • 控制组(control group): cgroup的资源控制是以控制组的方式实现,控制组指明了资源的配额限制。进程可以加入到某个控制组,也可以迁移到另一个控制组。
  • 层级(hierarchy): 控制组有层级关系,类似树的结构,子节点的控制组继承父控制组的属性(资源配额、限制等)。
  • 子系统(subsystem): 一个子系统其实就是一种资源的控制器,比如memory子系统可以控制进程内存的使用。子系统需要加入到某个层级,然后该层级的所有控制组,均受到这个子系统的控制。

概念间的关系:

  • 子系统可以依附多个层级,当且仅当这些层级没有其他的子系统,比如两个层级同时只有一个cpu子系统,是可以的。
  • 一个层级可以附加多个子系统。
  • 一个任务可以是多个cgroup的成员,但这些cgroup必须位于不同的层级。
  • 子进程自动成为父进程cgroup的成员,可按需求将子进程移到不同的cgroup中。

cgroup关系图如下:

img

两个任务组成了一个 Task Group,并使用了 CPU 和 Memory 两个子系统的 cgroup,用于控制 CPU 和 MEM 的资源隔离。

1.3 子系统

  • cpu: 限制进程的 cpu 使用率。
  • cpuacct 子系统,可以统计 cgroups 中的进程的 cpu 使用报告。
  • cpuset: 为cgroups中的进程分配单独的cpu节点或者内存节点。
  • memory: 限制进程的memory使用量。
  • blkio: 限制进程的块设备io。
  • devices: 控制进程能够访问某些设备。
  • net_cls: 标记cgroups中进程的网络数据包,然后可以使用tc模块(traffic control)对数据包进行控制。
  • net_prio: 限制进程网络流量的优先级。
  • huge_tlb: 限制HugeTLB的使用。
  • freezer:挂起或者恢复cgroups中的进程。
  • ns: 控制cgroups中的进程使用不同的namespace。

1.4 cgroups文件系统

Linux通过文件的方式,将cgroups的功能和配置暴露给用户,这得益于Linux的虚拟文件系统(VFS)。VFS将具体文件系统的细节隐藏起来,给用户态提供一个统一的文件系统API接口,cgroups和VFS之间的链接部分,称之为cgroups文件系统。

比如挂在 cpu、cpuset、memory 三个子系统到 /cgroups/cpu_mem 目录下

mount -t cgroup -o cpu,cpuset,memory cpu_mem /cgroups/cpu_mem

关于虚拟文件系统机制,见浅谈Linux虚拟文件系统机制

2. cgroups子系统

这里简单介绍几个常见子系统的概念和用法,包括cpu、cpuacct、cpuset、memory、blkio。

2.1 cpu子系统

cpu子系统限制对CPU的访问,每个参数独立存在于cgroups虚拟文件系统的伪文件中,参数解释如下:

  • cpu.shares: cgroup对时间的分配。比如cgroup A设置的是1,cgroup B设置的是2,那么B中的任务获取cpu的时间,是A中任务的2倍。

  • cpu.cfs_period_us: 完全公平调度器的调整时间配额的周期。

  • cpu.cfs_quota_us: 完全公平调度器的周期当中可以占用的时间。

  • cpu.stat 统计值

    • nr_periods 进入周期的次数
    • nr_throttled 运行时间被调整的次数
    • throttled_time 用于调整的时间

2.2 cpuacct子系统

子系统生成cgroup任务所使用的CPU资源报告,不做资源限制功能。

  • cpuacct.usage: 该cgroup中所有任务总共使用的CPU时间(ns纳秒)
  • cpuacct.stat: 该cgroup中所有任务总共使用的CPU时间,区分user和system时间。
  • cpuacct.usage_percpu: 该cgroup中所有任务使用各个CPU核数的时间。

通过cpuacct如何计算CPU利用率呢?可以通过cpuacct.usage来计算整体的CPU利用率,计算如下:

# 1. 获取当前时间(纳秒)
tstart=$(date +%s%N)
# 2. 获取cpuacct.usage
cstart=$(cat /xxx/cpuacct.usage)
# 3. 间隔5s统计一下
sleep 5
# 4. 再次采点
tstop=$(date +%s%N)
cstop=$(cat /xxx/cpuacct.usage)
# 5. 计算利用率
($cstop - $cstart) / ($tstop - $tstart) * 100

2.3 cpuset子系统

适用于分配独立的CPU节点和Mem节点,比如将进程绑定在指定的CPU或者内存节点上运行,各参数解释如下:

  • cpuset.cpus: 可以使用的cpu节点
  • cpuset.mems: 可以使用的mem节点
  • cpuset.memory_migrate: 内存节点改变是否要迁移?
  • cpuset.cpu_exclusive: 此cgroup里的任务是否独享cpu?
  • cpuset.mem_exclusive: 此cgroup里的任务是否独享mem节点?
  • cpuset.mem_hardwall: 限制内核内存分配的节点(mems是用户态的分配)
  • cpuset.memory_pressure: 计算换页的压力。
  • cpuset.memory_spread_page: 将page cache分配到各个节点中,而不是当前内存节点。
  • cpuset.memory_spread_slab: 将slab对象(inode和dentry)分散到节点中。
  • cpuset.sched_load_balance: 打开cpu set中的cpu的负载均衡。
  • cpuset.sched_relax_domain_level: the searching range when migrating tasks
  • cpuset.memory_pressure_enabled: 是否需要计算 memory_pressure?

2.4 memory子系统

memory子系统主要涉及内存一些的限制和操作,主要有以下参数:

  • memory.usage_in_bytes # 当前内存中的使用量
  • memory.memsw.usage_in_bytes # 当前内存和交换空间中的使用量
  • memory.limit_in_bytes # 设置or查看内存使用量
  • memory.memsw.limit_in_bytes # 设置or查看 内存加交换空间使用量
  • memory.failcnt # 查看内存使用量被限制的次数
  • memory.memsw.failcnt # - 查看内存和交换空间使用量被限制的次数
  • memory.max_usage_in_bytes # 查看内存最大使用量
  • memory.memsw.max_usage_in_bytes # 查看最大内存和交换空间使用量
  • memory.soft_limit_in_bytes # 设置or查看内存的soft limit
  • memory.stat # 统计信息
  • memory.use_hierarchy # 设置or查看层级统计的功能
  • memory.force_empty # 触发强制page回收
  • memory.pressure_level # 设置内存压力通知
  • memory.swappiness # 设置or查看vmscan swappiness 参数
  • memory.move_charge_at_immigrate # 设置or查看 controls of moving charges?
  • memory.oom_control # 设置or查看内存超限控制信息(OOM killer)
  • memory.numa_stat # 每个numa节点的内存使用数量
  • memory.kmem.limit_in_bytes # 设置or查看 内核内存限制的硬限
  • memory.kmem.usage_in_bytes # 读取当前内核内存的分配
  • memory.kmem.failcnt # 读取当前内核内存分配受限的次数
  • memory.kmem.max_usage_in_bytes # 读取最大内核内存使用量
  • memory.kmem.tcp.limit_in_bytes # 设置tcp 缓存内存的hard limit
  • memory.kmem.tcp.usage_in_bytes # 读取tcp 缓存内存的使用量
  • memory.kmem.tcp.failcnt # tcp 缓存内存分配的受限次数
  • memory.kmem.tcp.max_usage_in_bytes # tcp 缓存内存的最大使用量

2.5 blkio子系统 - block io

主要用于控制设备IO的访问。有两种限制方式:权重和上限,权重是给不同的应用一个权重值,按百分比使用IO资源,上限是控制应用读写速率的最大值。

按权重分配IO资源:

  • blkio.weight:填写 100-1000 的一个整数值,作为相对权重比率,作为通用的设备分配比。
  • blkio.weight_device: 针对特定设备的权重比,写入格式为 device_types:node_numbers weight,空格前的参数段指定设备,weight参数与blkio.weight相同并覆盖原有的通用分配比。

按上限限制读写速度:

  • blkio.throttle.read_bps_device:按每秒读取块设备的数据量设定上限,格式device_types:node_numbers bytes_per_second。
  • blkio.throttle.write_bps_device:按每秒写入块设备的数据量设定上限,格式device_types:node_numbers bytes_per_second。
  • blkio.throttle.read_iops_device:按每秒读操作次数设定上限,格式device_types:node_numbers operations_per_second。
  • blkio.throttle.write_iops_device:按每秒写操作次数设定上限,格式device_types:node_numbers operations_per_second

针对特定操作 (read, write, sync, 或 async) 设定读写速度上限

  • blkio.throttle.io_serviced:针对特定操作按每秒操作次数设定上限,格式device_types:node_numbers operation operations_per_second
  • blkio.throttle.io_service_bytes:针对特定操作按每秒数据量设定上限,格式device_types:node_numbers operation bytes_per_second

3. cgroups的安装和使用

测试环境为 ubuntu 18.10

3.1 cgroups的安装

  1. 安装 cgroups
sudo apt install cgroup-bin

安装完成后,系统会出现该目录/sys/fs/cgroup

  1. 创建cpu资源控制组,限制cpu使用率最大为50%
$ cd /sys/fs/cgroup/cpu
$ sudo mkdir test_cpu
$ sudo echo '10000' > test_cpu/cpu.cfs_period_us
$ sudo echo '5000' > test_cpu/cpu.cfs_quota_us
  1. 创建mem资源控制组,限制内存最大使用为100MB
$ cd /sys/fs/cgroup/memory
$ sudo mkdir test_mem
$ sudo echo '104857600' > test_mem/memory.limit_in_bytes

3.2 将进程加入到资源限制组

测试代码test.cc如下:

#include <unistd.h>
#include <stdio.h>
#include <cstring>
#include <thread>

void test_cpu() {
    printf("thread: test_cpu start\n");
    int total = 0;
    while (1) {
        ++total;
    }
}

void test_mem() {
    printf("thread: test_mem start\n");
    int step = 20;
    int size = 10 * 1024 * 1024; // 10Mb
    for (int i = 0; i < step; ++i) {
        char* tmp = new char[size];
        memset(tmp, i, size);
        sleep(1);
    }
    printf("thread: test_mem done\n");
}

int main(int argc, char** argv) {
    std::thread t1(test_cpu);
    std::thread t2(test_mem);
    t1.join();
    t2.join();
    return 0;
}

1. 编译该程序

g++ -o test test.cc --std=c++11 -lpthread

2. 观察限制之前的运行状态

img

3. 测试cpu的限制

cgexec -g cpu:test_cpu ./test

cpu使用率降低了一半。

img

除了使用 cgexec 限制进程外,还可以通过将进程号加入到 cgroup.procs 的方式,来达到限制目的。

4. 总结

本文简单介绍了Cgroups的概念和使用,通过Cgroups可以实现资源限制和隔离。在实际的生产环境中,Cgroups技术被大量应用在各种容器技术中,包括docker、rocket等。

这种资源限制和隔离技术的出现,使得模块间相互混部成为可能,大大提高了机器资源利用率,这也是云计算的关键技术之一。

5. 参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343