Docker是近年来新兴的虚拟化工具,它能够和虚拟机同样实现资源和系统环境的隔离。本文将主要根据IBM发表的研究报告,论述Docker与传统虚拟化方式的不一样之处,并比较物理机、Docker容器、虚拟机三者的性能差别及差别产生的原理。 linux
以下图分别是虚拟机与Docker的实现框架。
比较两图的差别,左图虚拟机的Guest OS层和Hypervisor层在Docker中被Docker Engine层所替代。虚拟机的Guest OS即为虚拟机安装的操做系统,它是一个完整操做系统内核;虚拟机的Hypervisor层能够简单理解为一个硬件虚拟化平台,它在Host OS是之内核态的驱动存在的。
虚拟机实现资源隔离的方法是利用独立的OS,并利用Hypervisor虚拟化CPU、内存、IO设备等实现的。例如,为了虚拟CPU,Hypervisor会为每一个虚拟的CPU建立一个数据结构,模拟CPU的所有寄存器的值,在适当的时候跟踪并修改这些值。须要指出的是在大多数状况下,虚拟机软件代码是直接跑在硬件上的,而不须要Hypervisor介入。只有在一些权限高的请求下,Guest OS须要运行内核态修改CPU的寄存器数据,Hypervisor会介入,修改并维护虚拟的CPU状态。
Hypervisor虚拟化内存的方法是建立一个shadow page table。正常的状况下,一个page table能够用来实现从虚拟内存到物理内存的翻译。在虚拟化的状况下,因为所谓的物理内存仍然是虚拟的,所以shadow page table就要作到:虚拟内存->虚拟的物理内存->真正的物理内存。
对于IO设备虚拟化,当Hypervisor接到page fault,并发现实际上虚拟的物理内存地址对应的是一个I/O设备,Hypervisor就用软件模拟这个设备的工做状况,并返回。好比当CPU想要写磁盘时,Hypervisor就把相应的数据写到一个host OS的文件上,这个文件实际上就模拟了虚拟的磁盘。
对比虚拟机实现资源和环境隔离的方案,Docker就显得简练不少。Docker Engine能够简单当作对Linux的NameSpace、Cgroup、镜像管理文件系统操做的封装。Docker并无和虚拟机同样利用一个彻底独立的Guest OS实现环境隔离,它利用的是目前Linux内核自己支持的容器方式实现资源和环境隔离。简单的说,Docker利用namespace实现系统环境的隔离;利用Cgroup实现资源限制;利用镜像实现根目录环境的隔离。
经过Docker和虚拟机实现原理的比较,咱们大体能够得出一些结论:
(1)Docker有着比虚拟机更少的抽象层。因为Docker不须要Hypervisor实现硬件资源虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源。所以在CPU、内存利用率上Docker将会在效率上有优点,具体的效率对比在下几个小节里给出。在IO设备虚拟化上,Docker的镜像管理有多种方案,好比利用Aufs文件系统或者Device Mapper实现Docker的文件管理,各类实现方案的效率略有不一样。
(2)Docker利用的是宿主机的内核,而不须要Guest OS。所以,当新建一个容器时,Docker不须要和虚拟机同样从新加载一个操做系统内核。咱们知道,引导、加载操做系统内核是一个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件须要加载Guest OS,这个新建过程是分钟级别的。而Docker因为直接利用宿主机的操做系统,则省略了这个过程,所以新建一个Docker容器只须要几秒钟。另外,现代操做系统是复杂的系统,在一台物理机上新增长一个操做系统的资源开销是比较大的,所以,Docker对比虚拟机在资源消耗上也占有比较大的优点。事实上,在一台物理机上咱们能够很容易创建成百上千的容器,而只能创建几个虚拟机。docker
在上一节咱们从原理的角度推测Docker应当在CPU和内存的利用效率上比虚拟机高。在这一节咱们将根据IBM发表的论文给出的数据进行分析。如下的数据均是在IBM x3650 M4服务器测得,其主要的硬件参数是:
(1)2颗英特尔xeon E5-2655 处理器,主频2.4-3.0 GHz。每颗处理器有8个核,所以总共有16个核。
(2)256 GB RAM.
在测试中是经过运算Linpack程序来得到计算能力数据的。结果以下图所示:
图中从左往右分别是物理机、Docker和虚拟机的计算能力数据。可见Docker相对于物理机其计算能力几乎没有损耗,而虚拟机对比物理机则有着很是明显的损耗。虚拟机的计算能力损耗在50%左右。
为何会有这么大的性能损耗呢?一方面是由于虚拟机增长了一层虚拟硬件层,运行在虚拟机上的应用程序在进行数值计算时是运行在Hypervisor虚拟的CPU上的;另一方面是因为计算程序自己的特性致使的差别。虚拟机虚拟的cpu架构不一样于实际cpu架构,数值计算程序通常针对特定的cpu架构有必定的优化措施,虚拟化使这些措施做废,甚至起到反效果。好比对于本次实验的平台,实际的CPU架构是2块物理CPU,每块CPU拥有16个核,共32个核,采用的是NUMA架构;而虚拟机则将CPU虚拟化成一块拥有32个核的CPU。这就致使了计算程序在进行计算时没法根据实际的CPU架构进行优化,大大减低了计算效率。安全
内存访问效率的比较相对比较复杂一点,主要是内存访问有多种场景:
(1)大批量的,连续地址块的内存数据读写。这种测试环境下获得的性能数据是内存带宽,性能瓶颈主要在内存芯片的性能上;
(2)随机内存访问性能。这种测试环境下的性能数据主要与内存带宽、cache的命中率和虚拟地址与物理地址转换的效率等因素有关。
如下将主要针对这两种内存访问场景进行分析。在分析以前咱们先概要说明一下Docker和虚拟机的内存访问模型差别。下图是Docker与虚拟机内存访问模型:
可见在应用程序内存访问上,虚拟机的应用程序要进行2次的虚拟内存到物理内存的映射,读写内存的代价比Docker的应用程序高。
下图是场景(1)的测试数据,即内存带宽数据。左图是程序运行在一块CPU(即8核)上的数据,右图是程序运行在2块CPU(即16核)上的数据。单位均为GB/s。
从图中数据能够看出,在内存带宽性能上Docker与虚拟机的性能差别并不大。这是由于在内存带宽测试中,读写的内存地址是连续的,大批量的,内核对这种操做会进行优化(数据预存取)。所以虚拟内存到物理内存的映射次数比较少,性能瓶颈主要在物理内存的读写速度上,所以这种状况Docker和虚拟机的测试性能差异不大;
内存带宽测试中Docker与虚拟机内存访问性能差别不大的缘由是因为内存带宽测试中须要进行虚拟地址到物理地址的映射次数比较少。根据这个假设,咱们推测,当进行随机内存访问测试时这二者的性能差距将会变大,由于随机内存访问测试中须要进行虚拟内存地址到物理内存地址的映射次数将会变多。结果以下图所示。
左图是程序运行在一个CPU上的数据,右图是程序运行在2块CPU上的数据。从左图能够看出,确实如咱们所预测的,在随机内存访问性能上容器与虚拟机的性能差距变得比较明显,容器的内存访问性能明显比虚拟机优秀;但出乎咱们意料的是在2块CPU上运行测试程序时容器与虚拟机的随机内存访问性能的差距却又变的不明显。
针对这个现象,IBM的论文给出了一个合理解释。这是由于当有2块CPU同时对内存进行访问时,内存读写的控制将会变得比较复杂,由于两块CPU可能同时读写同一个地址的数据,须要对内存数据进行一些同步操做,从而致使内存读写性能的损耗。这种损耗即便对于物理机也是存在的,能够看出右图的内存访问性能数据是低于左图的。2块CPU对内存读写性能的损耗影响是很是大的,这个损耗占据的比例远大于虚拟机和Docker因为内存访问模型的不一样产生的差别,所以在右图中Docker与虚拟机的随机内存访问性能上咱们看不出明显差别。服务器
上面两个小节主要从运行在Docker里的程序和运行在虚拟机里的程序进行性能比较。事实上,Docker之因此如此受到开发者关注的另一个重要缘由是启动Docker的系统代价比启动一台虚拟机的代价要低得多:不管从启动时间仍是从启动资源耗费角度来讲。Docker直接利用宿主机的系统内核,避免了虚拟机启动时所需的系统引导时间和操做系统运行的资源消耗。利用Docker能在几秒钟以内启动大量的容器,这是虚拟机没法办到的。快速启动、低系统资源消耗的优势使Docker在弹性云平台和自动运维系统方面有着很好的应用前景。数据结构
前面的内容主要论述Docker相对于虚拟机的优点,但Docker也不是完美的系统。相对于虚拟机,Docker还存在着如下几个缺点:
1.资源隔离方面不如虚拟机,Docker是利用cgroup实现资源限制的,只能限制资源消耗的最大值,而不能隔绝其余程序占用本身的资源。
2.安全性问题。Docker目前并不能分辨具体执行指令的用户,只要一个用户拥有执行Docker的权限,那么他就能够对Docker的容器进行全部操做,无论该容器是不是由该用户建立。好比A和B都拥有执行Docker的权限,因为Docker的server端并不会具体判断Docker cline是由哪一个用户发起的,A能够删除B建立的容器,存在必定的安全风险。
3.Docker目前还在版本的快速更新中,细节功能调整比较大。一些核心模块依赖于高版本内核,存在版本兼容问题。架构
摘自:http://www.linuxidc.com/Linux/2016-05/130991.htm并发