互联网技术 / 互联网资讯 · 2023年12月3日 0

Docker原理:Cgroups简介

在许多接触Docker的朋友中,提到cgroups这一术语时,往往会有一些困惑。这是Linux中一项历史悠久的技术,旨在实现资源限制,例如CPU和内存等方面的控制。然而,许多人发现这一技术的理解有一定难度。

本文的目的在于以最简单、直观的方式帮助你理解cgroups的基本概念。

5分钟了解Docker原理之二,最简单的Cgroups介绍!

cgroups作为Docker功能实现的重要基础设施,通过将操作系统中的各种资源汇聚成池子,允许用户通过配置来获取所需资源。

那么,这项技术是如何运作的呢?

首先要了解cgroups这个词,它由两部分组成:第一部分“c”代表Control,表示控制;第二部分“groups”则表明这是一个组。

1. 控制的目标

Control的对象是什么呢?除了CPU和内存,还有哪些资源?

通过使用Mount命令,我们可以查看系统支持的限制目标,这些目标被称为子系统。

不同系统版本之间可能存在一些细微差异,但通常子系统的分类包括:

CPU、cpuacct、cpuset、blkio、devices、net_cls、net_prio、freezer、ns和hugetlb等。

虽然内容繁杂,但我们主要关注的还是内存和CPU,这些细节不会影响我们对其设计原则的理解。

接下来,我们以CPU为例,探讨子系统的实际应用。

2. CPU使用限制的示例

首先,我们进入CPU子系统目录。

cd /sys/fs/cgroup/cpu

然后,创建一个名为xjjdog的cgroups,这个名称就是控制组。

mkdir xjjdog

此时,奇妙的事情发生了。使用ll命令查看xjjdog目录的内容,会发现系统已为我们生成了一系列文件。

通过调整这些文件中的数值,我们便可以对资源进行限制。例如,向cpu.cfs_quota_us文件写入100000(十万),表示使用xjjdog的控制组最多只能使用1个CPU核;若写入20000,则表示最多使用1/5个CPU核。

这是因为cpu.cfs_period_us这个配置文件默认将1个CPU分为10万份。

我们来尝试写入20000。

sudo echo 20000 > xjjdog/cpu.cfs_quota_us

接下来,将当前Shell的PID加入被控制进程列表。

echo $$ > xjjdog/tasks

执行完后,启动一个死循环。

while true; do ;; done;

重新打开一个Shell,使用top命令监视CPU的使用率。可以观察到,死循环最多只使用了20%的CPU,保持在20%以下,并在各个CPU之间切换。

5分钟了解Docker原理之二,最简单的Cgroups介绍!

依次执行以下命令,可以发现CPU的使用量逐步增加,大致上与我们的设定相符。

sudo echo 40000 > xjjdog/cpu.cfs_quota_us
sudo echo 60000 > xjjdog/cpu.cfs_quota_us
sudo echo 100000 > xjjdog/cpu.cfs_quota_us

对于其他资源的限制,思路也是类似的。最重要的是理解像cpu.cfs_quota_us这样的术语所代表的含义。查看手册可以轻松掌握这些概念。例如,quota意为配额,显然是用来限制资源使用。

5分钟了解Docker原理之二,最简单的Cgroups介绍!

如图所示,子系统可以控制多个任务,将其纳入控制组之中。我们在前文提到,可以将bash进程作为Docker系统的主进程,而该主进程的子进程也将共享相同的限制配置。

3. 组的含义

简单来说,group是指对各种资源进行分组。不同名称的资源会有不同的隔离配置,但它还有更多特性。

最重要的一点是其层级关系(Hierarchy)。这一点也较易理解,主要是为了简化配置。

例如,前文提到的xjjdog目录对CPU的限制为0.5核。如果我想创建另一个应用,对CPU使用限制为0.5核,同时限制内存为1GB,只需在xjjdog目录下创建xjjdog0目录,并仅配置内存方面的限制即可。

此外,如果在外层的CPU限制为2核,而在继承的目录中限制为1/5核,那么它的实际使用只能是操作系统的2/5核,这也是继承特性的一种体现。

cgroups诞生于2006年,由Google的工程师(Rohit Seth和Paul Menage)发起。2008年,该技术成功合并至Linux 2.6.24版本,可以说是一项较为古老的技术。如今,cgroups已成为systemd、Docker、Linux Containers(LXC)等技术的基础。

值得一提的是,Windows平台的WSL并不具备cgroups功能,通过Mount命令可验证这一点,因而无法支持Docker的运行,虽然WSL2已克服了这一限制。

许多朋友对Docker的发展状况感到担忧,但当你熟悉这些底层原理,并阅读完容器的标准后,就会发现,无论是使用Docker还是containerd,上层实现都是相似的。