虚拟化
虚拟化技术
目前虚拟化技术有软件模拟、全虚拟化(使用二进制翻译)、半虚拟化(操作系统辅助)、硬件辅助虚拟化和容器虚拟化这几种。
(1)软件虚拟化
软件模拟是通过软件完全模拟cpu、芯片组、磁盘、网卡等计算机硬件:
因为是软件模拟,所以理论上可以模拟任何硬件,但是非常低效,一般只用于研究测试的场景,典型的有QEMU。
(2)全虚拟化
x86平台指令集分为4个特权模式:Ring0 、Ring1、Ring2、Ring3、OS工作在Ring0级别,应用软件工作在Ring3级别,驱动程序工作在Ring1和Ring2。
如何将虚拟机越级的指令使用进行隔离,1998年VMware首次找到了解决办法,通过虚拟化引擎,捕获虚拟机的指令,并进行处理,即全虚拟化方案。
在全虚拟化的情况下,VMM工作在Ring 0 ,Guest OS工作在Ring 1 ,应用程序工作在Ring 3,可是这时候Guest OS是不知道自己工作在虚拟机里的,认为自己还是工作在Ring 0 ,所以它还是按照Ring 0级别产特权生指令,Guest OS产生的每一条指令都会被VMM截取,并翻译成宿主机平台的指令,然后交给实际的物理平台执行,由于每一条指令都需要这么翻译一下,所以这种虚拟化性能比较差。
(3)半虚拟化
半虚拟化是对Guest OS做相应修改,以便和VMM协同运作。在硬件辅助虚拟化兴起之前,半虚拟化性能胜过全虚拟化。在半虚拟化情况下,Guest OS知道自己并不是直接运行在硬件资源上,而是运行在虚拟化环境里,工作在非Ring 0,那么它原先在物理机上执行的一些特权指令,就会修改成其他方式(超级调用),这种方式是可以和VMM约定好的,半虚拟化不需要VMM层进行二进制翻译,所以性能较好,但是实现比较麻烦(要修改OS内核代码),典型的半虚拟化技术有xen。
(4)硬件辅助虚拟化
2005年,Intel推出了硬件辅助虚拟化方案,对CPU指令进行改造,即VT-x,VT-x提供了两种操作模式:VMX root operation和VMX non-root operation,VMM运行在 VMX root operation,虚拟机运行在VMX non-root operation。在绝大多数情况下,客户机在此模式下运行与原生系统在非虚拟化环境中运行性能一样,不需要像全虚拟化那样每条指令都要先翻译再执行;在少数必要的时候,某些客户机指令的运行才需要被VMM截获并做相应处理。这种方案因为是基于硬件的,所以效率非常高。
现在不仅CPU指令有硬件虚拟化方案,I/O通信也有硬件解决方案,称为VT-d;网络通信的称为VT-c。
(5)容器虚拟化
容器虚拟化是基于CGroups、Namespace等技术将进程进行隔离,每个进程就像一台独立的虚拟机,拥有自己被隔离出来的资源,也有自己的根目录、独立的进程编号、被隔离的内存空间。基于容器的虚拟化可以实现在单一内核上运行多个实例。目前热门的容器虚拟化技术Docker,Docker可以将一个开发环境进行打包,很方便在另一个系统上运行起来。
虚拟化架构
-
裸金属虚拟化:直接在硬件上面安装虚拟化软件,再在其上安装操作系统和应用,不需要操作系统,hypervisor本身就是一个操作系统, hypervisor直接访问硬件资源,这个使得虚拟机能够获得更好的性能、扩展性与稳定性,比较适合企业数据中心。调用的流程是 虚拟机内核 -> Hypervisor -> 硬件。
例如:VMware ESXI 、Proxmox VE、Microsoft Hyper-V
-
宿主虚拟化:在宿主操作系统之上安装和运行虚拟化程序,依赖于宿主操作系统对设备的支持和物理资源的管理。宿主虚拟化的 hypervisor 就像是安装在子操作系统上的一个应用,这种方式比裸机虚拟化的 hypervisor 提供更好的硬件兼容性,因为调用硬件的流程是 虚拟机内核 -> Hypervisor -> 操作系统 -> 硬件,但这也导致了宿主虚拟化的性能是要比裸机虚拟化差很多的。
例如: Windows系统上的 VMware Workstation \ VirtualBox 软件 ,Mac OS 上的 Parallels Desktop 软件
虚拟化对象
CPU虚拟化
CPU虚拟化指的是将单个物理CPU虚拟化成多个虚拟CPU供虚拟机使用,每个虚拟CPU就是一个超线程。虚拟CPU分时复用物理CPU,由虚拟机监控器(Virtual Machine Monitor,VMM)对虚拟CPU分配时间片,并同时对虚拟CPU的状态进行管理。
**超线程(hyper-threading)其实就是同时多线程(simultaneous multi-theading),是一项允许一个CPU执行多个控制流的技术。**它的原理很简单,就是把一颗CPU当成两颗来用,将一颗具有超线程功能的物理CPU变成两颗逻辑CPU,而逻辑CPU对操作系统来说,跟物理CPU并没有什么区别。因此,操作系统会把工作线程分派给这两颗(逻辑)CPU上去执行,让(多个或单个)应用程序的多个线程,能够同时在同一颗CPU上被执行。注意:两颗逻辑CPU共享单颗物理CPU的所有执行资源。因此,我们可以认为,超线程技术就是对CPU的虚拟化。
CPU虚拟化需要解决两个问题:
- 如何模拟CPU指令(所有敏感指令)
- 敏感指令:可以读写系统关键资源的指令叫做敏感指令。
- 特权指令:决大多数的敏感指令是特权指令,特权指令只能在处理器的最高特权级(内核态执行。
- 如何让多个VM共享CPU
利用与Native操作系统类似的机制—通过定时器中断,在中断触发时陷入VMM,从而根据
调度机制进行调度。
内存虚拟化
内存虚拟化:把物理机的真是物理内存统一管理,包装成多个虚拟机的内存给若干虚拟机使用。
在Linux这种使用虚拟地址的OS中,虚拟地址经过page table转换可得到物理地址:
如果这个操作系统是运行在虚拟机上的,那么这只是一个中间的物理地址(Intermediate Phyical Address - IPA),需要经过VMM/hypervisor的转换,才能得到最终的物理地址(Host Phyical Address - HPA)。从VMM的角度,guest VM中的虚拟地址就成了GVA(Guest Virtual Address),IPA就成了GPA(Guest Phyical Address)。
可见,如果使用VMM,并且guest VM中的程序使用虚拟地址(如果guest VM中运行的是不支持虚拟地址的RTOS,则在虚拟机层面不需要地址转换),那么就需要两次地址转换。
特点
内存超分配和复用
Host Memory和Guest Memory之间并不是一一对应,可以超额分配内存给VM。通讨内存复用技术实现超分配功能。
内存置换:我们在Linux中进行磁盘分区时,会看到有一个swap分区,即交换分区。当内存比较小的时候,会在磁盘上开辟出来一段空间,给内存置换使用。 当内存不够用的时候,把一些冷数据置换在磁盘上。冷数据就是指一 段时间没有被使用的数据,时间越长越冷。
内存气泡:假如我们有两台虚拟机,每台虚拟机规格4G内存,但是并不是每一时刻虚拟机都可以完全使用完这4G大小,因此,hypervisor(VMM)会回收这些未使用完的内存资源,然后给到使用率较高的虚拟机。通过挤压其他虚拟机的内存,把内存释放给其他内存使用率较高的虚拟机。这就是内存气泡技术。
NUMA
NUMA:Non-Uniform Memory Access,非一致性访问。一个服务器架构中,通常有多个物理CPU及对应的内存资源,某些CPU会绑定一定的内存和IO资源,可归为一个NUMA节点,也称为node,而这些CPU访问自身的内存和IO资源速度是最快的。
- 内存访问机制:在NUMA服务器内部,任—CPU可访问整个系统的内存,但远程内存访问的性能远低于本地内存访问。
- 节点互联机制:在同一个物理服务器内部实现,某一CPU进行远程内存访问时必须等待, NUMA服务器无法实现CPU增加时性能线性扩展。