前言

本文主要会介绍笔者在学习Docker的资源限制实现原理时所总结的知识点,其中会涉及到对于CPU资源限制、内存资源限制以及磁盘I/O资源限制等方面的相关内容。 笔者也会将自己的理解在文中进行阐述,这也算是在和大家交流心得的一个过程。若文中有错误的理解和概念,请大家及时纠正;吸纳大家的建议,对于我来说也是很重要的学习过程之一。


(目录)


1.CPU限制

默认情况下,所有的容器可以平等的使用host所提供的CPU资源,并且没有任何限制。

host资源是有限的,一但其上运行的容器过多时,此时就需要为其中的重要容器分配更多的CPU资源以保证其能够正常运转。而对于其他重要性较低的容器,就可以为其设定CPU资源使用上限,保证其不会抢走过多的CPU资源。

1.1 配置方式

在docker run命令中使用-c或--cpu-shares参数来配置容器所能够使用的CPU的额度/权重。

1.2 实现原理

Docker实际上是使用Linux Cgroups中的CPU Subsystem来实现的对CPU资源的限制

注意: 这里介绍的实现原理是基于Linux Cgroups的V1版本。

Docker 会为每个容器在CPU Subsystem中建立一个Control Group,并且将该容器中的所有进程都加入到该cgroup中。之后Docker就可以通过对该cgroup的CPU Subsystem相关参数进行调整来实现对容器进行 CPU 资源的限制了。上述提到的命令中的--cpu-shares参数,实际上就是在配置CPU Subsystem中某个容器所对应的Control Group中参数cpu.shares的值。

Tips: 关于Linux Cgroups CPU Subsystem的相关知识,可以阅读笔者总结的相关文章


2.内存限制

Docker可以限制容器可使用的内存,这里的内存指的是物理内存和SWAP。

2.1 配置方式

在docker run命令中使用-m / —memory参数来限制使用的内存上限;使用--memory-swap限制内存+swap的使用上限。

2.2 实现原理

Docker实际上是使用Linux Cgroups中的Memory Subsystem来实现的对内存资源的限制

注意: 这里介绍的实现原理是基于Linux Cgroups的V1版本。

对于每个容器创建后,Docker都会在Linux Cgroups的Memory Subsystem中建立一个Control Group,并将容器中的所有进程都加入到这个cgroup中。之后Docker就可以通过对该cgroup的Memory Subsystem相关参数进行调整来实现对容器进行内存资源的限制了。上述提到的命令中的-m / --memory参数实际上配置的是一个Memory Subsystem中的memory.limit_in_bytes的值。而其他的参数同理,都可以在Memory Subsystem中找到对应的配置参数。

Tips: 关于Linux Cgroups Memory Subsystem的相关知识,可以阅读笔者总结的相关文章


3.磁盘I/O限制

Linux上的磁盘读写模式分为两种: direct I/O和buffered I/O,Docker会针对这两种模式分别有不同的限制措施。

3.1 direct I/O模式

Docker对于direct I/O模式下的磁盘读写能做到权重和磁盘读写速率两种资源限制方式。

3.1.1 block I/O权重

默认情况下,所有容器能平等的读写磁盘。通过在docker run命令中添加参数--blkio-weight来改变容器在block I/O中的优先级,权重默认为500。这种方式可以实现对多个容器使用磁盘资源的限制需求

3.1.2 磁盘读写速率

Docker支持对每一个容器的IOPS和BPS(吞吐量)来进行限制。通过在docker run命令中添加参数--device-read/write-bps和--device-read/write-iops来实现容器磁盘读写速率的限制。在配置参数时,需要指定相应的物理磁盘的主次设备号。这种方式可以实现对单一容器读写磁盘速率的限制需求

3.1.3 实现原理

对于direct I/O模式资源限制,实际上是利用Linux Cgroups V1版本中的blkio Subsystem来实现的

与其他类型的资源相同,Docker都会在blkio Subsystem中建立一个Control Group,并将容器中的所有进程都加入到这个cgroup中。之后Docker就可以通过对该cgroup的blkio Subsystem相关参数进行调整来实现对容器进行存储资源的限制了。在docker run命令添加的相应参数实际上就是block I/O Cgroup中的相关参数,即实际上就是在配置blkio Subsystem的相关参数。

Tips: 关于Linux Cgroups blkio Subsystem的相关知识,可以阅读笔者总结的相关文章

3.2 buffered I/O模式的资源限制

由于Linux Cgroup v1版本中的block I/O Cgroup无法针对buffered I/O模式进行磁盘资源的相关限制。 因此需要使用Linux Cgroup v2版本中的I/O Subsystem来实现此需求


4.文件系统使用量限制

注意:此章节所关注的是对于文件系统使用量的限制,即目录可用空间这类资源的限制;而非磁盘读写相关的资源限制

对于一个容器,其所使用的文件系统可分为两类:

  1. 将数据写到容器自身的文件系统内 即写入overlayFS中
  2. 挂载相应的data volume 将数据写入volume中

其中,由于overlayFS中的upperdir实际上就是host上文件系统中对应的目录,并且data volume实际上也是host上文件系统中对应的目录;所以无论容器将数据写入到哪种类型的目录中,实际上最后还是都会存储到host上的文件系统内。基于上述这个特性,那么对于容器的文件系统使用量限制,就可以通过对host的文件系统的使用量进行限制来变相实现了。

Tips: 关于overlayFS的相关知识,可以阅读笔者总结的相关文章中的部分章节。

这里笔者提供一个实现思路供大家参考:

  1. 确认容器所使用的数据存放在host文件系统中的哪个目录内 如果容器使用的是data volume,那么就是data volume所绑定的那个目录。如果容器使用的是自身的overlayFS,那么需要先找到overlayFS中的upperdir所绑定的host目录。

  2. 确认限制配置方式 限制资源的配置方式与host上所使用的文件系统息息相关。因此需要先确认host使用使用的文件系统,然后获取到该文件系统对于目录数据使用量的限制方法。

  3. 实现配置 依据前两个步骤的结果,对指定的目录进行使用量的限制。