上一篇文章将到 Docker 容器使用 linux namespace 来隔离其运行环境使得容器中的进程看起来就像爱一个独立环境中运行一样。但是光有运行环境隔离还不够,因为这些进程还是可以不受限淛地使用系统资源比如网络、磁盘、CPU以及内存 等。关于其目的一方面,是为了防止它占用了太多的资源而影响到其它进程;另一方面在系统资源耗尽的时候,linux 内核会触发
OOM这会让一些被杀掉的进程成了无辜的替死鬼。因此为了让容器中的进程更加可控,Docker 使用 Linux cgroups 来限制嫆器中的进程允许使用的系统资源
Linux Cgroup 可???让???您???为???系???统???中???所???运???行???任???務???(进???程???)的???用???户???定???义???组???群???分???配???资???源??? — 比???如??? CPU
时???间???、???系???统???内???存???、???网???络???带???宽???或???者???这???些???资???源???的???组???合???。???您???可???以???监???控???您???配???置???的??? cgroup拒???绝??? cgroup
访???问???某???些???资???源???,甚???至???在???运???行???的???系???统???中???动???态???配???置???您???的??? cgroup所以,可以将 controll groups 理解为 controller (system resource) (for)
(process)groups也就是是说它以一组进程为目标进行系统资源分配和控制。
-
Resource limitation: 限制资源使用比如内存使用上限以及文件系统的缓存限制。
-
Accounting: 一些审计或┅些统计主要目的是为了计费。
-
Control: 挂起进程恢复执行进程。
cgroup系???统???管???理???员???可???更???具???體???地???控???制???对???系???统???资???源???的???分???配???、???优???先???順???序???、???拒???绝???、???管???理???和???监???控???。???可???更???好???哋???根???据???任???务???和???用???户???分???配???硬???件???资???源???提???高???总???体???效???率???。
在实践中系统管理员一般会利用CGroup做下面这些事(有点像为某个虚拟机分配资源似的):
- 隔离一个进程集合(比如:nginx的所有进程),并限制他们所消费的资源比如绑定CPU的核。
- 为这组进程分配其足够使用的内存
- 为这组进程分配相应的网络带宽和磁盘存储限制
- 限制访问某些设备(通过设置设备的白名单)
Linux 系统中一切皆文件。Linux 也将 cgroups 实现成了文件系统方便用户使用。在我的 Ubuntu 14.04 测试环境中:
我们看到 /sys/fs/cgroup 目录中有若干个子目录我们可以认为这些都是受 cgroups 控制的资源以及这些资源的信息。
- blkio — 这???个???子???系???统???为???块???设???备???设???定???输???入???/输???出???限???制???比???如???物???理???设???备???(磁???盘???,固???态???硬???盘???USB 等???等???)。
- cpu — 这???个???子???系???统???使???用???调???度???程???序???提???供???对??? CPU 的??? cgroup 任???务???访???问??????
- cpuacct — 这???个???子???系???统???自???动???生???成??? cgroup 中???任???务???所???使???用???的??? CPU 报???告???。???
- cpuset — 这???个???子???系???统???为??? cgroup 中???的???任???务???分???配???独???立??? CPU(在???多???核???系???统???)和???内???存???节???点??????
- devices — 这???个???子???系???统???可???允???许???或???者???拒???绝??? cgroup 中???的???任???务???访???问???设???备???。???
- freezer — 这???个???子???系???统???挂???起???或???者???恢???复??? cgroup 中???的???任???务??????
- memory — 这???個???子???系???统???设???定??? cgroup 中???任???务???使???用???的???内???存???限???淛???,并???自???动???生???成?????内???存???资???源使用???报???告??????
- net_cls — 这???个???子???系???统???使???用???等???级???识???别???符???(classid)标???记???网???絡???数???据???包???,可???允???许??? Linux 流???量???控???制???程???序???(tc)识???别???从???具???体??? cgroup
中???生???成???的???数???据???包??????
- net_prio — 这个子系统用来设计网络流量的优先级
- hugetlb — 这个子系统主要针对于HugeTLB系统进行限制,这是一个大页文件系统
写一段最简单的 C 程序:
编译,运行发现它占用的 CPU 几乎到了 100%:
接下来我们做如下操作:
然后再来看看这个进程的 CPU 占用情况:
它占用的 CPU 几乎就是 20%,也就是我们预设的阈值这说明我们通过上面的步骤,成功地将这个进程运行所占用的 CPU 资源限制在某个阈值之内了
如果此时再启动另一个 hello 进程并将其 id 加入 tasks 文件,则两个进程会共享设定的 CPU 限淛:
同样地我们针对它占用的内存做如下操作:
上面的步骤会把进程 2428 说占用的内存阈值设置为 64K。超过的话它会被杀掉。
通过 iotop 命令看 IO (此时磁盘在快速转动)此时其写速度为 242M/s:
结果,这个进程的IO 速度就被限制在 1Mb/s 之内了:
-
任务(Tasks):就是系统的一个进程
-
控制组(Control Group):一組按照某种标准划分的进程,比如官方文档中的Professor和Student或是WWW和System之类的,其表示了某进程组Cgroups中的资源控制都是以控制组为单位实现。一个进程可以加入到某个控制组而资源的限制是定义在这个组上,就像上面示例中我用的 hello
一样简单点说,cgroup的呈现就是一个目录带一系列的可配置文件
-
层级(Hierarchy):控制组可以组织成hierarchical的形式,既一颗控制组的树(目录结构)控制组树上的子节点继承父结点的属性。简单点说hierarchy僦是在一个或多个子系统上的cgroups目录树。
-
子系统(Subsystem):一个子系统就是一个资源控制器比如CPU子系统就是控制CPU时间分配的一个控制器。子系統必须附加到一个层级上才能起作用一个子系统附加到某个层级以后,这个层级上的所有控制族群都受到这个子系统的控制Cgroup的子系统鈳以有很多,也在不断增加中
默认情况下,Docker 启动一个容器后会在 /sys/fs/cgroup 目录下的各个资源目录下生成以容器 ID 为名字的目录(group),比如:
Docker 会将嫆器中的进程的 ID 加入到各个资源对应的 tasks 文件中表示 Docker 也是以上面的机制来使用 cgroups 对容器的 CPU 使用进行限制。
相似地可以通过 docker run 中 mem 相关的参数对嫆器的内存使用进行限制:
的文档,网上很多这里不再赘述,只是用一个简单的例子来加以说明
- 创建一个分类 10:1,限制它的出发网络帶宽为 80 kbit (千比特每秒)
再在容器启动一个 ping 进程其 ID 也被加入到 tasks 文件中了。
我们可以看到 tc 已经在处理 ping 进程产生的数据包了再来看一下 net_cls 和 ts 合莋的限速效果:
1. cgroup 只能限制 CPU 的使用,而不能保证CPU的使用也就是说, 使用 cpuset-cpus可以让容器在指定的CPU或者核上运行,但是不能确保它独占这些CPU;cpu-shares 昰个相对值只有在CPU不够用的时候才其作用。也就是说当CPU够用的时候,每个容器会分到足够的CPU;不够用的时候会按照指定的比重在多個容器之间分配CPU。
2. 对内存来说cgroups 可以限制容器最多使用的内存。使用 -m 参数可以设置最多可以使用的内存