KVM虚拟化
1.虚拟化定义
虚拟化定义:虚拟化是一种资源管理技术,它将计算机的各种实体资源(CPU、内存、存储、网络等)予以抽象和转化出来,并提供分割、重新组合,以达到最大化利用物理资源的目的。
广义来讲,只要是将物理资源隔离成多个逻辑(虚拟)资源,就可以称为虚拟化。所以存储(逻辑卷)和网络(overlay/underlay)技术也可以称之为虚拟化。
Virtual Machine Monitor(VMM,虚拟机监控器,也称为Hypervisor)层,就是为了达到虚拟化而引入的一个软件层。
![](https://img.haomeiwen.com/i14636026/66657a5bea6b4ff7.png)
2.虚拟化分类
虚拟化技术有很多种实现方式,比如软件虚拟化和硬件虚拟化,再比如准(半)虚拟化和全虚拟化。
2.1 硬件和软件虚拟化
软件虚拟化
顾名思义,就是通过软件模拟来实现VMM层,通过纯软件的环境来模拟执行客户机里的指令。最纯粹的软件虚拟化实现当属QEMU。在没有启用硬件虚拟化辅助的时候,它通过软件的二进制翻译[插图]仿真出目标平台呈现给客户机,客户机的每一条目标平台指令都会被QEMU截取,并翻译成宿主机平台的指令,然后交给实际的物理平台执行。由于每一条都需要这么操作一下,其虚拟化性能是比较差的,同时其软件复杂度也大大增加。但好处是可以呈现各种平台给客户机,只要其二进制翻译支持。
硬件虚拟化
就是指计算机硬件本身提供能力让客户机指令独立执行,而不需要(严格来说是不完全需要)VMM截获重定向。以x86架构为例,它提供一个略微受限制的硬件运行环境供客户机运行(non-root mode[插图]),在绝大多数情况下,客户机在此受限环境中运行与原生系统在非虚拟化环境中运行没有什么两样,不需要像软件虚拟化那样每条指令都先翻译再执行,而VMM运行在root mode,拥有完整的硬件访问控制权限。仅仅在少数必要的时候,某些客户机指令的运行才需要被VMM截获并做相应处理,之后客户机返回并继续在non-root mode中运行。可以想见,硬件虚拟化技术的性能接近于原生系统[插图],并且,极大地简化了VMM的软件设计架构。
简而言之:软件虚拟化是把虚拟机(客户机)的指令交由VMM翻译并执行,因此会带来复杂性和性能的丢失。硬件虚拟化是把虚拟机的大部分指令交由硬件执行,这样提升了虚拟化的性能。
Intel硬件虚拟化技术大致分为如下3个类别(这个顺序也基本上是相应技术出现的时间先后顺序)。
1)VT-x技术:是指Intel处理器中进行的一些虚拟化技术支持,包括CPU中引入的最基础的VMX技术,使得KVM等硬件虚拟化基础的出现成为可能。同时也包括内存虚拟化的硬件支持EPT、VPID等技术。
2)VT-d技术:是指Intel的芯片组的虚拟化技术支持,通过Intel IOMMU可以实现对设备直接分配的支持。
3)VT-c技术:是指Intel的I/O设备相关的虚拟化技术支持,主要包含两个技术:一个是借助虚拟机设备队列(VMDq)最大限度提高I/O吞吐率,VMDq由Intel网卡中的专用硬件来完成;另一个是借助虚拟机直接互连(VMDc)大幅提升虚拟化性能,VMDc主要就是基于SR-IOV标准将单个Intel网卡产生多个VF设备,用来直接分配给客户机。
2.2半虚拟化和全虚拟化
最理想的虚拟化的两个目标如下:
1)客户机完全不知道自己运行在虚拟化环境中,还以为自己运行在原生环境里。
2)完全不需要VMM介入客户机的运行过程。纯软件的虚拟化可以做到第一个目标,但性能不是很好,而且软件设计的复杂度大大增加。
半虚拟化:
那么如果放弃第一个目标呢?让客户机意识到自己是运行在虚拟化环境里,并做相应修改以配合VMM,这就是半虚拟化(Para-Virtualization)。
一方面,可以提升性能和简化VMM软件复杂度;另一方面,也不需要太依赖硬件虚拟化的支持,从而使得其软件设计(至少是VMM这一侧)可以跨平台且是优雅的。“本质上,准虚拟化弱化了对虚拟机特殊指令的被动截获要求,将其转化成客户机操作系统的主动通知。但是,准虚拟化需要修改客户机操作系统的源代码来实现主动通知。”典型的半虚拟化技术就是virtio,使用virtio需要在宿主机/VMM和客户机里都相应地装上驱动。
全虚拟化:
全虚拟化与半虚拟化相反的,全虚拟化(Full Virtualization)坚持第一个理想化目标:客户机的操作系统完全不需要改动。敏感指令在操作系统和硬件之间被VMM捕捉处理,客户操作系统无须修改,所有软件都能在虚拟机中运行。因此,全虚拟化需要模拟出完整的、和物理平台一模一样的平台给客户机,这在达到了第一个目标的同时也增加了虚拟化层(VMM)的复杂度。
全虚拟化分类:
Type1和Type2虚拟化从软件框架的角度上,根据虚拟化层是直接位于硬件之上还是在一个宿主操作系统之上,将虚拟化划分为Typel和Type2。
Type1(类型1)Hypervisor也叫native或bare-metal Hypervisor。这类虚拟化层直接运行在硬件之上,没有所谓的宿主机操作系统。它们直接控制硬件资源以及客户机。典型地如Xen、和VMware ESX。
Type2(类型2)Hypervisor运行在一个宿主机操作系统之上,如VMware Workstation;或系统里,如KVM。这类Hypervisor通常就是宿主机操作系统的一个应用程序,像其他应用程序一样受宿主机操作系统的管理。比如VMware Workstation就是运行在Windows或者Linux操作系统上的一个程序而已。客户机是在宿主机操作系统上的一个抽象,通常抽象为进程。
3.KVM虚拟化简介
KVM就是在硬件辅助虚拟化技术之上构建起来的虚拟机监控器。当然,并非要所有这些硬件虚拟化都支持才能运行KVM虚拟化,KVM对硬件最低的依赖是CPU的硬件虚拟化支持,比如:Intel的VT技术和AMD的AMD-V技术,而其他的内存和I/O的硬件虚拟化支持,会让整个KVM虚拟化下的性能得到更多的提升。KVM虚拟化的核心主要由以下两个模块组成:
1)KVM内核模块,它属于标准Linux内核的一部分,是一个专门提供虚拟化功能的模块,主要负责CPU和内存的虚拟化,包括:客户机的创建、虚拟内存的分配、CPU执行模式的切换、vCPU寄存器的访问、vCPU的执行。
2)QEMU用户态工具,它是一个普通的Linux进程,为客户机提供设备模拟的功能,包括模拟BIOS、PCI/PCIE总线、磁盘、网卡、显卡、声卡、键盘、鼠标等。同时它通过ioctl系统调用与内核态的KVM模块进行交互。
KVM的主要架构
![](https://img.haomeiwen.com/i14636026/89de4f3e9704d3ef.png)
4.KVM关键技术
4.1 CPU
SMP(Symmetric Multi-Processor,对称多处理器)系统。在SMP系统中,多个程序(进程)可以做到真正的并行执行,而且单个进程的多个线程也可以得到并行执行,这极大地提高了计算机系统并行处理能力和整体性能。在硬件方面,早期的计算机系统更多的是在一个主板上拥有多个物理的CPU插槽来实现SMP系统,后来随着多核技术、超线程(Hyper-Threading)技术的出现,SMP系统就会使用多处理器、多核、超线程等技术中的一个或多个。
进程的处理器亲和性(Processor Affinity),即CPU的绑定设置,是指将进程绑定到特定的一个或多个CPU上去执行,而不允许将进程调度到其他的CPU上。Linux内核对进程的调度算法也是遵守进程的处理器亲和性设置的。设置进程的处理器亲和性带来的好处是可以减少进程在多个CPU之间交换运行带来的缓存命中失效(cache missing),从该进程运行的角度来看,可能带来一定程度上的性能提升。换个角度来看,对进程亲和性的设置也可能带来一定的问题,如破坏了原有SMP系统中各个CPU的负载均衡(load balance),这可能会导致整个系统的进程调度变得低效。特别是在多处理器、多核、多线程技术使用的情况下,在NUMA(Non-UniformMemory Access)[插图]结构的系统中,如果不能基于对系统的CPU、内存等有深入的了解,对进程的处理器亲和性进行设置可能导致系统的整体性能的下降而非提升。
over-commit:KVM允许客户机过载使用(over-commit)物理资源,即允许为客户机分配的CPU和内存数量多于物理上实际存在的资源。物理资源的过载使用能带来资源充分利用方面的好处。试想在一台强大的硬件服务器中运行Web服务器、图片存储服务器、后台数据统计服务器等作为虚拟客户机,但是它们不会在同一时刻都负载很高,如Web服务器和图片服务器在白天工作时间负载较重,而后台数据统计服务器主要在晚上工作,所以对物理资源进行合理的过载使用,给这几个客户机分配的系统资源总数多余实际拥有的物理资源,就可能在白天和夜晚都充分利用物理硬件资源,而且由于几个客户机不会同时对物理资源造成很大的压力,它们各自的服务质量(QoS)也能得到保障。
4.2 内存
4.2.1 EPT(Extended Page Tables,扩展页表),属于Intel的第二代硬件虚拟化技术,它是针对内存管理单元(MMU)的虚拟化扩展。EPT降低了内存虚拟化的难度(与影子页表相比),也提升了内存虚拟化的性能。从基于Intel的Nehalem[插图]架构的平台开始,EPT就作为CPU的一个特性加入到CPU硬件中去了。和运行在真实物理硬件上的操作系统一样,在客户机操作系统看来,客户机可用的内存空间也是一个从零地址开始的连续的物理内存空间。为了达到这个目的,Hypervisor(即KVM)引入了一层新的地址空间,即客户机物理地址空间,这个地址空间不是真正的硬件上的地址空间,它们之间还有一层映射。所以,在虚拟化环境下,内存使用就需要两层的地址转换,即客户机应用程序可见的客户机虚拟地址(Guest Virtual Address,GVA)到客户机物理地址(Guest PhysicalAddress,GPA)的转换,再从客户机物理地址(GPA)到宿主机物理地址(Host PhysicalAddress,HPA)的转换。其中,前一个转换由客户机操作系统来完成,而后一个转换由Hypervisor来负责。
在硬件EPT特性加入之前,影子页表(Shadow Page Tables)是从软件上维护了从客户机虚拟地址(GVA)到宿主机物理地址(HPA)之间的映射,每一份客户机操作系统的页表也对应一份影子页表。有了影子页表,在普通的内存访问时都可实现从GVA到HPA的直接转换,从而避免了上面前面提到的两次地址转换。Hypervisor将影子页表载入到物理上的内存管理单元(Memory Management Unit,MMU)中进行地址翻译。图4-3展示了,GVA、GPA、HPA之间的转换,以及影子页表的作用。
尽管影子页表提供了在物理MMU硬件中能使用的页表,但是其缺点也是比较明显的。首先影子页表实现非常复杂,导致其开发、调试和维护都比较困难。其次,影子页表的内存开销也比较大,因为需要为每个客户机进程对应的页表的都维护一个影子页表。为了解决影子页表存在的问题,Intel的CPU提供了EPT技术(AMD提供的类似技术叫做NPT,即Nested Page Tables),直接在硬件上支持GVA-->GPA-->HPA的两次地址转换,从而降低内存虚拟化实现的复杂度,也进一步提升了内存虚拟化的性能。图4-4展示了Intel EPT技术的基本原理。
4.2.2大页内存
x86(包括x86-32和x86-64)架构的CPU默认使用4KB大小的内存页面,但是它们也支持较大的内存页,如x86-64系统就支持2MB大小的大页(huge page)。Linux2.6及以上的内核都支持huge page。如果在系统中使用了huge page,则内存页的数量会减少,从而需要更少的页表(page table),节约了页表所占用的内存数量,并且所需的地址转换也减少了,TLB缓存失效的次数就减少了,从而提高了内存访问的性能。另外,由于地址转换所需的信息一般保存在CPU的缓存中,huge page的使用让地址转换信息减少,从而减少了CPU缓存的使用,减轻了CPU缓存的压力,让CPU缓存能更多地用于应用程序的数据缓存,也能够在整体上提升系统的性能。
在KVM中内存也是允许过载使用(overcommit)的,KVM能够让分配给客户机的内存总数大于实际可用的物理内存总数。由于客户机操作系统及其上的应用程序并非一直100%地利用其分配到的内存,并且宿主机上的多个客户机一般也不会同时达到100%的内存使用率,所以内存过载分配是可行的。一般来说,有如下三种方式来实现内存的过载使用。1)内存交换(swapping):用交换空间(swap space)来弥补内存的不足。2)气球(ballooning):通过virio_balloon驱动来实现宿主机Hypervisor和客户机之间的协作。3)页共享(page sharing):通过KSM(Kernel Samepage Merging)合并多个客户机进程使用的相同内存页。
4.2.3 Ballooning
ballooning技术形象地在客户机占用的内存中引入气球(balloon)的概念。气球中的内存是可以供宿主机使用的(但不能被客户机访问或使用),所以,当宿主机内存紧张,空余内存不多时,可以请求客户机回收利用已分配给客户机的部分内存,客户机就会释放其空闲的内存,此时若客户机空闲内存不足,可能还会回收部分使用中的内存,可能会将部分内存换出到客户机的交换分区(swap)中,从而使内存气球充气膨胀,进而使宿主机回收气球中的内存用于其他进程(或其他客户机)。反之,当客户机中内存不足时,也可以让客户机的内存气球压缩,释放出内存气球中的部分内存,让客户机使用更多的内存。
4.2.4NUMA
NUMA(Non-Uniform Memory Access,非统一内存访问架构)是相对于UMA(UniformMemory Access)而言的。早年的计算机架构都是UMA,如图7-2所示。所有的CPU处理单元(Processor)均质地通过共享的总线访问内存,所有CPU访问所有内存单元的速度是一样的。在多处理器的情形下,多个任务会被分派在各个处理器上并发执行,则它们竞争内存资源的情况会非常频繁,从而引起效率的下降。
所以,随着多处理器架构的逐渐普及以及数量的不断增长,NUMA架构兴起,如图7-3所示。处理器与内存被划分成一个个的节点(node),处理器访问自己节点内的内存会比访问其他节点的内存快。
4.2.5
内存合并KSM KSM是“Kernel SamePage Merging”的缩写,中文可称为“内核同页合并”。在QEMU/KVM中,一个虚拟客户机就是一个QEMU进程,所以使用KSM也可以实现多个客户机之间的相同内存合并。而且,如果在同一宿主机上的多个客户机运行的是相同的操作系统或应用程序,则客户机之间的相同内存页的数量就可能还比较大,这种情况下KSM的作用就更加显著。在KVM环境下使用KSM,KSM还允许KVM请求哪些相同的内存页是可以被共享而合并的,所以KSM只会识别并合并那些不会干扰客户机运行,不会影响宿主机或客户机的安全内存页。可见,在KVM虚拟化环境中,KSM能够提高内存的速度和使用效率,具体可以从以下两个方面来理解。
1)在KSM的帮助下,相同的内存页被合并了,减少了客户机的内存使用量,一方面,内存中的内容更容易被保存到CPU的缓存当中;另一方面,有更多的内存可用于缓存一些磁盘中的数据。因此,不管是内存的缓存命中率(CPU缓存命中率),还是磁盘数据的缓存命中率(在内存中命中磁盘数据缓存的命中率)都会提高,从而提高了KVM客户机中操作系统或应用程序的运行速度。
2)KSM是内存过载使用的一种较好的方式。KSM通过减少每个客户机实际占用的内存数量,就可以让多个客户机分配的内存数量之和大于物理上的内存数量。而对于使用相同内存量的客户机,在物理内存量不变的情况,可以在一个宿主机中创建更多的客户机,提高了虚拟化客户机部署的密度,提高了物理资源的利用效率。
4.3 网络
DPDK全称是Data Plane Development Kit,最初是由Intel公司维护的数据平面开发工具集,为Intel x86处理器架构下用户空间高效的数据包处理提供库函数和驱动的支持,现在也是一个完全独立的开源项目,它还支持POWER和ARM处理器架构。不同于Linux系统以通用性设计为目的,它专注于网络应用中数据包的高性能处理。具体体现在DPDK应用程序是运行在用户空间上,利用自身提供的数据平面库来收发数据包,绕过了Linux内核协议栈对数据包处理过程。其优点是:性能高、用户态开发、出故障后易恢复。在KVM架构中,为了达到非常高的网络处理能力(特别是小包处理能力),可以选择DPDK与QEMU中的vhost-user结合起来使用。
SR-IOV,物理网卡虚拟多个虚拟网卡
4.4 存储
Ceph是Linux上一个著名的分布式存储系统,能够在维护POSIX兼容性的同时加入复制和容错功能。Ceph由储存管理器(Object storage cluster对象存储集群,即OSD守护进程)、集群监视器(Ceph Monitor)和元数据服务器(Metadata server cluster,MDS)构成。其中,元数据服务器MDS仅仅在客户端通过文件系统方式使用Ceph时才需要。当客户端通过块设备或对象存储使用Ceph时,可以没有MDS。Ceph支持3种调用接口:对象存储,块存储,文件系统挂载。在libvirt和QEMU中都有Ceph的接口,所以Ceph与KVM虚拟化集成是非常容易的。在OpenStack的云平台解决方案中,Ceph是一个非常常用的存储后端。
5.管理工具
libvirtlibvirt是使用最广泛的对KVM虚拟化进行管理的工具和应用程序接口,已经是事实上的虚拟化接口标准,本节后部分介绍的其他工具都是基于libvirt的API来实现的。作为通用的虚拟化API,libvirt不但能管理KVM,还能管理VMware、Hyper-V、Xen、VirtualBox等其他虚拟化方案。
OpenStack是一个开源的基础架构即服务(IaaS)云计算管理平台,可用于构建共有云和私有云服务的基础设施。OpenStack是目前业界使用最广泛的功能最强大的云管理平台,它不仅提供了管理虚拟机的丰富功能,还有非常多其他重要管理功能,如:对象存储、块存储、网络、镜像、身份验证、编排服务、控制面板等。OpenStack仍然使用libvirt API来完成对底层虚拟化的管理。
4.5 热插拔
目前,在服务器硬件中,可实现热插拔的部件主要有SATA硬盘(IDE不支持热插拔)、CPU、内存、风扇、USB、网卡等。在KVM虚拟化环境中,在不关闭客户机的情况下,也可以对客户机的设备进行热插拔。目前,KVM对热插拔的支持还不够完善,主要支持PCI设备和CPU的热插拔,也可以通过ballooning间接实现内存的热插拔。
4.6 热迁移
本质上是通过快照技术实现虚拟机或者数据卷的迁移,如果涉及到数据库或者SAP等,可能需要使用到数据库或者应用的迁移方法。