1 虚拟化技术定义
首先援引一段《虚拟化技术发展编年史》中针对虚拟化技术的定义:在计算机科学中,虚拟化技术(Virtualization)是一种资源管理(优化)技术,将计算机的各种物理资源(例如CPU、内存、磁盘空间,以及网络适配器等 I/O 设备)予以抽象、转换,然后呈现出一个可供分割并任意组合为一个或多个(虚拟)计算机的配置环境。虚拟化技术打破了计算机内部硬件实体结构不可分割的物理实体障碍,使用户能够以更灵活、更精细化的配置方式来使用硬件资源,即现下常提到的硬件变的软件"可定义"了。
其实,早在1974 年,Gerald J. Popek(杰拉尔德·J·波佩克)和 Robert P. Goldberg(罗伯特·P·戈德堡)在合作论文《Formal Requirements for Virtualizable Third Generation Architectures》中便已提出了一组称为虚拟化准则的充分条件,又称Popek and Goldberg virtualization requirements,其所述虚拟化系统结构有三个基本满足条件------资源控制(Resource Control)、等价性(Equivalence)、效率性(Efficiency),满足这些条件的控制程序才可以被称为虚拟机监控器(Virtual Machine Monitor,简称 VMM),并首次在此文中提出了两种Hypervisor原型,分别是类型 I虚拟机和类型II虚拟机:
类型 II(寄居或托管型Hypervisor)虚拟机的VMM作为普通应用程序运行在主操作系统上,虽然有利于最大程度屏蔽底层硬件差异,但其运行效率也比类型I低,其排在前面是因为此类型VMM技术更早面世。市面上典型产品包括VMware 5.5以前版本、Xen 3.0以前版本、Virtual PC 2004等。
类型 I(原生或裸机型Hypervisor)虚拟机的VMM则是直接运行在宿主机的硬件上,以此来控制硬件和管理客户机操作系统,此类虚拟机依赖硬件支持,故运行效率也更高,目前市面上主流产品均是此类,例如VMware 5.5及以后版本、Xen 3.0 及以后版本、Virtual PC 2005、KVM。
2 x 86 体系虚拟化技术诞生背景
不过,在1999年VMware的x86虚拟化产品面世以前,虚拟化技术一直都只属于大型机这类高端玩家,PC机领域基本无缘。
当时,CPU为了保证程序代码执行的安全性、多用户的独立性以及操作系统的稳定性,提出了 CPU执行状态的概念。它有效地限制了不同程序之间的数据访问能力,避免了非法的内存操作,同时也避免了应用程序误操作计算机物理设备。
Intel x86架构使用了4个级别来标明不同级别的执行状态权限。最高级别R0实际就是内核态,拥有最高权限,而一般应用程序处于R3状态(即用户态)。在权限约束上,高权限态应用可以阅读低权限态应用的运行内容,例如进程上下文、代码、数据等等,反之则不行。而当时处于一般应用程序等级的VMM,显然无法越级访问只有操作系统内核才能访问的内存、磁盘、鼠键等外围硬件设备中的数据。
而且,当时的Intel x86架构缺乏专门针对虚拟化技术的硬件支持,也就难以直接满足波佩克与戈德堡提出的虚拟化系统架构要求,所以从这两个方面而言,x86架构是一个天然不适合虚拟化的架构。具体而言,当时的x86架构CPU上有17条指令是虚拟化实现的直接阻碍,错误执行这些指令会导致操作系统显示警告、终止应用程序甚至完全崩溃。
VMware最先提供了此问题的解决方案------在虚拟机生成这些特殊指令时将它们"困住",然后将它们转换成可虚拟化的安全指令,同时确保其他指令能不受干扰地执行。如此,便产生了一种与主机硬件匹配并能保证软件完全兼容的高性能虚拟机方案。
这就是第一代纯软件实现的全虚拟化(Full virtualization)方案诞生的背景,VMware首先完成了此方案的商业落地,即1999年推出的企业虚拟化产品VMaware Workstation,并由此一举奠定企业虚拟化解决方案服务商行业龙头的地位。
从此,虚拟化技术进入蓬勃发展期,不论是技术研究深度还是领域扩展广度都得到了大幅延伸,并由此直接推动了第一个云计算时代的到来(针对三个云计算时代的界定可参见笔者在第三期发表的《重识云原生系列第一篇------不谋全局不足以谋一域》)。
3 虚拟化技术发展简史
不过,全软虚拟方案毕竟受限于其纯软件实现的先天性方案缺陷,即需要由软件层的VMM完成大量指令转换,其实际运行性能以及宿主机资源利用效率一直备受诟病。于是人们开始将目光转向硬件,希望通过减少主要处理场景的指令转换、增加硬件直连的执行比例,由此提升虚拟机的整体运行性能。终于,在2003年,英国剑桥大学计算机实验室发布了开源虚拟化项目Xen,标志着虚拟化技术进入第二代-半虚拟化(Para-virtualization)技术时代。
此后,随着微软、Oracle、Redhat、Intel、AMD、思科、惠普等软硬件头部企业的先后进场,虚拟化技术终于来到了基于硬件辅助虚拟技术(Hardware Virtual Machine,简称HVM)的第三代虚拟化技术时代,此标志便是2006年,Intel和AMD相继推出硬件辅助虚拟化方案Intel VT-x与AMD-V,通过引入新的指令和运行模式,省去了二进制指令转换环节,由此大幅提升虚拟机运行性能,顺便将虚拟化方案的演进方向由半虚拟化重新拉回到全虚拟化赛道上来(只是由纯软件虚拟变成了硬件辅助虚拟)。
而到了2007 年,随着Linux Kernel 2.6.20合入虚拟化内核模块KVM(Kernel-based Virtual Machine,由以色列公司Qumranet开发),OS内核虚拟方案进入大众视野。凭借着Linux在企业服务器市场一统天下的地位以及免费开源的技术生态, KVM方案迅速成为当今主流云厂商计算虚拟化方案的事实标准,而KVM实现的前提也是CPU必须支持硬件辅助虚拟技术。
而就在大家以为KVM已经包打天下的时候,Docker的出现又似一次"时空折跃",将虚拟化技术的竞争瞬间带进了云原生的赛道。
此图援引自《虚拟化技术发展编年史》
4 从"软"到"硬"的虚拟化技术
虽然虚拟化技术就是为了将硬件变得"软件可定义化",但技术方案的演进却是一个从"软"到"硬"的过程,接下来我们遵循冯·诺依曼计算机体系模型(即运算器、存储器、控制器、输入设备和输出设备五大部件组成的计算机系统),挨个拆分来看各大部件的虚拟化演进之路,由此也可一窥惊人类似的从"软"到"硬"的技术演进思路。
4.1 CPU虚拟化
在CPU虚拟化方面,上文其实已经详细阐述了,从VMare到Xen,再到KVM,其实主要就是CPU指令处理的虚拟化进程,我们很明显得可以看到,其经历的是全软件虚拟化(Full-virtualization)、半虚拟化(Para-virtualization)、硬件辅助虚拟化(Hardware Virtual Machine,简称HVM)三个过程。
4.2 内存虚拟化
对于内存而言,内存的地址映射与分页机制的实现本身就有类似虚拟化的技术实现------屏蔽底层物理内存地址的不连续性,以连续的虚拟逻辑地址对外(此处特指应用程序)提供服务。
在非虚拟化环境中,虚拟逻辑地址与真实物理地址的映射与转换是通过CPU的MMU(memory management unit)管理单元来实现。
而在虚拟化环境中,由于客户机中的虚拟逻辑地址不能直接用于宿主机真实物理地址的MMU寻址,所以需要先把客户机虚拟逻辑地址GVA(Guest Virtual Address)转换为虚拟机物理地址GPA(Guest Physical Address),再把虚拟机物理地址转换成宿主机上的虚拟逻辑地址HVA(Host Virtual Address),然后运行在宿主机上的VMM再将宿主机虚拟地址HVA最终映射为真正宿主机物理地址HPA (Host Physical Address),以供上层虚拟机使用。显然,此种映射方式,虚拟机的每次内存访问都需要VMM介入,并由软件进行多次地址转换,其效率是非常低的。
为了提高GVA到HPA转换的效率,先后诞生了两种直接转换的实现方案:第一种方案是影子页表(Shadow Page Table)技术,基于软件方式,实现客户机虚拟地址到宿主机物理地址之间的直接转换(KVM虚拟机支持);第二种方案是基于硬件辅助虚拟化对MMU的支持来直接实现两者之间的转换,即Virtualation MMU方案,Intel的EPT(Extent Page Table) 技术和AMD的NPT(Nest Page Table) 技术均是此方案在两家CPU厂商的独立实现。很明显,有了CPU厂商的硬件辅助方案做性能加持,内存的虚拟化才具备真正商业落地的可能性。
4.3 I / O虚拟化
从处理器的角度看,外设是通过一组I/O资源来进行访问的,所以外设相关的虚拟化技术被统称为I/O虚拟化。
从下图可以看到,其实IO虚拟化也是经历了全软虚拟、半虚拟、硬件直通三个阶段:
4.3.1 第一代模拟I/O方案
完全使用软件来模拟,VMM给Guest OS模拟出一个IO设备以及设备驱动,Guest OS要想使用IO设备需要先访问内核,然后通过驱动访问到VMM模拟的IO设备,最后到达VMM模拟设备区域,这是实现方式性能最低。VMware Workstation、Qemu均是此实现思路。
4.3.2 第二代半虚拟化方案
半虚拟化比模拟性能要高,其通过系统调用直接使用I/O设备,与CPU半虚拟化方案类似,VMM给Guest OS提供了特定的驱动程序,使Guest OS自身的IO设备不需要处理IO请求,而是直接发给VMM进行处理,由此提升IO处理性能。典型实现例如Xen、Virtio。
4.3.3 第三种I/O直通方案
I/O直通技术(I/O through)比模拟和半虚拟化性能都好,性能几乎等价于硬件设备直通,但灵活性较差。其实现思路就是提供多个物理I/O设备,如硬盘提供多块、网卡提供多个,然后规划好宿主机上运行的Guest OS数量,通过协调VMM来达到Guest OS与物理设备直接映射绑定的效果。
在当前主流云平台的实现方案中,半虚拟化方案与I/O直通方案因各有明显优劣势,呈一时瑜亮之势,可根据灵活性要求、性能要求选用。
5 后续技术演进展望
上文有提及,就在大家以为KVM已经一统江湖的时候,Docker的出现又将虚拟化技术的竞争带到了云原生的赛道。
Docker容器技术基于依赖自包含的运行标准化设计思想,使人们得以重新站在应用程序的视角(而不是资源视角)来审视虚拟化技术的初衷------构造一个尽可能与底层硬件无关的标准化运行环境,使得软件能一次打包、到处运行,但这个答案并不只有VM(只是在当年软硬件标准化程度相对较低的时代背景下,虚拟化技术成为了当时可见的最佳方案)。
然而云计算发展至今,软硬件厂商在被云"赶着"走上标准化之路之后,基于LXC、cGroup、Namespace等Linux内核隔离技术衍生出的容器技术立马就蜕变成了新时期的更佳解决方案,这是一种比传统虚拟机技术更加轻量、快捷、细粒度的资源虚拟方案。这也是继Linux打败Windows Server、KVM打败VMare之后,开源生态的又一次胜利。当然这也有赖于Linux庞大成熟的开源生态,才能如此迅速地推动容器技术标准的快速发展与成熟。
当然,同时需要指出的是,容器技术发展至今,容器(Container)玩家早已不仅仅只有Docker,还包括Kata container、Rocket container等等。
更进一步,从云计算的角度来说,不论是VMM还是Container都只解决了单机硬件资源的逻辑切分问题,如果要大规模商用,还需要一个大型、至少数据中心级的统一资源调度系统来确保巨量计算资源实例的快速、自动化编排,于是Kubenetes"适时"地出现了。其实,容器早期的选项是Docker Swarm和Apache Mesos,但谷歌担心Docker发展太快、威胁到自己的云计算市场地位,于是将自己内部使用了近十年的编排工具Borg用Go语言重写并做了开源发布,一如当年Android之于智能手机市场,Kubenetes一经推出便将Docker Swarm和Apache Mesos打的溃不成军,K8S一跃成为容器编排领域的行业事实标准。
由此,"Kubenetes+容器"的组合正式宣告了云计算的第三个时代------云原生时代的正式到来。
当然,从目前来看,容器技术依然处在快速发展的早期阶段,依然在重复"用软件方案解决一切问题"的早年虚拟化技术趟过的"老路"。不过,随着容器技术在公有云的大规模商用、大型企业的迅速普及,伴随着各类大规模、高性能场景的导入,其也开始走软硬结合的务实路线,以期通过底层硬件的卸载能力加持,抵消容器层网络、存储资源适配转发的性能损耗,以期早日实现全面替代虚拟机技术的目标。
于是,我们可以看到,大型云厂商的容器网络方案,无一不是直接与云平台的Overlay网络拉平,并通过智能网卡等技术来实现网络流量的硬件卸载,又是一幕"软饭硬吃"的案例重现。
所以说,计算虚拟化这碗看上去已经"够软"的饭,最终还是得由硬件"来吃"。