Docker提供了一种打包机制,这种机制打包了应用运行所需要的整个操作系统,从而保证了本地环境和云端环境的高度一致。避免了用户通过”试错“来匹配两种不同运行环境之间差异的痛苦过程。
”编排“(Orchestration)主要指用户如何通过某些工具或者配置来完成一组虚拟机以及关联资源的定义、配置、创建、删除等工作,然后由云计算平台按照这些指定的逻辑来完成的过程。
基于Kubernetes API和扩展接口的二次创新工作:
- 微服务治理项目Istio
- 有状态部署框架Operator
- 像Rook这样的开源项目,通过Kubernetes的可扩展接口,把ceph这样的重量级产品封装成了简单易用的容器存储插件
用clone()系统调用创建一个新进程时,可以在参数中指定CLONE_NEWPID参数。这时,新创建的这个进程将会”看到“一个全新的进程空间,在这个进程空间里,它的PID是1。之所以说”看到“,是因为这只是一个“障眼法”,在宿主机真实的进程空间里,这个进程的PID还是真实的数值,比如100。当多次执行上面的clone()调用,这样就会创建多个PID Namespace,而每个Namespace里的应用进程,都会认为自己是当前容器里的第一号进程,它们既看不到宿主机里真正的进程空间,也看不到其他PID Namespace里的具体情况。
除了用到了PID Namespace,Linux 操作系统还提供了Mount、UTS、IPC、Network和User这些Namespace,用来对各种不同的进程上下文进行“障眼法”操作。比如Mount Namespace用于被隔离进程只看到当前Namespace 里的挂载点信息,Network Namespace用于被隔离进程看到当前Namespace里的网络设备和配置。
Docker容器实际上就是扎起创建容器进程时,指定了这个进程所需要启动的一组Namespace参数。这样,容器就只能“看”到当前Namespace所限定的资源、文件、设备、状态或者配置。而对于宿主机以及其他不相关的程序,它就完全看不到了。
所以,容器就是一种特殊的进程而已!
虚拟机和容器对比图
Hypervisor通过硬件虚拟化功能,模拟除了与逆行一个操作系统所需要的各种硬件,比如CPU、内存、I/O设备等。然后在这些虚拟的硬件上安装了一个新的操作系统,即Guest OS。
进程会觉得自己是各自PID Namespace里的第一号进程,只能看到各自Mount Namespace里挂载的目录和文件,只能访问到各自Network Namespace里的网络设备,就仿佛运行在一个个“容器里面”与世隔绝。
Namespace技术实际上修改了应用进程看待整个计算机“视图”,即它的“视图”被操作系统做了限制,只能“看到”某些指定的内容。
为什么Docker项目比虚拟机更受欢迎?
使用虚拟化技术作为应用沙河,就必须要由Hypervisor来负责创建虚拟机,这个虚拟机是真实存在的,并且它里面必须运行一个完整的Guest OS才能执行用户的应用进程,这就不可避免地带来了额外的资源消耗和占用。根据实验,一个运行着CentOS的KVM虚拟机启动后,在不做优化的情况下,虚拟机自己就需要占用100~200MB内存。此外,用户应用运行在虚拟机里面,它对宿主机操作系统的调用就不可避免地要经过虚拟化软件的拦截和处理,这本身又是一层性能损耗,尤其对计算资源、网络和磁盘I/O的损耗很大。相比之下,容器化后的用户应用,却依然还是一个宿主机上的普通进程,这就意味着这些因为虚拟化而带来的性能损耗都是不存在的;而另一方面,使用Namespace作为隔离手段的容器并不需要单独的Guest OS,这就使得容器额外的资源占用几乎可以忽略不计。
“敏捷”和“高性能”是容器相较于虚拟机最大的优势
但Linux Namespace也有“隔离不彻底”的缺点。
容器只是运行在宿主机上的一种特殊进程,多个容器之间使用的还是同一个宿主机的操作系统内核。
这就意味着,你要在Windows宿主机上运行Linux容器,或者在低版本的Linux宿主机上运行高版本的Linux容器,都是行不通的。在Linux内核中有很多资源和对象是不能被Namespace化的,最典型的例子就是:时间
除了CPU子系统外,Cgroups的每一个子系统都有其独有的资源限制能力,比如:
- blkio,为块设备设定I/O限制,一般用于磁盘等设备
- cpuset,为进程分配单独的CPU核和对应的内存节点
- memory,为进程设定内存使用限制
Cgroups就是一个子系统目录加上一组资源限制文件的组合。
对于Docker来说,只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的PID填写到对应控制组的tasks文件中就可以了,比如:
docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash