KVM介绍
KVM(kernel-based virtual machine,基于内核的虚拟主机),最初是一家叫Qumranet的以色列公司研发。作为他们的VDI产品的虚拟机。为了简化开发,KVM的开发人员并没有选择从底层开始新写一个Hypervisor,而是选择了基于Linux kernel,通过加载新的模块从而使Linux Kernel本身变成一个Hypervisor。2006年10月,在先后完成了基本功能、动态迁移以及主要的性能优化之后,Qumranet正式对外宣布了KVM的诞生。
KVM虚拟化技术实现相比XEN来说只有更奇葩没有最奇葩,它之所以叫基于内核的虚拟化技术,其KVM自身就是一个Linux内核模块,当一个安装有Linux系统的物理机装载了KVM这个内核模块之后,摇身一变,此Linux系统就变成了一个hypervisor。但是这个Hypervisor上面运行的进程还是会继续运行,同时也可以创建虚拟机,但每个虚拟机就是运行在Linux内核之上的一个系统进程,可以随时使用kill命令杀死。
也就在虚拟化兴起时,Linux内核社区急于将虚拟化的支持包含在内。了解XEN虚拟化技术的应该知道,Xen实现的是一个半虚拟化技术,同时XEN同ESXI一样需要独立运行在硬件之上的一个Hypervisor。所以Xen取代内核由自身管理系统资源的架构引起了内核开发人员的抵触。而KVM不需要剥夺硬件控制权,只是寄宿在Linux内核之上,于是Linux内核的维护者就像看到大救星一样,以迅雷不及掩耳的速度把KVM收录进了内核,时间大概在2006年10月左右。
之后,KVM这家公司在2008年9月被RedHat收购,出价1亿7百万美金。RedHat收购KVM后也算有了自己的虚拟化技术,此后就开始大力支持KVM,慢慢抛弃了XEN,从REHL5.4开始KVM就已经被收录,从RHEL5.8开始就正式抛弃了XEN,到RHEL6.0开始已经看不到任何XEN的踪影了。并且非但如此,RedHat怕XEN有可能侵蚀KVM市场,就把很多既可以支持XEN又可以支持KVM的管理工具改写,移除了所有XEN管理部分。由于KVM这种虚拟化技术出现的比较晚,所以充分利用了现代操作系统特性,特别是KVM要求只能运行在支持HVM(硬件辅助虚拟化)的平台上并且只能是64位平台,如Intel的VT。
KVM架构
KVM是一个非常精巧的设计方式,它只是Linux的一个内核模块,但是这个内核模块一旦装载立即可以成为一个hypervisor,如果不装载就还是一个正常的Linux系统。有了KVM模块以后Linux就有了三种运行模式:
Guest Mode:来宾模式,此模式只负责非I/O类操作或者说是非特权指令操作,如算术运行,由于是虚拟而非模拟,底层架构一样,所以此时Guest OS可以直接通过KVM Driver直接运行到物理CPU的ring 3上执行。如果是模拟那么此时就需要经过User Mode转到CPU执行。但一旦需要跟I/O打交道或需要运行特权指令,就需要Guest OS中的进程进行内部系统调用到达Geust OS的内核空间,然后经过User Mode到Kernel Mode这么一个过程。
User Mode:用户模式,此模式就代表来宾模式执行I/O类操作请求(站在虚拟机角度),因为QEMU就在用户模式运行(QEMU负责模拟I/O设备提供给Guest OS使用)。
Kernel Mode:内核模式,此模式是真正可以操作硬件的,当Guest OS执行I/O类操作或特权指令操作时需要向用户模式提交请求,然后由用户模式再次发起硬件操作请求给内核模式从而真正操作硬件。
KVM组件
在一个装载了KVM模块的Linux系统上,其运行的KVM虚拟机表现为一个个线程,Linux系统可以正常管理。KVM核心就两个组件:/dev/kvm和QEMU。
KVM模块是KVM虚拟机的核心部分,其主要功能是初始化CPU硬件,打开虚拟化模式,然后将虚拟客户机运行在虚拟机模式下,并对虚拟客户机的运行提供一定的支持。
为了软件的简洁和性能,KVM仅支持硬件虚拟化。自然而然,打开并初始化系统硬件以支持虚拟机的运行,是KVM模块的职责所在。以KVM在Intel公司的CPU上运行为例,在被内核加载的时候,KVM模块会先初始化内部的数据结构;做好准备之后,KVM模块检测系统当前的CPU,然后打开CPU控制寄存器CR4中的虚拟化模式开关,并通过执行VMXON 指令将宿主操作系统(包括KVM模块本身)置于虚拟化模式中的根模式;最后,KVM模块创建特殊设备文件/dev/kvm并等待来自用户空间的命令。接下来虚拟机的创建和运行将是一个用户空间的应用程序(QEMU)和KVM模块相互配合的过程。
1)/dev/kvm
/dev/kvm是一个字符设备,工作于Hypervisor。在用户空间,可通过这个接口(调用ioctl系统调用)管理虚拟机或通过这个接口编程序用来管理虚拟机,实现VM创建、删除、分配内存、读写VCPU的寄存器、想VCPU注入中断、运行VCPU等功能。如virsh或qemu-kvm这些工具都是都可以用来管理KVM虚拟机。
2)QEMU
QEMU本身并不是KVM的一部分,其自身就是一个著名的开源虚拟机软件。与KVM不同,QEMU虚拟机是一个纯软件的实现,所以性能低下。但是,其优点是在支持QEMU本身编译运行的平台上就可以实现虚拟机的功能,甚至虚拟机可以与宿主机并不是同一个架 构。作为一个存在已久的虚拟机,QEMU的代码中有整套的虚拟机实现,包括处理器虚拟化、内存虚拟化,以及KVM使用到的虚拟设备模拟(比如网卡、显卡、存储控制器和硬盘等)。
为了简化开发和代码重用,KVM在QEMU的基础上进行了修改。虚拟机运行期间,QEMU 会通过KVM模块提供的系统调用进入内核,由KVM模块负责将虚拟机置于处理器的特殊模式运行。遇到虚拟机进行输入输出操作,KVM模块会从上次的系统调用出口处返回 QEMU,由QEMU来负责解析和模拟这些设备。
从QEMU角度来看,也可以说QEMU使用了KVM模块的虚拟化功能,为自己的虚拟机提供硬件虚拟化的加速,从而极大地提高了虚拟机的性能。除此之外,虚拟机的配置和创 建,虚拟机运行依赖的虚拟设备,虚拟机运行时的用户操作环境和交互,以及一些针对虚拟机的特殊技术(诸如动态迁移),都是由QEMU自己实现的。
KVM的特性和局限性
KVM特性支持
一、内存管理
KVM从Linux继承了强大的内存管理功能,一个虚拟机的内存与任何其他Linux进程的内存一样进行存储,可以以大页面的形式进行交换以实现更高的性能,
KVM支持最新的基于硬件的内存虚拟化功能,支持使用Intel EPT或AMD RVI技术来完成内存地址映射,GVAàHPA,以实现更低的CPU利用率和更高的吞吐量。
支持KSM(Kernel Same-page Merging,相同内存页合并),比如在KVM上同时运行多个Linux相同版本的主机,它们都会载入一些相同的动态库,由于是只读的,所以可以进行合并。KSM通过扫描每个虚拟机的内存,查找个虚拟机间相同的内存页,并将这些内存页合并成一个各相关虚拟机能够共享的独立内存页面,从而实现了内存页面共享。节约内存使用,使得我们的KVM可以过载使用内存,虚拟机内存分配可以大于物理机内存。如果这些合并页中有某个虚拟机需要修改,那么此时KVM就会进行copy on write机制给它重新生成一个副本,它只能修改自己的而不能修改共享的。
二、硬件支持
由于KVM出现的较晚,充分利用了先进技术,所以KVM运行的物理机必须要支持硬件辅助虚拟化且只能是X64架构。
由于KVM是寄宿在Linux内核之上,所以支持的硬件取决于Linux内核支持的硬件。
三、存储
KVM可以支持任何Linux内核支持的存储设备,如:
本地存储:IDE、SCSI、SAN、SATA、SAS、PCI-E等。
网络附加存储:NAS、SAMBA等
存储区域网络:SAN,ISCSI。
分布式存储:GlustFS
KVM的原生磁盘格式为QCOW2,它支持快照,允许多级快照、压缩和加密。
四、实时迁移
各个Hypervisor利用共享存储实现实时虚拟机迁移,并且虚拟机运行的服务无中断。但是KVM实现实时迁移有一些前提条件,如:
1.镜像文件必须放在共享存储。
2.共享存储还必须放在同一个位置,否则配置文件会找不到。
3.各个Hypervisor必须要兼容。
4.CPU必须拥有相同特性,最好同款CPU。
5.两台Hypervisor的时间必须要一致。
6.两台Hypervisor必须有一样的网络配置。
五、支持的Guest OS
像XEN那种半虚拟化,由于要修改系统内核才能运行,所以不是每个系统都支持,比如Windows系统。但KVM属于全虚拟化技术,所以支持大多数系统,如:Linux、Windows、OpenBSD、FreeBSD、OpenSolaris等。另外,运行在KVM上的Windows还通过了微软的虚拟化认证,也就是说,如果你在KVM上面运行正版Windows系统,如果出现异常,微软官方是承认可提供技术支持的。当然这也是红帽跟微软的勾当而已。
六、设备驱动
还是那句话,Linux内核支持的驱动,KVM都支持。另外,KVM是一个混合类型的VMM,因为KVM能够以模拟(QEMU)的方式支持完全虚拟机,又能够支持在Guest OS中安装驱动实现IO的半虚拟化,也就是两阶段IO,前半部分IO在Guest OS上,后半部分在宿主机上。
现在在KVM中常用的IO半虚拟化组件叫virtio,由IBM和RedHat联合研发,是一个比较通用的半虚拟化IO组件。目前,基于virtio有virtio-blk支持块存储半虚拟化、virtio-net支持网络半虚拟化、virtio-pci支持pci设备虚拟化、virtio-console支持控制台的虚拟化、virtio-ballon支持动态内存的扩展和收缩。而virtio在Linux 2.6.25内核已经收录,只要编译内核时选择了virtio模块就可以,但是如果是微软的系统那么还需要去RedHat官方下载对应的virtio程序才可以支持。
七、性能和可伸缩性
KVM也继承了Linux的性能和可伸缩性。KVM虚拟化性能在很多方面(如计算能力、网络带宽等)已经可以达到非虚拟化原生环境的95%以上的性能。KVM的扩展性也非常良好,客户机和宿主机都可以支持非常多的CPU数量和非常大量的内存。例如,Redhat官方文档就介绍过,RHEL 6.x系统中的一个KVM客户机可以支持160个虚拟CPU和多达2TB的内存,KVM宿主机支持4096个CPU核心和多达64TB的内存。
KVM局限性
一、CPU过载使用
KVM允许过载使用CPU,但是过载能力有限,过载使用不但不会提升性能反而会降低性能。一般所有虚拟CPU数量加在一起不要大于物理CPU核心数,一旦超过物理CPU数量依然需要调度。
二、虚拟化时间需要依赖外部时钟才能实现精确计时
Linux系统有个特性,它有两套时钟,一套是硬件时钟、另一套是系统启动时从硬件读取的时间称为系统时间。当系统一旦启动后,系统时间就开始自己记时了,根据CPU震荡频率来计时,比如是一个2G赫兹的CPU,那么系统就认为1s中震荡2G个时钟周期,它就认为时间过1s,计时非常精确。但是很遗憾的是,一旦我们做了虚拟化,就意味着这颗CPU未必就是供这一个虚拟机所使用的,比如2G赫兹的CPU,这个虚拟机只得到了1G赫兹,那么此虚拟化还是以2G赫兹为1s计时,就会比正常时间整整慢一半。所以任何虚拟机的时钟都不会精确,包括vmware workstations(vmware提供的vmware tools工具就是实现把虚拟机时间一直跟系统时间同步),一般所有虚拟化都需要提供一个时钟服务器,一直同步这个比较精确的时间。
三、MAC地址
KVM的MAC地址分配机制跟vmare一样,前24位固定,后24后随机。当虚拟机量特别大时,可能会出现MAC地址冲突。
四、性能影响
对于CPU MMU来讲,在完全虚拟化模式下,性能大概有10%的损耗;如果支持EPT技术以及硬件辅助虚拟化技术,性能损耗大概在5%左右。
对于网络IO在完全虚拟化模式下,只相当于物理硬件性能的60%左右;半虚拟化模式下75%;透传模式下95%。
对于磁盘IO如果使用模拟的方式,只相当于物理硬件性能的40%左右;如果使用半虚拟化性能在85%左右,所以磁盘IO是最需要半虚拟化的;如果是透传大概在95%左右。
对于显卡设备模拟,相当于物理硬件设备的50%左右;然后半虚拟化是不支持的。
对于时间计时在完全虚拟化模式下,是不可能精确;在半虚拟化模式下,可以做到精确,因为它有一个特殊模块来完成计时辅助。