计算虚拟化
概述
计算虚拟化是将物理服务器资源通过虚拟化技术抽象成逻辑资源,让一台物理服务器变成多台相互隔离的虚拟服务器,CPU、内存、磁盘、I/O设备等硬件资源变成虚拟化资源池进行统一动态管理,从而提高资源利用率,降低系统管理成本,让IT对业务变化更具适应力。

ZStack Cube 旗舰版支持采用基于KVM的硬件虚拟化技术。KVM是一个Linux内核模块,将Linux内核变成一个Hypervisor。KVM在Linux系统内以进程形式出现,由标准Linux调度程序进行调度,因此KVM能够使用Linux内核已有功能,例如:内存管理、CPU调度等。但是,KVM本身仅提供CPU与内存虚拟化,I/O设备虚拟化需结合Qemu才能完成。Qemu是一个用户态的设备模拟器,为云主机提供虚拟设备模型,负责各种虚拟设备的创建、调用及管理。

技术特性
CPU虚拟化
在x86体系架构上,CPU一般有4个特权级别:RING0~RING3,用于给操作系统和应用程序访问硬件。在Linux中,仅使用其中2个特权级别:RING0 (内核态) 、RING3 (用户态) 。
关于VMX根模式与VMX非根模式。对于硬件辅助虚拟化而言,为能在不对操作系统做任何修改的前提下使用云主机,CPU引入2种运行模式:VMX根模式、VMX非根模式。宿主机运行在根模式下,宿主机内核处于RING0,用户态程序处于RING3。云主机运行在非根模式下,云主机内核处于RING0,用户态程序处于RING3。
关于VM Exit与VM Entry。处于非根模式的云主机,当外部中断或缺页异常,或主动调用VMCALL指令来调用VMM服务时,CPU会从非根模式切换至根模式,整个过程称为VM Exit。相反,当VMM通过显式调用VMLAUNCH或VMRESUME指令切换至非根模式时,硬件自动加载云主机上下文,运行云主机指令,这一转换称为VM Entry。

当云主机通过VM Exit从非根模式退出至根模式后,KVM会根据退出原因执行进一步操作,若是I/O操作则交由QEMU处理,若是非I/O操作则由KVM自行处理,处理完成后通过VM Entry再次切入非根模式运行。

内存虚拟化
云主机管理器 (VMM) 负责管理和分配每个云主机的物理内存。云主机操作系统看到的是一个虚构的云主机物理地址 (GPA) 空间。操作系统的内存管理模块负责将云主机虚拟地址 (GVA) 映射到云主机物理地址 (GPA) ,其指令目标地址也是一个云主机物理地址 (GPA) 。这样的地址在无虚拟化情况下,其实是实际物理地址。但在有虚拟化情况下,这样的地址不能被直接处理使用,需VMM先将云主机物理地址 (GPA) 转换成一个物理机物理地址 (HPA) ,再交由物理处理器执行。
- 维护云主机物理地址 (GPA) 到物理机物理地址 (HPA) 之间的映射关系。
- 当云主机访问云主机物理地址 (GPA) 时,根据映射关系,将其转换成物理机物理地址 (HPA) 。

内存的硬件辅助虚拟化使用扩展页表 (EPT) 技术,通过硬件完成云主机虚拟地址 (GVA) 到物理机物理地址 (HPA) 的转换。

关于内存隔离。在物理机操作系统上,云主机进程需使用vMMU和EPT进行地址翻译。云主机进程在物理机上实际也作为普通进程存在,但它维护了两套页表:EPT页表、物理机端的普通页表。当为云主机分配内存时,首先在物理机上以普通进程的身份分配内存,然后通过EPT页表将这些内存分配给云主机。该方法可确保:物理机物理地址(HPA)分配的统一性,不同云主机之间的内存隔离,并建立了EPT页表与物理机页表之间的对应关系。云主机上看到的连续内存,实际上可能映射到物理机上多个不连续的地址区间,并且是由Hypervisor按需动态分配的。这种设计实现了不同类型进程的有效隔离和资源管理,同时保持系统的灵活性和效率。
关于内存完全释放。在云主机内存分配过程中,初始分配并不涉及实际的物理内存。当云主机真正使用内存时,控制权会转移至物理机的Hypervisor进行实际分配。对Hypervisor而言,给云主机分配内存实质是为云主机的进程分配内存空间,这些空间对应于物理机虚拟地址 (HVA) 。物理机虚拟地址 (HVA) 最终映射到哪个物理机物理地址 (HPA) ,由物理机的内存管理子系统负责。该子系统统一管理物理机上的所有物理内存,并在分配时进行标记,确保不同进程获得不同的物理机物理地址 (HPA) 。当物理机物理地址 (HPA) 不足时,可能会回收部分分配给云主机的内存,并在EPT页表中标记为页面不存在。云主机再次访问被回收的内存时,会重新分配新的物理机物理地址 (HPA) 空间。这一机制可确保云主机的物理内存不会被重复分配给不同的云主机,从而维护内存隔离和安全性。
设备虚拟化
设备虚拟化方式主要有三种:设备模拟、半虚拟化设备、设备直通。
设备模拟
设备模拟通过QEMU提供的设备模型,可完全模拟出与物理设备一样的接口。因此,在云主机操作系统中,使用原生驱动即可使用设备。设备模拟只能模拟出具有基本功能的设备,不支持复杂功能和模型的设备。完全模拟的设备兼容性好,但由于是纯软件模拟,性能相对较低。

半虚拟化设备
半虚拟化设备实现前后端驱动。利用云主机中的前端驱动,通过基于事务的通信机制,将请求直接发给宿主机端的后端驱动,从而很大程度上减少上下文切换的开销,性能相比完全设备模拟有较大提升。然而,Virtio后端驱动仍在QEMU中实现,在IO处理过程中会经过用户态与内核态之间的多次切换。为进一步提升性能,可将Virtio后端驱动的功能放至内核态实现,称为Vhost-kernel后端,于是数据仅需经过从用户态到内核态的一次切换,就可完成数据传输,实现性能提升。
随着技术发展,将数据放入用户态处理可得到更灵活的形式。因此,在原有Vhost架构中进行改动,增加Vhost-user后端,搭配DPDK、SPDK中相关用户态函数库,性能进一步提升。

设备直通
设备透传基于硬件的设备虚拟化技术,支持将PCI/PCIe物理设备直接映射到云主机的地址空间,在云主机中,使用原生设备驱动就可直接使用设备,达到近乎物理设备的性能。物理设备被透传后由云主机独享,其它云主机无法共享使用该设备。

SR-IOV是由PCI-SIG组织定义的PCIe规范的扩展规范,目的是通过提供一种标准规范,为云主机提供独立的内存空间、中断、DMA数据流。 SR-IOV支持单个物理PCIe设备 (PF) 虚拟出多个虚拟PCIe设备 (VF) ,然后通过设备透传技术将虚拟PCIe设备直通到各云主机,以实现单个物理PCIe设备支撑多云主机的应用场景。

