转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。
上次咱们说到PaaS的发展历史,从Cloud Foundry黯然退场,到Docker加冕,正是Docker“一点点”的改进,掀起了一场蝴蝶效应,煽动了整个PaaS开源项目市场风起云涌。程序员
为了让你们更好的理解“容器”这个PaaS中最核心的技术,本篇将从一个进程开始,为你们讲述容器究竟是什么,Cloud Foundry等PaaS“前浪”是如何实现容器的。docker
以Linux操做系统为例,计算机里运行的进程是程序执行以后,从磁盘的二进制文件,到内存、寄存器、堆栈指令等等所用到的相关设备状态的一个集合,是数据和状态综合的动态表现。而容器技术的目标就是对一个进程的状态和数据进行的隔离和限制。能够说,容器的本质其实就是Linux中的一个特殊进程。这个特殊的进程,主要靠Linux系统提供的两个机制来实现,这里先回顾一下。网络
Linux Namespace是Linux内核的一项功能,该功能对内核资源进行分区,以使一组进程看到一组资源,而另外一组进程看到另外一组资源。该功能经过为一组资源和进程具备相同的名称空间而起做用,可是这些名称空间引用了不一样的资源。资源可能存在于多个空间中。此类资源的示例是进程ID,主机名,用户ID,文件名以及与网络访问和进程间通讯相关的某些名称。其种类列举以下:函数
在Linux操做系统中,PID==1的进程被称为超级进程,它是整个进程树的root,负责产生其余全部用户进程。全部的进程都会被挂在这个进程下,若是这个进程退出了,那么全部的进程都被 kill。工具
刚才咱们提到了隔离和限制,具体指的是什么呢?开发工具
以Docker为例(Cloud Foundry同理,个人机器上没有安装后者),咱们能够执行下列的命令建立一个简单的镜像:
$ docker run -it busybox /bin/shgoogle
这条语句执行的内容是:用docker运行一个容器,容器的镜像名称叫busybox,而且运行以后须要执行的命令是/bin/sh,而-it参数表示须要使用标准输入stdin和分配一个文本输入输出环境tty与外部交互。经过这个命令,咱们就能够进入到一个容器内部了,分别在容器中和宿主机中执行top命令,能够看到如下结果:spa
(在容器内外执行top语句的返回结果)操作系统
从中能够发现,容器中的运行进程只剩下了两个。一个是主进程PID==1的/bin/sh超级进程,另外一个是咱们运行的top。而宿主机中的其他的全部进程在容器中都看不到了——这就是隔离。线程
(被隔离的top进程,图片来自网络)
本来,每当咱们在宿主机上运行一个/bin/sh程序,操做系统都会给它分配一个进程编号,好比PID==100。而如今,咱们要经过Docker把这个/bin/sh程序运行在一个容器中,这时候,Docker就会在这个PID==100建立时施加一个“障眼法”,让他永远看不到以前的99个进程,这样运行在容器中的程序就会当本身是PID==1的超级进程。
而这种机制,其实就是对被隔离的程序的进程空间作了手脚,虽然在容器中显示的PID==1,可是在本来的宿主机中,它其实仍是那个PID==100的进程。所使用到的技术就是Linux中的Namespace机制。而这个机制,其实就是Linux在建立进程时的一个可选参数。在Linux中,建立一个线程的函数是(这里没写错就是线程,Linux中线程是用进程实现的,因此能够用来描述进程):
int pid = clone(main_function, stack_size, SIGCHLD, NULL);
若是咱们给这个方法添加一个参数好比CLONE_NEWPID:
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
那么这个新的进程就会看到一个全新的进程空间,在这个空间里,由于该空间中仅有这一个进程,因此它本身的PID就等于1了。
这样一个过程就是Linux容器最基本的隔离实现了。
光有namespace隔离的容器就和没有电脑的程序员同样,是残缺不全的。
若是咱们只隔离不限制,笼子里面的程序照样占用系统资源,访问依旧自由。为了给有了隔离性的程序添加资源限制,就用到了第二个技术:cgroups
cgroups原本是google的工程师在2006年开发的一个程序,全称是Linux Control Group,是Linux操做系统中用来限制一个进程组能使用资源的上限,包括CPU、内存、磁盘、网络带宽等的功能。
经过Cgroups给用户暴露的API文件系统,用户能够经过修改文件的值来操做Cgroups功能。
(被cgroup限制的进程,图片来自网络)
在Linux系统(Ubuntu)中能够执行如下命令查看CgroupsAPI文件:
mount -t Cgroups
(cgroup文件系统)
从上图能够看到,系统中存在包括cpu、内存、IO等多个Cgroups配置文件。
咱们以CPU为例来讲明如下Cgroups这个功能。对CPU的限制须要引入两个参数cfs_period和cfs_quota,咱们为了给活字格公有云Docker内的程序限制CPU时,会常常操做这两个参数。这两个参数是组合使用的,意思是在长度为cfs_period时间内,程序组只能分到总量为cfs_quota的CPU时间。也就是说cfs_quota / cfs_period == cpu使用上限。
要想限制某个进程的CPU使用,能够在/sys/fs/Cgroups/cpu目录下,执行如下命令建立一个文件夹container:
/sys/fs/Cgroups/cpu/ > mkdir container
此时,咱们能够发现系统自动在container目录下生成的一系列CPU限制的参数文件,这是Linux系统自动生成的,表示咱们成功为CPU建立了一个控制组container:
(默认的CPU资源文件列表)
为了展现CPU限制的实际效果,让咱们执行一个用如下脚本建立的死循环:
while : ; do : ; done &
咱们在top命令结果中会看到返回的进程为398,由于死循环,cpu占用率为100%:
(死循环的进程占了100% CPU)
这时,咱们再看下container目录下的cpu.cfs_quota_us和cpu.cfs_period_us:
(默认状况下CPU的限制参数)
这里是没有作过限制时的样子。cfs_quota_us为-1说明并无限制CPU的运行上限。如今咱们改一下这个值:
echo 20000 > /sys/fs/Cgroups/cpu/container/cpu.cfs_quota_us
而后将以前的进程398写入这个控制组的tasks文件中:
echo 398 > /sys/fs/Cgroups/cpu/container/tasks
这时再top一下,发现刚才的死循环的CPU使用率变成20%了,CPU使用资源限制开始生效。
(使用cgroup限制CPU使用量的死循环进程)
以上,就是经过Cgroups功能对容器作限制的原理了。同理,咱们能够用此方法,对一个进程的内存、带宽等作限制,若是这个进程是一个容器进程,一个资源受控的容器基本就能够展示在你面前了事实上,在云时代的早期,Cloud Foundry等“前浪”都是采用这种方式建立和管理容器。相比于后来者,Cloud Foundry等在容器的隔离和限制上,虽相对简单、易于理解,但在一些场景下不免会受到制约。
这里要作一个特别的说明,只有Linux中运行的容器是经过对进程进行限制模拟出来的结果,Windows和Mac下的容器,都是经过Docker Desktop等容器软件,操做虚拟机模拟出来的“真实”的虚拟容器。
本节从容器的原理和Linux下实现容器隔离和限制的技术入手,介绍了在云时代早期Cloud Foundry等Paas平台的容器原理。下一节将继续为你们介绍Docker在Cloud Foundry容器基础之上又作了什么改动,是如何解决Cloud Foundry致命短板的。
若是您想了解Docker如何搅动风云,Docker的这个容器又和传统虚拟机有何区别?
敬请期待下篇,咱们继续唠。