容器本身的价值非常有限,真正有价值的是“容器编排”。
1. 容器,到底是什么?
容器其实就是一种沙盒技术,作为一个“盒子”可以把应用装起来,使得各个应用之间不相互干扰,并且被装进“盒子”的应用,可以很方便地搬来搬去。
1.1 “边界”
容器技术的核心功能,就是通过约束和修改进程的动态表现,为其创造一个边界。
对于Docker等大多数Linux容器来说,Cgroups技术是用来制造约束的主要手段,而Namespace技术是用来修改进程视图的主要方法。
1.1.1 Linux的Namespace机制(容器的隔离)
其实就是对被隔离应用的进程空间动了手脚,使得这些进程只能“看到”重新计算过的PID,比如PID=1,实际上他在Linux中的进程PID是原来的进程PID。
Namespace其实是Linux创建新进程的一个可选参数,通过給创建进程的系统调用clone()指定CLONE_NEWPID参数,这个新创建的进程将会“看到”一个全新的进程空间,它的PID是1,实际上在宿主机中,其PID不是1.
如果执行多次这样的clone()系统调用,这样就是创建多个PID Namespace,每个Namespace中的进程都会认为自己是PID1号进程,它们即看不到宿主机里真正的进程空间,也看不到别的Namespace里的进程空间,从而实现隔离。
实际上,容器进程在创建时,指定了该进程所需要启用的一组Namespace参数。这样容器就只能“看到”当前Namespace所限定的资源、文件、设备、状态或者配置,而对于宿主机以及其他程序,就看不到了。容器其实是一种特殊的进程。
1.1.2 容器的优点与缺点
相比于虚拟机来说,容器的优点是“敏捷”&“高性能”,因为他只是Linux上的一个特殊的进程,不需要消耗额外的资源。
缺点是,多个容器仍然共享同一Linux内核,隔离不彻底;Linux内核中,有很多资源和对象是不能被Namespace化的(比如时间);由于多个容器共享虚拟机内核,容器向应用暴露了相当大的攻击面,应用越狱难度较低。
1.1.3 对于容器的“限制”
虽然已经通过Namespace机制将容器隔离了起来,但是它在宿主机上仍然是一个普通的进程,与其他进程处于同等地位。它会被其他进程抢走资源,也会自己花光资源。
Linux Cgroups就是Linux内核中用来为进程设置资源限制的一个重要功能。它的主要作用就是限制一个进程组能够使用的资源上限,包括CPU,内存,磁盘,网络带宽等等。
它就是一组子系统加上一组资源限制文件的组合,对于Docker来说,只需要在每个子系统下面为每个容器创建一个控制组,在启动容器进程之后,将容器进程的PID填写到对应控制组的tasks文件中即可。
1.1.4 容器的“一致性”
在容器的根目录下挂载一个完整操作系统的文件系统,称之为rootfs(根文件系统)。
由于rootfs的存在,容器才有了一个一个重要特性:“一致性”。有了rootfs之后,打包应用时不只打包了应用,还包括整个操作系统的文件和目录,应用运行所需的所有依赖都被封装在了一起。