Docker原理之限制篇 ---CGroups资源限制

简介

CGroups的全称叫做 control groups,是由Google首创,并被合入Linux内核的一种资源限制机制。使用CGroups可以将一系列任务极其子任务整个到资源划分等级不同的组内,从而管理系统资源。通俗讲,CGroups可以限制和记录任务组所使用的物理资源(包括CPU、Memory、IO等)。
CGroups对外以伪文件系统的方式提供API,用户态程序可以操作对应的文件以达到对CGroups的控制,其对于操作的单元可以细粒度到线程级别。需要注意的是,当父任务创建完子任务后,子任务依然处于父任务的CGroups组中。

功能

CGroups主要提供了以下四大功能:

  1. 资源限制:CGroups可以针对任务使用的资源总额进行限制
  2. 优先级分配:通过对CPU时间片、IO带宽等的限制,达到了控制任务优先级的目的
  3. 资源统计:提供资源使用量的统计功能,例如CPU的使用时长、mem的占用量等
  4. 任务控制:CGroups可以针对任务进行挂起、恢复等。

概念

CGroups提供了非常强大的资源控制能力,当然,其相关概念也比较多,本节主要介绍CGroups涉及的概念,以及基本含义。本节对后边的内容相当重要,一定要熟悉相关概念。

task(任务)

表示CGroups中的一个任务,该任务可以是线程,也可以是进程。

subsystem(子系统)

CGroups中对于某种资源的调度控制器,例如CPU子系统,控制CPU时间片的分配;mem子系统,控制cgroup对于内存的使用量等。在Linux中,子系统主要有以下9种组成(不同内核版本看到的种类数可能不同):

  1. blkio:对于块设备输入输出的限制
  2. cpu:控制对于CPU的使用
  3. cpuacct:自动生成cgroup中任务对CPU资源使用情况的报告
  4. cpuset:可以为cgroup中任务分配独立的CPU和内存
  5. devices:开启或关闭cgroup中任务对设备的访问
  6. freezer:挂起或回复cgroup中的任务
  7. memory:设定cgroup中任务对内存使用量的限定,并自动生成资源使用情况报告
  8. perf_event:cgroup中任务可进行统一性能测试
  9. net_cls:通过等级标识标记网络数据包,从而允许流量控制程序识别从cgroup中生成的数据包
  10. net_prio:可以使用CGroup控制流量的优先级
  11. pids:限制任务的数量
cgroup(控制组)

在CGroups中,所有的控制都是以控制组为单位实现的,表示将某种或某些资源按照某种控制标准进行划分而成的任务组,包含一个或多个subsystem。一个task可以加入某个cgroup,也可以从某个cgroup迁移到另一个cgroup。

hierarchy(层级)

由一系列cgroup以树状结构排列而成,每个层级通过绑定对应的子系统进行资源控制。层级中的cgroup节点可以包含零个或多个自己诶点,子节点继承父节点挂载的子系统。

组织规则

cgroups的主要由以下四大规则进行组织

规则1

同一层级可以附加一个或多个子系统,例如一个层级中,可以附加cpu子系统,也可以附加mem子系统。

规则2

当且仅当目标层级只有一个子系统时,一个子系统可以附加到多个层级上。例如:层级A上拥有CPU子系统,层级B上拥有mem子系统时,CPU子系统无法再添加到层级B上;如果层级B上没有mem子系统时,CPU子系统可以附加于层级B上。

规则3

系统新建一个层级时,该系统上所有任务默认加入该新层级的初始化cgroup中,这个cgroup被称为root cgroup。对于创建的每个层级,任务只能存在于其中一个cgroup中,即一个任务不能存在于同一个层级的不同cgroup中,但一个任务可以存在于不同层级中的多个cgroup中。

规则4

任务在fork、clone自身时创建的子任务默认与父任务在同一个cgroup中,但子任务允许被移动到不同cgroup中。

实操

本节利用限制cpu使用率的例子,理解CGroups的简单使用。本节主要使用Linux命令行对文件进行操作,在程序中,我们可以使用程序提供的文件操作函数来对CGroup进行操作。

查看挂载

通过 mount | grep cgroup 命令查看cgroup的挂载
在这里插入图片描述

第一行显示的是cgroup的文件系统类型为tmpfs(内存中的临时文件系统);第二行表示systemd对cgroup的支持,systemd可以通过相关命令来控制进程;其余各行就是cgroups对应的子系统挂载目录。

挂载cgroups

通过 mount -t cgroup 命令挂载cgroup后,即可看到对应的子系统挂载目录
在这里插入图片描述在这里插入图片描述

限制CPU

在操作限制CPU的实验之前,我们先编写一个消耗CPU高的程序,用来实验。

#include <stdlib.h>

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

  while(1){
     for(int i = 0 ;i<100;i++);
  }

  return EXIT_SUCCESS;
}

编译运行上述程序,并使用top命令查看其CPU占比
在这里插入图片描述在这里插入图片描述
从图中可以看到,不一会CPU占用就飙升到了100%。我们先看下对应进程所属的cgroup(输入 cat /proc/[pid]/cgroup即可)
在这里插入图片描述
我们看到,对应的cgroup都是 / 。此时,我们进入cpu子系统的cgroup目录,创建新的cgroup名为cg1
在这里插入图片描述
进入cg1 cgroup后,我们ls后看到有很多文件,这里重点介绍两个我们限制cpu使用时用到的文件,其他文件大家有兴趣可以自行查阅相关资料。

  • cpu.cfs_period_us:用来设置一个CFS调度时间周期长度,默认值是100000us(100ms),一般cpu.cfs_period_us作为系统默认值我们不会去修改它。
  • cpu.cfs_quota_us:用来设置在一个CFS调度时间周期(cfs_period_us)内,允许此控制组执行的时间。默认值为-1表示没有限制时间。
  • cgroup.procs:需要加入该cgroup的进程号

对于cpu.cfs_period_us和cpu.cfs_quota_us之间的关系再多做一点解释:

cpu.cfs_quota_us / cpu.cfs_period_us = 需要的CPU核数

例如:

  • cpu.cfs_quota_us = 50000
  • cpu.cfs_period_us = 100000
    则,该表明cgroup需要 0.5 核 CPU

通过上边的理论支撑,我们如果要将上述程序的CPU使用率限制在50%,则需要分三步操作:

  1. 先cat cpu.cfs_period_us查看当前CFS的调度周期长度
  2. echo cpu.cfs_quota_us 写入允许此控制组执行的时间为cpu.cfs_period_us的二分之一
  3. 将进程号echo进 cgroup.procs

在这里插入图片描述在这里插入图片描述
执行完上述操作后,我们可以看到,CPU的使用率已经被限制在了50%左右。
在日常的使用中,除了上述 cpu.cfs_quota_us 和 cpu.cfs_period_us 外,还有一个非常重要的文件是 cpu.shares,他是用来设置cpu子系统对于不同cgroup之间的cpu分配比例

例如,A cgroup 设置需要 4 个 CPU (cpu.cfs_quota_us/cpu.cfs_period_us = 4 ),B cgroup 也设置需要4个CPU,假设当前宿主机有16核CPU,则A和B都可以跑满4个CPU,即当CPU资源充足时,各自都可跑满设置的CPU核数。但是在CPU资源紧张的情况下,这个时候需要通过 cpu.shares 设置的比例来判断CPU分配的个数。例如还是上边的例子,假设此时宿主机只有4个CPU,A的cpu.shares为1024,B的cpu.shares 为 3072,他俩的比值为1:3,这个时候如果A满负荷运行,B不占用CPU或休眠,则A依然可以获得4个CPU。但是,如果此时A和B都需要满负荷运行,则A只能获得1个CPU,B可以获得3个CPU。

cpu.shares在生产环境最广泛的应用就是用来解决宿主机CPU资源紧张时优先保障核心业务或在线业务,主动降级非核心业务或离线业务。例如:我们可以将核心业务的cpu.shares设置为10240,将离线业务的cpu.shares设置为1024,则在资源紧张情况下,可以最大程度保障核心服务拿到CPU时间片的概率。

总结

CGroups是内核提供的一种资源限制机制,对用户态程序以伪文件系统的方式提供操作API,虽然概念繁多,但是我们通过对于cpu限制的实操,简单了解了CGroups的使用方法,也算是入门了CGroups这门技术。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值