docker 深入理解之cgroups
cgroups 资源限制
cgroups 是什么
cgroups 最初名为process container,有Google工程师Paul Menage和Rohit Seth于 2006 年提出,后由域container有多重含义容易引起误会,就与2007年更名为control groups, 并整合进Linux内核,顾名思义就是把任务放到一个组里面同一管理,cgroups 是Linux内核提供方的一种机制,这种机制可以根据需要把一系列统一任务极其子任务整合(或分隔)到按资源划分等级不同组内,从而为系统资源管理提供一个统一的框架。
cgroups 的四个特点
cgroups的API以一个伪文件系统的方式实现,用户态的程序可以通过文件操作实现cgroups 的组织
cgroups的组织管理操作单元可以细粒到线程级别,另外用户可以创建销毁cgroups,从而实现资源再分配管理
所有资源管理的功能都以子系统方式实现,接口统一
子任务创建之初与其父进程处于同一个cgroups的控制组
cgroups 的作用
实现成功cgroups的主要目的是为不同用户层面的资源管理,提供一个统一化的接口。从单个方面的资源控制到操作系统层面的虚拟化,cgroups提供了四大功能
资源限制 | cgroups可以对任务使用的资源总额进行限制,如设定应用运行时使用的内存上限,一但超过这个配额就发出OOM提示 |
优先级分配 | 通过分配的CPU时间片数量及磁盘IO带宽大小,实际就相当于控制了任务运行的优先级 |
资源统计 | cgroups 可以统计系统的资源使用量,如CPU时长,内存使用量,这个功能非常适用于计费 |
任务控制 | cgroups可以对任务执行挂起 |
过去有一段时间,内核开发者甚至把namespace也作为一个cgroups的子系统加入进来,也就是说cgroups曾经甚至还包括了资源隔离的能力。但资源隔离会给cgroups带来许多问题,如pid namespace加入后,PID在循环出现的时候,cgroups会出现命名冲突、cgroups创建后进入新的namespace导致其他子系统脱离了控制,所以2011年就被移除了
cgroups 术语表
task(任务) | 在cgroups的术语中,任务表示系统的一个进程或者线程 |
cgroups(控制组) | cgroups中的资源控制都以cgroups以单位实现,cgroups表示按某种资源控制标准划分而成的任务组,包含一个或多个子系统,一个任务加入某个cgroups,也可以从某个cgroups签到另一cgroups |
subsystem(子系统) | cgroups中的子系统就是一个资源调度控制器。CPU子系统可以控制从CPU时间分配,内存子系统可以设置cgroups的内存使用量 |
hierarchy(层级) | 层级由一系列cgroups以一个树状结构排列而成,每个层级通过绑定对应的子系统进行资源控制。层级中cgroups的节点可以包含零个节点或多个子节点,子节点继承父节点挂载的子系统。整个操作系统可以有多个层级 |
组织结构与基本规则
传统的Unix任务管理,实际上是先启动init任务作为根节点,在有init创建子任务作为子节点,而每个子节点又可以创建新的子节点,如此往复,形成一个树状结构。而系统中多个cgroups系统也构成类似的树状结构,子节点从父节点继承属性
它们最大的不同在于,系统中的多个cgroups构成的层级并非单根结构,可以允许存在多个。如果任务模型是由init作为根节点构成的一棵树,那么系统中多个cgroups则是由多个层级构成的树林。这样做的目的很好理解,如果只有一个层级,那么所有子任务都将被迫邦定其的所有子系统,这会给某些任务造成不必要的限制。docker中,每个子系统独立构成一个层级,这样易于管理
*规则1:同一个层级可以附加一个或多个子系统,CPU和memory的子系统附加到一个层级
*规则2:一个子系统可以附加到多个层级,当且仅当目标层级只有唯一一个子系统时,小圈中的数字表示子系统附加的时间顺序,CPU子系统附加到层级A的同时不能再附加到层级B,因为层级B已经附加了内存子系统。如果层级B没有过内存子系统,那么CPU子系统同时附加到两个层级是允许的
*规则3:系统每次新建一个层级时,该系统上的所有任务默认加入这个新建的层级的初始化cgroups,这个cgroups也被称为root cgroups。对于创建的每个层级,任务只能存在于其中一个cgroups中,即一个子任务不能存在于同一个层级的不同cgroups中,但一个任务可以存在于可以存在于不同层级的多个cgroups中,如果操作时把一个任务添加到同一个层级中的一个cgroups中,则会将它从第一个cgroups中移除。下面httpd任务已经加入到层级A中的/cg1,而不能加入到同时加入同一个层级中/cg2.但是可以加入层级B中的/cg3
规则4:任务在fork/clone 自身时创建的子任务默认与原来任务在同一个cgroups中,但是子系统允许被移动到不同的cgroups中,即fork/clone 完成后,父子进程在cgroups方面是互不影响的。小圈中数字表示任务出现的时间顺序,当httpd刚fork出另一个httpd时两者在同一个层级中的cgroups中,但随着ID变成4840的httpd需要移到其他cgroups也是可以的,因为父任务间已经独立。一句话就是,初始化子任务时与父任务在同一个cgroups,但是这种关系随后可以改变
子系统介绍
子系统实际是cgroups的资源控制系统,每种子系统独立的控制一种资源,目前docker使用9中子系统,其中net_cls子系统在内核中已经广泛实现,docket尚未采用
blkio | 可以为快设备设定输入\输出限制,如物理驱动设备(磁盘、固态硬盘、USB等) |
CPU | 使用调度程序控制任务对CPU的使用 |
cpuacct | 自动生成cgroups中任务对cpu资源使用情况报告 |
cpuset | 可以为cgroups中的任务分配独立的CPU(针对多处理器系统)和内存 |
devices | 可以开启或者关闭cgroups中任务对设备的访问 |
freezer | 可以挂起或恢复cgroups中任务 |
memory | 可以设定cgroups中任务对内存使用量的限定,并且自动生成这些任务对内存资源的使用情况报告 |
perf_event | 使用后使cgroups的任务可以进行统一的性能测试 |
net_cls | docker没有直接使用它,它通过使用等级识别符标记网络数据包,从而允许Linux流量控制程序识别从具体cgroups中生成的数据包 |
子系统如何使用很重要,但docker并没有对cgroups本身做曾强,容器用户一般已不需要直接操作cgroups,Linux中cgroups的实现形式为一个文件系统,因此需要mount这个文件系统才能使用,挂载成功后,就能看到子系统
[root@mast ~]# mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,pids)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,net_prio,net_cls)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,devices)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,perf_event)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuacct,cpu)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,hugetlb)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,memory)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuset)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,freezer)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,blkio)
查看挂载CPU子系统的控制组下的文件
[root@mast ~]# ls /sys/fs/cgroup/cpu
cgroup.clone_children cgroup.procs cpuacct.stat cpuacct.usage_percpu cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat release_agent
cgroup.event_control cgroup.sane_behavior cpuacct.usage cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release tasks
在/sys/fs/cgroup的CPU的子目录下创建控制组,控制组目录创建后,查看目录
[root@mast ~]# cd /sys/fs/cgroup/cpu
[root@mast cpu]# mkdir cg1
[root@mast cpu]# ls cg1/
cgroup.clone_children cgroup.procs cpuacct.usage cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release
cgroup.event_control cpuacct.stat cpuacct.usage_percpu cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks
设置PID为18828进程cup使用配额
[root@mast cpu]# echo 1404 >> /sys/fs/cgroup/cpu/cg1/tasks
[root@mast cpu]# echo 20000 > /sys/fs/cgroup/cpu/cg1/cpu.cfs_quota_us
cgroups 实现方式及工作原理
cgroups的实现本质上是给任务挂钩子,当任务运行的过程中涉及某种资源时,就会触发钩子上所附带的子系统进行检测,根据资源类别不同,使用对应的技术进行资源限制和优先级分配
cgroups如果判断资源超限及超出后的措施
对于不的系统资源,cgroups提供统一的接口操作对资源进行控制和统计,但限制具体方式不同。内存子系统,会在描述内存状态的“mm struct” 结构体中记录它所属cgroups,当进程需要更多内存时,就会触发cgroups用量检测,用量超过cgroups规定的限额,则拒绝用户的内存申请,否则就给予相应内存并记录在cgroups的统计信息中,实际要比描述的复杂的多,不仅考虑内存的分配与回收,还需考虑不同类型的内存cache和swap等
进程需要所需要的内存超出cgroups最大限额以后,如果设置了OOM Control(内存超额控制),那么进程就手动OOM信号结束;否则进程就会被挂起,进入睡眠状态,直到cgroups中其他进程释放足够的内存资源位置。docker中默认是开启OOM Control的,其他子系统的实现于此类似,cgroups提供了多种资源限制的策略供用户选择。
cgroups与任务之间的关联关系
实际上,cgroups与任务之间是多对多的关系,所以它们不是直接关联,而是通过一个中间结构把双向的关联信息记录下来。每个任务结构体task_struct中都包含一个指针,可以查询到对应的cgroups的情况,同时也可以查到各个子系统状态,这些子系统状态也包含了找到任务的指针,不同类型子系统按照定义本身可以控制信息结构体,最终在自定c义的结构体中把子系统状态指针包含进去,然后通过内核container_of(这个宏可以通过一个结构体的成员找到结构自身)等宏定义来获取对应的结构体,关联到任务,以此达到资源限制的目的。同时为了让cgroups便于让用户理解,也为精简内核代码为cgroups提供熟悉的权限和命名空间管理。内核开发者按照Linux虚拟文件系统转换器(VFS)接口实现统一套名为cgroups的文件系统,非常巧妙的表示cgroups的层级概念,把各个子系统的实现都封装到文件系统的各项操作中。
docker在使用cgroups时注意事项
在实际使用的过程中,docker需要挂载cgroups文件系统新建一个层级,挂载时指定要绑定的子系统。把cgroups文件系统挂载上以后,就可以像操作文件一样对cgroups的层级进行浏览和操作管理(包括权限管理、子系统管理等)。处理cgroups文件系统之外,内核没有为cgroups的访问和操作添加任何系统调用
如果新建的层级结构要绑定子系统与目前已经存在的层级结构完全相同,那么新挂载的会重用已经存在-的那套(指向相同的css_set).否则,如果要绑定的子系统已经被别层级绑定,就会返回挂载失败的错误,如果一切顺利,挂载完成后层级就被激活并与相应的子系统关联起来,可以开始使用了
目前无法讲一个子系统绑定到激活的层级上,或者从一个激活的层级中解除某个子系统的绑定
当一个顶级的cgroups被卸载(umount)时,如果其中创建过深层次的后代cgroups目录,那么上一层的cgroups被卸载,层级也是激活的状态,其后代cgroups的配置依旧有效。只有递归式卸载层级中的所有cgroups,那个层级真正被删除
在创建的层级中创建文件夹,类似于fork了一个子cgroups,子cgroups中默继承父cgroups中的配置属性,但可以根据需求对配置参数进行属性,这样就把一个大的cgroups系统切割成一个个嵌套的、动态变化的“软分区”。
/sys/fs/cgroups/cpu/docker/<container-ID>下文件的作用
一个cgroups创建完成后,不管绑定任何子系统,其目录下都会生成几个文件,用来cgroups的相应信息。
tasks:文件中罗列了所有在该cgroups中任务的TID,即所有进程或者线程的ID,该文件并不保证任务的TID有序,把一个任务的TID写到这个文件里就意味着把这个任务加入到cgroups中,如果这个任务所在的任务组与其不在同一个cgroups中,那么会在cgroups.procs文件里记录一个该文件所在任务组的TGID值,但是该任务组的其他任务并不影响。
cgroups.procs:这个文件罗列出所有在该cgroups中的TGID(线程组ID),即线程组中第一个进程的PID。该文件并保证TGID有序或无序重复,写一个TGID到这个文件意味着就意味着把与其相关的线程加入到这个cgroups中
notify_on_release:填0或1 ,表示是否在cgroups中最后一个任务退出后通知运行releaseagent,默认是0,表示不运行
release_agebt: 指定release agent 执行脚本的文件路径,这个脚本通常用于自动化卸载无用的cgroups
docker 深入理解之cgroups的更多相关文章
- Docker资源管理探秘:Docker背后的内核Cgroups机制
http://www.infoq.com/cn/articles/docker-resource-management-cgroups 随着Docker技术被越来越多的个人.企业所接受,其用途也越来越 ...
- Docker个人理解总结
最新在学习Docker,记录下自己对Docker的理解. 一.Docker是什么? 1. Docker是一个能够把开发的应用程序自动部署到容器的开源引擎. 2.Docker使用Google公司推出的G ...
- 用前端姿势玩docker【一】Docker通俗理解常用功能汇总与操作埋坑
前言 首先一句话表达个人对docker的理解:与传统虚拟技术基于硬件及物理资源的虚拟化相比,Docker更加轻量化,docker为基于操作系统或内核级别的虚拟化,并且提供了从各种机制与操作以满足从开发 ...
- Docker资源限制与Cgroups
一.Linux control groups 简介 Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如 ...
- 初识docker与理解
因最近公司的一个新项目,有一个业务场景是需要给多个甲方的服务器配置运行环境与部署,所以考虑使用docker来实现环境配置的统一 1.docker是什么 docker是一种容器虚拟化技术的实现,相当于在 ...
- Docker入门——理解Docker的核心概念
1 前言 相信不少人听过这么一句话: 人类的本质是复读机. 在软件开发领域也一样,我们总是想寻找更好地方式复制优秀的逻辑或系统.最核心的方法是抽取通用逻辑和组件,把差异化的东西接口化或配置化,达到复用 ...
- docker的理解
作者:刘允鹏链接:https://www.zhihu.com/question/28300645/answer/67707287来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- 关于docker的理解随记
1.容器其实不是什么新技术,说白了就是namespace对资源进行隔离,再加UFS实现分层镜像,以及cgroup实现资源限制.这些技术,都是linux中已有的技术,而且有些技术很早之前就有了. 2.上 ...
- docker 深入理解之namespace
namespace 名称空间 docker容器主要通过资源隔离来实现的,应该具有的6种资源隔 namespace 的六项隔离 namespace 系统调用参数 隔离的内容 UTS CLONE_NEWU ...
随机推荐
- @font-face 用fontsquirrel把ttf文件获取别的文件格式
@font-face是css3的一个模块,但是@font-face这个功能早在IE4就支持了,他主要是把自己定义的Web字体嵌入到你的网页中, @font-face { font-family: &l ...
- HTML 新属性
accesskey 属性 -- 代表链接的快捷键访问方式 定义了accesskey的链接可以使用快捷键(ALT+字母)访问. 主菜单与导航菜单使用accesskey,通常是不错的选择. 取值: 字母 ...
- 【旧文章搬运】对抗RKU的StealthCode检测
原文发表于百度空间,2009-07-02========================================================================== 快一个月没 ...
- 设计模式——模板模式(Template Pattern)
在读Spring源码的时候,发现Spring代码中运用了大量的模板模式,比如根据文件系统目录加载配置文件(FileSystemXmlApplicationContext),类路径加载配置文件(Clas ...
- ASP.NET Core Web API + Angular 仿B站(一) 目的分析以及创建 WebAPI + Angular7 项目
前言: 本系列文章主要为对所学 Angular 框架的一次微小的实践,对 b站页面作简单的模仿. 本系列文章主要参考资料: 微软文档: https://docs.microsoft.com/zh-cn ...
- 洛谷 - P1141 - 01迷宫 - dfs
https://www.luogu.org/problemnew/show/P1141 能互相到达的格子的答案自然是一样的,第一次dfs标记联通块,第二次dfs把cnt传递到整个联通卡并顺手消除vis ...
- PAT团体程序设计天梯赛 - 模拟赛
由于本人愚笨,最后一题实在无力AC,于是只有前14题的题解Orz 总的来说,这次模拟赛的题目不算难,前14题基本上一眼就有思路,但是某些题写起来确实不太容易,编码复杂度有点高~ L1-1 N个数求和 ...
- ionic4+angular7+cordova上传图片
安装插件 安装插件Image Picker $ ionic cordova plugin add cordova-plugin-telerik-imagepicker $ npm install @i ...
- 树的直径初探+Luogu P3629 [APIO2010]巡逻【树的直径】By cellur925
题目传送门 我们先来介绍一个概念:树的直径. 树的直径:树中最远的两个节点间的距离.(树的最长链)树的直径有两种方法,都是$O(N)$. 第一种:两遍bfs/dfs(这里写的是两遍bfs) 从任意一个 ...
- cmd - 批量重命名文件
相信大家或多或少都遇到过类似的情况:从网上下载了好多图片(或者其他的文件),这些图片的名字往往都是些乱七八糟的字母数字的组合,我们想要一次性修改几十张上百张的图片的名字应该怎么办呢? 这里有两种方法, ...