剖析系统虚拟化(4)- VMware ESX 架构

Sina WeiboBaiduLinkedInQQGoogle+RedditEvernote分享




 

上篇文章已经向大家介绍了VMware vSphere,而本篇将继续把重点放在vSphere身上,并向介绍大家vSphere之核心ESX的架构,虽然关于ESX架构的公开资料较少,但是基于这些已公开的资料,并加上我的一些实际经验,我觉得还是能对ESX的架构有一个大致的描述,下图为ESX的架构:

ESX Server Architecture

图1. ESX的架构图(点击可看大图)(参【2】)

ESX主要可被分为两部分:其一是用于提供管理服务的Service Console,其二是ESX的核心,也是主要提供虚拟化能力的VMKernel。

Service Console

简单的来说,Service Console就是一个简化版Redhat Enterprise OS。虽然其不能实现任何虚拟化功能,但是对这个ESX架构而言,它却是一个不可分割的一部分。主要有五个方面功能:

  1. 启动VMKernel,当ESX主机启动的时候,首先会启动Service Console,接着在Linux runlevel 3上启动VMKernel,之后将全部硬件资源的管理权移交给VMKernel。当VMKernel启动成功之后Service Console就成为运行VMKernel上面的第一个虚拟机。
  2. 提供各种服务接口,比如命令行,Web接口,SDK接口等,并安装VirtualCenter Agent以支持很多需要和Virtual Center配合的高级服务,比如,vMotion和DRS等。
  3. 性能检测,因为所有VMkernel的性能数据都会记录在Service Console的/proc目录下,所以不仅能够通过脚本来处理这些性能数据,而且还能使用Service Console自带的ESXTOP命令来观测。
  4. 认证,Service Console提供多种认证机制。
  5. 负责主机部分硬件的管理,比如,鼠标,键盘,显示屏和CD-ROM等等。

注:虽然Service Console提供了许多功能,但因为其本身资源所限的原因(关于这点,我曾经和一位VMware工程师有过聊天,好像整个Service Console大概只能占有280MB内存和少量的I/O),所以不适合在Service Console中执行一些重量级的任务,比如:上传或者复制虚拟磁盘(Virtual Disk)。

VMKernel

VMKernel是由VMware开发的基于POSIX协议的操作系统,它提供了很多在其它操作系统中也能找到的功能,比如,创建和管理进程,信号(Signal),文件系统和多线程等。但它是为运行多个虚拟机而“度身定做”的。它的核心功能是资源进行虚拟化。下面将通过CPU,内存和I/O这三个方面,来讲解VMKernel是如何实现虚拟化的。

CPU

在CPU方面,ESX使用了在第二篇提到的两个全虚拟化技术:优先级压缩(Ring Compression)和二进制代码翻译(Binary Translation)。

优先级压缩,指的是为了让VMKernel获得所有物理资源的控制权,比如CPU。这就需要让VMKernel运行在Ring 0,在其上面的虚拟机内核代码是运行在Ring 1,而虚拟机的用户代码只能运行在Ring 3上。这种做法不仅能让VMKernel安全地控制所有的物理资源,而且能让VMKernel截获部分在虚拟机上执行的特权指令,并对其进行虚拟化。

二进制代码翻译,虽然上面的优先级压缩这个技术已经处理了很多特权指令引发的异常情况,但是由于X86架构在初始设计方面并没有考虑到虚拟化这个需求,所以有很多X86特权指令成了优先级压缩的漏网之鱼,虽然通过传统的Trap-Emulation技术也能处理这些指令,但是由于其不仅需要花时间观测有潜在影响的指令,而且还要监视那些非常普通的指令,导致Trap-Emulation的效率非常低,所以VMware引进了二进制代码翻译这个技术,这个技术能让那些非常普通的指令直接执行,不干涉,并提供接近物理机的速度,但会扫描并修改那些有嫌疑的代码,使其无法对虚拟机造成错误的影响。由于大多数代码都不属于有嫌疑的,所以二进制代码翻译的效率远胜Trap-Emulation。还有经过VMware长达十年的调优,使得二进制代码翻译这个技术越发优秀。

接下来,谈一下的VMware的二进制代码翻译技术的特点:

  1. 纯二进制:二进制翻译器的输入和输出都是二进制的X86代码,而不是文本形式的源代码。
  2. 动态:二进制代码只会在运行时翻译,翻译器会在生成代码之间进行串联。
  3. 随需应变:只有在代码即将执行时翻译,这样只有代码才会被翻译,从而避免对数据的进行翻译。
  4. 基于底层:翻译器只会根据X86指令集进行翻译,而不是上层的二进制接口。
  5. 子集:如果翻译器的输入是完整的X86指令集,但是它的生成的代码是X86的安全子集,同时意味着生成的代码能在低权限的用户模式运行。
  6. 灵活:翻译的代码会根据虚拟机的运行状态来进行调整,从而提升效率。

对于CPU虚拟化而言,只有上面这两种技术是远远不够的,还需要调度技术,也就是需要CPU调度器(Scheduler)。但是CPU的调度器和常见操作系统的调度器是很不同的,因为CPU的调度器的责任是将执行上下文分配给一个处理器,而普通操作系统的调度器则是执行上下文分配给一个进程。同样的是,CPU调度器并没有采用传统的优先级机制,而是采用平衡共享的机制,来将处理器资源更好地分配给虚拟机,同时也能设定每个虚拟机的份额,预留和极限等设定值。在VMware最常用的CPU调度器算法,是“Co-Scheduling”算法,其也常被称为“gang-scheduling”算法,它的核心概念是让相关的多个进程尽可能在多个处理器上同时执行,因为当多个相关进程同时执行时,它们互相之间会进行同步,假设他们不再一起执行的话,将会增加很多由同步导致的延迟。在vSphere中,VMware推出了Co-Scheduling的更新版本,叫做Relaxed Co-Scheduling,它能更好地与虚拟机进行协作。同时,为了更好利用最新推出了多核系统,VMware也给调度器添加很多新的特性,主要集中在两方面:其一是对现有多核环境的探知,比如对NUMA(Non-Uniform Memory Access),Hyperthreading,VM-Affinity的支持。其二是在多核之间进行有效的负载均衡。

 

内存

VMKernel在内存虚拟化方面所采用的核心机制就是“影子页表 (Shadow Page Table)”。在探讨影子页表的机制之前,先看一下传统页表的运行机制,其实也很简单,就是页表将VPN(Virtual Page Number 虚拟内存页号)翻译成MPN(Machinel Page Number,机器内存页号),之后将这个MPN发给上层,让其调用。但是这种做法在虚拟的环境是不适用的,因为当虚拟机从页表得到的翻译之后的页号不是MPN是PPN(物理内存页号),之后需要从PPN再转换成MPN,由于这样将经历两层转换,所以肯定会较高的成本,所以VMware引入影子页表这个机制,它维护为每个Guest都维护一个“影子页表”,在这个表中能直接维护VPN和MPN之间映射关系,并加载在TLB中。所以通过“影子页表”这个机制能够让Guest在大多数情况下能通过TLB直接访问内存,保证了效率。

Shadow Page Table

图2. 内存虚拟化(点击可看大图)

由于虚拟机对内存的消耗胜于对CPU的消耗,同时介于内存的内容同质化和浪费这两个现象在虚拟环境非常普遍,所以VMware在影子页表的基础上引入了三个非常不错的技术来减少内存的消耗,以支撑更多的虚拟机:其一是Memory Overcommit机制,这个机制通过让虚拟机占用的内存总量超越物理机的实际容量来使一台物理机能支持更多的虚拟机。其二是用于减少虚拟机之间相似内存页的Page Sharing,它主要实现是通过对多个虚拟机的内存页面进行Hash,来获知那些内存页面是重复的,接着将多个重复的内存页面整合为一个replica,之后通过CoW(Copy On Write)的机制来应对对内存页面的修改。其三是能在各个虚拟机之间动态调整内存的Balloon Driver,其实现机制就是通过给每个虚拟机安装VMware Tools(可以把VMware Tools看作VMware的驱动)来装入Balloon Agent,在运行的时候,Balloon Agent会和主机的Balloon Driver进行沟通,来调整每台虚拟机的内存空间,来将那些在某些虚拟机上不处于工作状态的内存通过swapping等方式来闲置出来,以拨给那些急需内存的虚拟机。

 

I/O

VMKernel的做法是通过模拟I/O设备(磁盘和网卡等)来实现虚拟化。而且主要选取最大众化的硬件来模拟,比如440BX的主板,LSI Logic的SCSI卡和AMD Lance的网卡,从而提高这些模拟I/O设备的兼容性。 对Guest OS而言,它所能看到就是一组统一的I/O设备,同时Guest OS每次I/O操作都会陷入到VMM,让VMM来执行。这种方式,对Guest而言,是一种非常透明的方式,因为无需顾忌其是否和底层硬件兼容,比如Guest操作的是SCSI的设备,但实际物理机可以SATA的硬盘。虽然这种模拟I/O设备的做法有一定开支,但在经过了VMware长时间优化,使得其在处理小规模的I/O时,非常游刃有余,但是在这个模型的方法在处理大规模I/O的时候,有时候可能会出现力不从心的局面,所以VMware在I/O层推出一些半虚拟机技术,比如,vmxnet半虚拟化网卡。

其次,为了更好地为VM服务,VMKernel还支持一些高级I/O技术:

  1. VMFS,是VMware为虚拟化设计的分布式文件系统,它不仅能给虚拟机提供高速的I/O,而且由于它自带的锁机制,所以允许多个主机能同时访问同一个文件系统。因为放置在其上面的多为大于1G的Virtual Disk,为了减少存取文件系统数据结构的元数据的大小,它Block大小被设计为1MB到256MB,默认是1MB,使得其元数据得到了精简,而且所有的元数据都被放置在内存中作为缓存,以提高速度。
  2. Virtual Switch,其也是VMKernel的一个组件,主要给ESX主机上面所有虚拟机提供网络支持。在功能方面。除了不支持STP(Spanning ree protocol,生成树协议)和无需通过检测网络流量来获得之外,其他基本和物理交换机类似。 在vSphere中,VMware也推出了Virtual Switch的升级版本Distributed Virtual Switch,它将解决一些Virtual Switch的瑕疵。
  3. 支持新的物理层技术:VMDirectPath能增强网络和存储方面的I/O性能,PCI-SIG的SR-IOV硬件虚拟化技术能更好地对PCIe设备进行虚拟化, vStorage的 Thin Provisioning和Linked Clone这两个技术可减少存储空间达50%左右。
  4. 网络和存储方面的调度:除了系统能通过预设定一些网络和存储的参数来提升性能,用户还可以通过GUI(比如vSphere Client)来对网络和存储这两方面进行调优。

 

总结

在开头也说,有可能是竞争的原因,使得VMware已经越来越少地公开它的技术资料,特别是最核心的ESX技术。 所以上面这些材料主要是来自于ESX 2的文档,而不是来自于最新的vSphere 4的文档,但是从这些文档中,我们还可以可以看出它绝对是全虚拟化的巅峰,并且在其新版中也已经引入了代号为VMI的半虚拟技术和支持Intel/AMD最新的硬件辅助虚拟化技术。就像本系列第二篇X86虚拟化技术所讲的那样,虽然在速度上面,半虚拟化技术和硬件辅助虚拟化技术的确各有千秋,但是他们都有软肋,半虚拟化技术是需要对Guest OS进行修改,硬件辅助虚拟化技术则是不够成熟,而且ESX的全虚拟化技术是经过VMware高级工程师们长达10年优化的,所以在跑某些Workload的时候,全虚拟化反而速度更优。综上所述,用户在使用最新版ESX的时候,应该根据不同的workload来选择不同的虚拟化方法,具体可以查看VMware的白皮书(见参3)。

本篇结束,下篇将关注Virtual Networking!

参考资料:

  1. 《VMware ESX Server Advanced Technical Design Guide》
  2. VMWare ESX Server 2 – Architecture and Performance Implications
  3. Virtual Machine Monitor Execution Modes in VMware vSphere 4.0
  4. Architecture of VMware ESXi
  5. VMware vSphere 4: The CPU Scheduler in VMware ESX 4
  6. Understanding Memory Resource Management in VMware ESX Server
(4个打分, 平均:5.00 / 5)

雁过留声

“剖析系统虚拟化(4)- VMware ESX 架构”有26个回复

  1. Deadfish 于 2010-04-27 5:22 下午

    VMWare 的ESX的中文资料确实比较少,感谢楼主的精心写作。

  2. ikewu83 于 2010-04-27 6:41 下午

    呵呵,因为资料太少了,所以写的很意犹未尽啊,本来希望能提供大家更多细节。

  3. John 于 2010-04-27 8:26 下午

    VMWARE 有一个paper,比较有意思. 结论是说, 全虚拟化在wmware上面的性能并不如BT. 是因为他们对BT的研究已经很长很长时间,有很深的技术积累. 然后说,如果新开发一个VMM的话,能利用VT之类的技术是可以的,但是对于VMWARE这样的,需要比较大的改动才能充分利用硬件虚拟化技术.

    题目是:”A Comparison of Software and Hardware Techniques for x86 Virtualization

  4. John 于 2010-04-27 8:27 下午
  5. John 于 2010-04-27 8:59 下午

    ps:我只是转贴链接. 是CLF上一位朋友写的.

  6. Lucifer 于 2010-04-27 9:05 下午

    半虚拟化和全虚拟化对应
    而硬件(辅助)虚拟化和软件虚拟化对应,这四个或者三个并不是并列的关系……软件虚拟化可以分为半虚拟化和全虚拟化,硬件虚拟化也可以分为半虚拟化和全虚拟化,ikewu83和john都拿半虚拟化、全虚拟化、硬件虚拟化直接比较,并不正确

    vmware的papaer说的是硬件虚拟化并不一定比软件虚拟化(也就是它自己用的BT技术)更好,实际上也是如此

    使用BT技术的系统可以是也可以不是全虚拟化,因为虚拟化可以细分为CPU虚拟化、内存虚拟化以及IO虚拟化等,BT只涉及到cpu和内存方面;对单纯指令的执行来说可以是BT/全虚拟化,而在IO上则可以通过back/end driver模型实现半虚拟化

  7. ikewu83 于 2010-04-27 9:31 下午

    呵呵,谢谢大家的评论,现在各种虚拟化技术的确各有千秋!

  8. Lucifer 于 2010-04-27 9:49 下午

    虚拟化的分类……下面的这个表大致上还是比较正确的
    http://publish.it168.com/diy/showBigPic.asp?cDocid=20070608033502&picid=471784.jpg

  9. ikewu83 于 2010-04-27 10:34 下午

    to Lucifer:
    那张表我看了,还是有一定的新意,谢谢留言!

  10. hello 于 2010-04-27 11:12 下午

    都是是分析X86的,看来mobile virtualization目前应用还是太少。

  11. 老韩 于 2010-04-28 12:49 上午

    8楼的表格有价值,学习了

  12. ikewu83 于 2010-04-28 3:24 上午

    to hello:
    mobile virtualization现在有两点不足,其一是硬件不够强或者电池不够,其二是缺乏需求。

  13. 素里太守 于 2010-04-28 12:00 下午

    to 12楼:
    对你说的两点十分同意,这两点也许要改为3点。

    同样是跑ANDROID上网浏览,VMWARE 的X86(单核, 2.3G)比高通的72(76)XX好像有两代CPU的差距。这就是说,486,最多586上跑VMWARE,学术意义有,实际意义???

  14. ikewu83 于 2010-04-28 4:01 下午

    to 素里太守:
    这个比喻还是挺靠谱的!

  15. John 于 2010-04-28 6:50 下午

    TO 13:
    虚拟化!=(vmware and xen)
    你用 desktop 的观点看嵌入式,当然得到的结论也有偏差了.

  16. 不能说的秘密 于 2010-04-28 7:04 下午

    世界前两大嵌入式CPU IP都在往CPU里面加虚拟化support, why? 不要问我消息来源,不能说 :)

    这是一个趋势,就像几年前BNN在CLF上讨论XEN得到的回应一样,怀疑.5年后的今天,现状是…. 首席应该后悔当时没有抓住趋势博一把吧.

  17. ikewu83 于 2010-04-28 7:20 下午

    to John:
    当然偏差不可避免,最关键的是缺乏Killer App。

  18. 素里太守 于 2010-04-28 9:16 下午

    to 15:

    X86的ANDROID是用虚拟机跑的;高通的72(76)XX的ANDROID没有用虚拟机。而且X86的ANDROID是1024×768的;高通片子上的ANDROID是800×480的。俺基本叙述的是对一个事实的主观感觉,除非有人能证明在同一CPU上跑ANDROID比这个CPU加虚拟机跑ANDROID要慢。 :-P

  19. John 于 2010-04-28 9:31 下午

    to 18:

    简单得说就是嵌入式系统是专用系统,嵌入式的虚拟化方案也不同于 xen/vmware esx这一类太heavy的方案.所以不要用看desktop/server中的xen/vmware 的观点来看嵌入式.背后的需求推动力不同,导致了方案也不同. 嵌入式中的方案更多的是类似于L4这一类或者是厂商专有的方案.

  20. former borqser 于 2010-04-28 11:28 下午

    19楼说的对,嵌入式特别是终端设备,侧重点不一样,需求还是以安全为主,隔离,”单独的地址空间”,而服务器和桌面虚拟化除安全外,要进行设备虚拟,复用物理设备,这些在终端特别是手机从目前的市场看需求不大。

  21. ikewu83 于 2010-04-29 12:07 上午

    看来要写一篇分析Mobile Virtulization的文章!

  22. hello 于 2010-04-29 12:19 上午

    To all:
    不能拿X86的PC平台的一些性能参数与embedded相比,没有可比性。mobile virtualization 只要找到合适的应用点,一切都有可能。只要一个ARM9就可以做到mobile virtualization:一个android+一个rtos. 所以这些硬件的条件都不是问题.

  23. 素里太守 于 2010-04-29 1:52 上午

    To Hello:

    俺要说的是不管ARM9架构哦还是ARM11架构或者Cortex架构,跑ANDROID高通72(76)XX(ARM 11 528Mhz)就是基准硬件平台,不管虚拟不虚拟,性能低于这个基准的CPU是搞不出好的用户体验的。

  24. ikewu83 于 2010-04-30 12:05 上午

    我相信再过5年ARM能达到Core Duo 2的水平,也意味着ARM已经足够快了!

  25. Bob_zhao 于 2011-01-27 7:02 下午

    想请教一个问题:Guest OS到底是怎么去访问影子页表表项的,按照我的理解,Guest OS在TLB miss之后,会通过Guest CR3寄存器获取到Guest的页目录项,通过页目录项访问到页表项,进而得到虚拟机的物理地址,但是好像还是没有方法直接通过影子页表得到Host的物理地址;
    难道是Guest OS根本就不去访问自己维护的页表,通过什么方式直接访问到Host的影子页表物理地址,只有这样才能获取到Guest虚拟地址到host物理地址的映射。

  26. James 于 2011-01-27 7:40 下午

    回楼上

    影子是由 VMM 维护的. guest VA -> GUEST PA -> HOST->PA. 其中 GUEST PA->HOST ->PA是影子页表的entry.