隔离的问题
之前我们做的Demo都没有使用限制,这个时候我们使用stats命令来看下整体资源的使用情况;
docker stats
这个时候我们可以看到容器是可以使用到宿主机的所有的资源,这也是基于Linux Namespace的隔离机制相比于虚拟化技术的不足之处,就是对资源的隔离不够彻底,当一个宿主机上运行多个容器的时候,容器是共享宿主机的CPU和内存,这个时候如果某XX程序写了一个内存溢出的程序部署到容器中,这个时候就会影响到同一台宿主机的其他容器,那么对于这个问题我们该如何解决?
Cgroups
Linux Cgroups的全称是Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等等。这种机制可以根据需求把一系列系统任务及其子任务整合(或分隔)到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架。简单说,Cgroups 可以限制、记录任务组所使用的物理资源。本质上来说,Cgroups 是内核附加在程序上的一系列钩子(hook),通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的。也就是说开发者可以通过 Cgroups 提供的精细化控制能力,限制某一个或者某一组进程的资源使用。
Cgroups的主要作用
实现 Cgroups 的主要目的是为不同用户层面的资源管理提供一个统一化的接口。从单个任务的资源控制到操作系统层面的虚拟化,Cgroups 提供了四大功能:
-
资源限制:Cgroups 可以对进程的资源总额进行限制;
-
优先级分配:通过分配的 CPU 时间片数量和磁盘 IO 带宽,实际上就等同于控制了任务运行的优先级;
-
资源统计:Cgroups 可以统计系统的资源使用量,比如 CPU 使用时长、内存用量等;
-
任务控制:Cgroups 可以对任务执行挂起、恢复等操作;
Cgroups文件系统探索
在Linux中,Cgroups给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的/sys/fs/cgroup路径下,我们可以通过 mount 命令来查看 Cgroups 默认的挂载点:
mount | grep cgroup
输出的结果是一系列文件系统目录(如果你在自己的机器上没有看到这些目录,那你就需要自己去挂载Cgroups)。
让我们来使用ll命令看一下 /sys/fs/cgroup目录下包含哪些子目录,
ll /sys/fs/cgroup
在/sys/fs/cgroup目录包括cpuset、cpu、 memory这样的子目录,这些都是我这台机器当前可以被Cgroups进行限制的资源种类,接下来我们深入到memory的子目录下看下该目录下都有什么:
这些文件就是 Cgroups 的 memory 子系统中的根级设置。比如 memory.limit_in_bytes 中的数字用来限制进程的最大可用内存,memory.swappiness 中保存着使用 swap 的权重等等。既然 Cgroups 是以这些文件作为 API 的,那么我就可以通过创建或者是修改这些文件的内容来限制进程的资源,接下来我们就来在展示下如何使用Cgroups。
如何使用Cgroups
该案例是限制进程可以用的CPU
-
在 /sys/fs/cgroup/cpu目录下新建一个名称为limit_cpu的目录;
#进入对应的目录 cd /sys/fs/cgroup/cpu #新建文件夹 mkdir limit_cpu
-
查看新建文件的目录,我们可以发现系统已经帮我们自动创建的以下目录,也就是说明了Cgroups 的文件系统会在创建文件目录的时候自动创建这些配置文件;
cd limit_cpu/ ls
-
我们通过配置将CPU周期限制为总量的十分之一;
#设置CPU period的周期的100ms(100000 us),该值也是默认的值 echo 100000 > cpu.cfs_period_us #设置CPU的配额为10ms(10000 us),这样就是为总量的十分之一 echo 10000 > cpu.cfs_quota_us
-
切换/usr/local目录下,新建cputime.c文件,编写如下相加程序;
#切换目录 cd /usr/local #新建文件 touch cputime.c #编辑文件 vim cputime.c void main(){ unsigned int i, end; end = 1024 * 1024 * 1024; for(i = 0; i < end; ) { i ++; } }
-
编译程序
gcc cputime.c -o cputime
-
使用不同的CPU限制,对比执行时间执行时间,通过对比我们可以发现限制的CPU使用时间大概是我们不使用限制下的时间的10倍,说明我们限制是生效的;
#CentOS系统需要安装libcgroup-tools包,才有cgroup配置命令 yum install -y libcgroup-tools.x86_64 #无限制下的CPU执行时间 time ./cputime #使用limit_cpu限制下的CPU执行时间 time cgexec -g cpu:limit_cpu ./cputime
总结一下,Linux Cgroups 就是一个子系统目录加上一组资源限制文件的组合。
Docker限制探究
使用
使用如下命令启动,看到--cpu-period和--cpu-quota相信你会感到熟悉,这不是和我们上面使用限制CPU时候的参数配置基本上是一样,这个时候我们怀疑Docker的限制可能使用Cgroups的技术,接下来我们就探究下是不是这样的。
docker run -it -d --cpu-period=100000 --cpu-quota=20000 --memory 1000M --name limitcentos centos:latest
我们使用docker stats查看docker资源使用情况,会发现limitcentos的内存以及被限制到1000M了。
docker stats
原理探究
通过参数我们猜测可能Docker的限制可能使用Cgroups的技术,验证的最好的办法就是去找下Cgroups的目录结构,接下来我们分别看CPU的目录是否存在docker的限制。
进入Cgroups的cpu目录,我们会发现拖多出docker的目录;
cd /sys/fs/cgroup/cpu
ls
进入docker目录,看到蓝色部分我们会想到docker启动成功以后返回一串字符串,确实蓝色部分就是代表Docker,最后那张图是limitcentos启动后返回的,可以看到他们是一致的;
进入limitcentos的对应的目录,我们会发现其目录和CPU限制的是基本一致的;
image.png
接下来我们查看下cfs_period_us和cfs_quota_us的内容是否和docker启动的参数一致,经过验证发现是一致的;
#查看周期
cat cpu.cfs_period_us
#查看限制
cat cpu.cfs_quota_us
image.png
经过demo验证,证实了Docker的限制就是使用Cgroups的技术。