Docker底层的内核知识——cgroups

概述

我的上一篇博客Docker底层的内核知识——namespace讲解了内核中支持Docker作资源隔离的机制namespace。本篇文章主要讲述Docker背后内核的另一机制——cgourps。cgroups不仅可以用来限制被namespace隔离的资源,还可以为资源设置权重、计算使用量、操控任务启停等。

从Linux系统中看cgroups

我们依然先从操作系统中直观的看一下cgroups是个什么东西。
这里写图片描述
进入到sys/fs/cgroup/目录下,我们可以看到许多目录,如上图所见。
这些如blkio、cpu、cpuacct等目录都是cgroups机制的子系统,子系统的概念一会再解释。简单来说,就是这些东西就是对cgroup做资源限制的。blkio负责为块设备设定输入/输出限制,比如物理驱动设备——磁盘。cpu使用调度程序控制任务对cpu的使用,cpuacct自动生成cgroup中任务对CPU资源使用情况的报告。
而正如我们所见,为了让cgroups便于用户理解和使用,也为了用精简的内核代码为cgroup提供熟悉的权限和命名空间管理,内核开发者们按照Linux虚拟文件系统转换器接口实现了一套名为cgroup的文件系统,非常巧妙地用来表示cgroups的层级概念,把各个子系统的实现都封装到文件系统的各项操作中。那么,我们就可以像操作文件一样对cgroups的层级进行浏览和操作管理。除了cgroup文件系统以外,内核没有为cgroups的访问和操作添加任何系统调用,这点与namespace不同,namespace都是通过系统调用来进行操作和管理的。

cgroups的由来

在操作系统中感受了cgroups,下面我们来看看cgroups的由来。
cgroups是由Google的工程师于2006年提出的,最初名为process container。为什么叫这个名字呢?因为刚开始有cgroups的概念时,namespace其实是cgroups的一个子系统,也就是说,cgroups当时还具有资源隔离的功能。不过后来的发展将namespace独立出去了。另外,由于container具有多重含义容易引起误解,就在2007年更名为control groups,并整合进Linux内核,顾名思义就是把任务放到一个组里面加以控制,这个组就是cgroup。

cgroups的官方定义

在这里给出最严谨的官方定义:
cgroups是Linux内核提供的一种机制,这种机制可以根据需求把一系列系统任务及其子任务整合(或分隔)到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架。

关于cgroups的术语

相信大家经常会听人说cgroups或者cgroup。就比如我文章前面,一会提到cgroups,一会提到cgroup,这两个术语之间有什么区别呢?接下来列举关于cgroups的几个术语加以理解:
cgroups:cgroups是Linux内核中的一个机制,我们用它来作容器资源的限制等功能。
cgroup:cgroup中文叫做控制组。它是cgroups实现资源控制的一个基本单位。cgroup表示按某种资源控制标准划分而成的一个任务组。它其中包含有一个或多个任务。
task:前面介绍cgroup时提到的任务就是task。任务表示系统的一个进程或线程。之所以把进程和线程统称为任务,是因为内核本身的调度和管理并没有对进程和线程做区分,只根据clone创建时传入参数的不同从概念上区别进程和线程,所以cgroups中简化称之。
subsystem:cgroups中的子系统。一个子系统就是一个资源调度控制器。比如前面一开始让大家看的cpu、memory、blkio、cpuacct等都是子系统。
hierarchy:中文叫做层级。层级由一系列cgroup以一个树状结构排列而成。每个层级通过绑定对应的子系统进行资源控制。前面一开始看到的目录就是子系统,而这些子系统就挂载着层级。一个层级内创建一个目录就类似于fork一个cgroup,这个cgroup继承了父cgroup的配置属性。当然,后面可以进行配置属性的修改。
语言叙述太苍白,请看实际操作:
这里写图片描述
我们进入cpu子系统的层级下,创建一个目录cgroup1,这个cgroup1就是一个新创建的cgroup控制组,我们可以看下cgroup1中的内容。
这里写图片描述
可以看到cgroup1目录下直接有这么多文件,且和cpu目录下本来存在的文件相同。实际上就是cgroup1继承了根cgroup的配置属性。这个根cgroup是新建层级之时就有的。
我们分别看一下两个目录下cpu.shares的值,会发现它们都是1024。
这里写图片描述

cgroups的作用

我们上面说完了cgroups的一些术语。以后对cgroups的术语就不用傻傻分不清楚了。我们常说cgroups是做资源限制的,而cgroups的功能其实不单单是做资源限制的。接下来我们看一下cgroups具体能干些什么。
cgroups为我们提供了四项功能:
资源限制:cgroups可以对任务使用的资源总额进行限制。如cpu的使用,memory的使用。
优先级分配:通过分配的CPU时间片数量及磁盘IO带宽大小,实际上就相当于控制了任务运行的优先级。
资源统计:cgroups可以统计系统的资源使用量,如CPU使用时长、内存用量等信息,该功能可以用于资源使用的计费。
任务控制:cgroups可以对任务执行挂起、恢复等操作。

子系统简介

前面已经解释过了什么是子系统。这里对子系统再进行详细的讲述,因为一个子系统就是一个资源控制器,每个子系统都独立地控制一种资源。
这里写图片描述
这是我们一开始就看到的图片,接下来我们挑几个重要的子系统再进行解释:
blkio:可以为块设备设定输入/输出限制,比如物理驱动设备。
cpu:使用调度程序控制任务对CPU的使用。
cpuacct:自动生成cgroup中任务对CPU资源使用情况的报告。实际就是记录CPU的使用情况。
cpuset:可以为cgroup中的任务分配独立的CPU和内存。当然,分配独立的CPU的前提是节点是多处理器的。
devices:可以开启或关闭cgroup中任务对设备的访问。
freezer:可以挂起或恢复cgroup中的任务。这就是cgroups的任务控制功能。
memory:可以设定cgroup中任务对内存使用量的限定,并且自动生成这些任务对内存资源使用情况的报告。
perf_event:使用后使cgroup中的任务可以进行统一的性能测试。
net_cls:Docker没有直接使用它,它通过使用等级识别符标记网络数据包,从而允许Linux流量控制程序识别从具体cgroup中生成的数据包。
pids:用来限制cgroup中任务的数量。
hugetlb:支持cgroups限制巨页的使用。

cgroup超出限额的后果

我们都知道cgroup作为一个资源控制的基本单位。那么,当cgroup使用的资源超出了分配的限额会有什么后果呢?
以内存为例,当进程所需的内存超过了它所属的cgroup最大限额时,如果Linux设置了OOM,那么进程会收到OOM信号并结束;否则进程就会被挂起,进入睡眠状态,直到cgroup中其他进程释放了足够的内存资源为止。Docker中是默认开启OOM的。其他子系统的资源限制与此类似。

总结

cgroups相比于namespace解释起来比较复杂,因为要做实际的演示比较难。最直观的了解cgroups就是通过看cgroup文件系统来感受它。(cd /sys/fs/cgroup/)除了cgroup文件系统以外,内核没有为cgroups的访问和操作添加任何系统调用。虽然操作方式不同,cgroups和namespace一个做资源控制,一个做资源隔离。共同成为Docker背后的内核支持机制。

猜你喜欢

转载自blog.csdn.net/hty46565/article/details/80230716