Hypervisor的演化史及未来展望【图文】
在本文中,我们将首先概述在 20 世纪 70 年代发明的经典陷入 - 模拟(trap-and-emulate )的Hypervisor架构,然后讲述从上世纪 70 年代一直发展到现在云计算时代的Hypervisor技术脉络,最后我们来看看影响Hypervisor设计的未来趋势。
(作者注:本文的灵感来自于Anthony Liguori为AWS的Nitro项目所做的演讲,这也是我极力推荐的,任何对Hypervisor和云基础设施感兴趣的人都应该看看这个视频。)
架构
Hypervisor是一组系统软件,能够提供虚拟机(VM),以供用户来运行他们自己的操作系统和应用程序。Hypervisor提供虚拟机之间的隔离技术,从而使得这些虚拟机彼此独立运行成为可能,而且这些虚拟机可以运行不同的操作系统,和其它的虚拟化技术一样,Hypervisor也提供多租户的实现,从而简化了虚拟机的提供和管理。
目前人们诟病Hypervisor的一个主要原因,是其相比于诸如容器这样的虚拟化技术,显得有点太过繁重(Morabito et al., 2015)。然而,技术从来都不是一成不变的,Hypervisor本身也是在进化的,Hypervisor也可以是非常轻量级的(Manco et al., 2017),而且可以让运行在Hypervisor中的客户操作系统非常的轻量级(Madhavapeddy, 2013)。
Hypervisor可以分解为两部分: 虚拟机监视器 (VMM) 和设备模型。VMM 响应设置虚拟机和掌控由客户操作系统执行诸如I/O访问的特权指令引发的陷阱(即虚拟机出口),设备模型,负责实现所有设备(如网卡,存储设备等)的 I/O 接口。Hypervisor的体系结构如下图所示:
(术语Hypervisor和VMM经常可以互换,但是,更为严谨的说法是Hypervisor 由VMM和设备模型组成。)
虚拟机监视器 (VMM)
VMM必须满足三个属性(Popek and Goldberg, 1973):
等价性:程序执行在裸机和VMM下具有相同的可观察行为,时间和资源的可用性可不算在内,这两点是因为共享物理硬件而难以保证。
效率:大多数程序指令直接在物理CPU上执行,而不是通过Hypervisor的介入。
资源控制:VMM管理着所有的硬件资源,虚拟机需要Hypervisor的许可方能直接访问硬件。
作为一个侧面说明,值得注意的是,仿真器同时满足等价性和资源控制,但不满足效率。Linux内核所实现的KVM子系统,(当然其它操作系统也将 KVM 移植了),就为实现VMM而提供了构建块,KVM子系统实际上是对CPU硬件虚拟化功能的一种友好的抽象,它能够被诸如QEUM这样的用户态应用很好的利用,从而实现VMM的功能以及一个全栈的Hypervisor。
设备模型
若要实现设备模型,就需要I/O虚拟化,而对于I/O虚拟化的实现来说则有两种模式:基于软件和硬件辅助。
基于软件的I/O虚拟化的实现是能够让多个虚拟机可以共享同一个物理设备的软件I/O接口。基于软件的I/O虚拟化的具体实现则可以有多个后端,举例来说,一个基于软件的存储设备既可以基于块设备,也可以基于文件系统。当然,这种实现的方式的缺陷就是所有的vCPU使用的都是同一个CPU资源,这会降低CPU的可用能力,并会引起抖动。
硬件辅助的I/O虚拟化则是在硬件层实现了I/O接口,此方法需要硬件能够支持多个虚拟机可共享访问物理设备。SRV-IO是PCI的扩展,其允许将物理的 PCI功能分割为多个虚拟的PCI功能。
演化
在上世纪 70 年代,VMM的陷入 - 模拟模式被得到了正式的认可(Popek and Goldberg, 1973),但直到 90 年代中期才流行起来,用于在多核的机器上运行商业操作系统(Bugnion et al., 1997)。然而,当年最受欢迎的机器架构是英特尔的 X86,是没有虚拟化功能的,因为其在一些特权声明没有陷入(trap)功能。
在 1999 年,一家叫做VMware的公司做了一款Hypervisor, 它的目标就是在 X86下运行虚拟化。但是它实现的方式是使用二进制翻译,而不是指令的陷入,同时仍然直接在物理CPU上运行无特权的指令,解决了x86的虚拟化问题(Adams and Agesen, 2006),这使得VMware虚拟机管理程序可以在虚拟机的 x86 硬件上运行未修改的商业操作系统,而不会影响性能。
在 2003 年,又出现了叫做Xen的Hypervisor,它使用了完全不同的方法来解决X86的虚拟化问题,放弃了二进制翻译的做法,而是修改了客户操作系统的源代码来陷入到Hypervisor 中,以代替执行非陷入特权指令。
随后,英特尔和AMD分别在 2005 和 2006 年先后发布了带有虚拟化扩展的 X86架构的CPU,这又使得经典的陷入 - 模拟模式成为了可能。而且又一项技术出现了,那就是KVM,最初是为Linux而开发的,其作为Linux内核的一个子系统,与QEMU的设备模式协作,共同构成了完整的Hypervisor。最初,KVM项目提供的基于软件的设备模式从而模拟完整的硬件设备,后来又引入了virtio机制,从而实现了半虚拟化I/O设备模型。
未来
Hypervisor经历如此多年的广泛应用及发展,已经通过了考验,但是我们也要考虑其在未来发展的一些趋势和可能。
硬件虚拟化: 正在变得越来越广泛,比如,亚马逊的Nitro项目 就将非传统的设计带入到了Hypervisor的设计当中,它将所有的基于软件的设备模型都替换掉了,如此文所指示的,全部采用了硬件虚拟化,亚马逊的Nitro Hypervisor还利用Linux KVM重新定制了一套VMM。
操作系统 :同样也在发展,以能跟上Hypervisor的步伐。Unikernel就是一个非常有意思的项目,它将内核和应用打包在一起,运行在相同的CPU保护级别(Madhavapeddy, 2013),没有使用传统上讲内核和用户空间之间分离的做法,这样减少了上下文切换和系统调用的开销,虽然会损失一些操作系统的功能。Unikernel的基本思想可以追溯到早期的程序库操作系统,相对于裸金属,Hypervisor的设备模式更加的简单,这就使得此想法在现实世界中更加的可行。
轻量级虚拟化: 随着云计算的日益普及,轻量级虚拟化技术也日益被重视起来。容器就是提供轻量级虚拟化的一项卓越技术。但是,容器无法做到像虚拟机那样的完全隔离,而且由于容器是共享一个主机操作系统,而且可以访问绝大多数的操作系统系统调用接口,所以会导致各种安全问题(Manco et al., 2017)。而相对于Hypervisor则没有那么多的安全问题(Manco et al., 2017),如果减低对VMM的等价性要求,其实 unikernels 可以提供更好的优化Hypervisor (Williams, 2016)。
Serverless计算:是一种新兴的技术模式,更准确的描述是功能即服务,它允许应用程序开发人员将功能而不是应用程序部署到托管平台。Serverless 计算的一个方法是使用Hypervisor和unikernel来打包和部署这些功能(Koller and Williams, 2017)。
能源效率:是Hypervisor设计的另外一个重要的未来方向。到 2030 年作为通信技术的一部分,云计算将会占到全球电力损耗的 20%,在最糟糕的情况下,甚至可达到 50%(Andrae and Edler, 2015)。Hypervisor 的能源开销可能会非常的高,具体当然是取决于具体的工作负载。其中有实验证明 KVM的能源开销在 59% 到 273% 之间(Jin et al., 2012)。
内核旁路网络:近来被凸显的一个热门技术,原因是随着网卡变得越来越快,传统的TCP/IP和POSIX套接字开始不能满足需求(Han et al., 2012; Young et al., 2014; Yasukata et al., 2016)。Hypervisor采用I/O半虚拟化的技术有效的解决了网络数据路径的问题,但是也引入了一层抽象,而这又会增加网络的开销。在Linux中,有人提出采用vhost架构 来解决此问题,Vhost的运行原理是将virtuali的半虚拟化I/O设备模型从QEMU(VMM的用户态空间)迁移到了主机内核(即和KVM模块在内核态),这就消除了网络从内核到用户态之间的切换。还有一种技术的实现是Hypervisor实现内核旁路网络,通过使用硬件网卡虚拟化来显现,即Arrakis项目(Peter et al., 2014)。
总结
Hypervisors是上世纪 70 年代所发明的技术,将近 50 年的时间,验证了其实用性,X86的架构特点只能意味着第一个成功的Hypervisor不得不借助于二进制翻译来处理特权指令。二进制翻译之后又演化出半虚拟化(由Xen得到了很大的推广),再之后则是英特尔和AMD为x86架构增加了虚拟化的扩展,从而实现了Hypervisor整合到了经典的模式。
尽管近年来容器技术成为炙手可热的虚拟化技术,甚至像诸如serverless这样的新兴计算模式更是让Hypervisor再度成为有吸引力的技术,轻量级Hypervisor的设计、unikernels、以及硬件辅助虚拟化,所有这些都在减少Hypervisor 的开销,这一切都使得Hypervisor 相对容器更具竞争力。