2、KVM2.1、KVM详解2.1.1、简介

KVM全称是基于内核的虚拟机(Kernel-basedVirtualMachine),最初由以色列的公司Qumranet开发。KVM于2006年12月被合并在发布于2007年2月的内核中。RedHat公司在2008年9月收购Qumranet公司后,在RHEL6及以后发行版中使用KVM作为默认的虚拟化引擎。

KVM是x86架构且硬件支持虚拟化技术(intelVT或AMD-V)的Linux全虚拟化解决方案,它包含一个为处理器提供底层虚拟化、可加载的核心模块(或)。KVM本身不执行任何硬件模拟,需要修改过的QEMU向它提供模拟的I/O。

2.1.2、架构

2.2、KVM和QEMU

QEMU是一个开源的模拟器,作者是法布里斯·贝拉(FabriceBellard)。QEMU可以模拟完整的硬件环境,与Bochs,PearPC类似,但具有高速度、跨平台等特性。由于QEMU是纯软件模拟,GuestOS的指令都需要QEMU转义给真正的硬件,因而性能较差。

KVM只是一个内核模块,本身只能提供CPU和内存的虚拟化,没有用户空间的管理工具,需要QEMU为其提供I/O支持。

在的时候出现了QEMU-KVM分支,发布了三个正式版本(1.1/1.2/1.3)后,与QEMU主版本合并了。所以,现在的QEMU默认就支持QEMU-KVM。

Qemu是纯软件实现的虚拟化模拟器,几乎可以模拟任何硬件设备,我们最熟悉的就是能够模拟一台能够独立运行操作系统的虚拟机,虚拟机认为自己和硬件打交道,但其实是和Qemu模拟出来的硬件打交道,Qemu将这些指令转译给真正的硬件。

正因为Qemu是纯软件实现的,所有的指令都要经Qemu过一手,性能非常低,所以,在生产环境中,大多数的做法都是配合KVM来完成虚拟化工作,因为KVM是硬件辅助的虚拟化技术,主要负责比较繁琐的CPU和内存虚拟化,而Qemu则负责I/O虚拟化,两者合作各自发挥自身的优势,相得益彰。

从本质上看,虚拟出的每个虚拟机对应host上的一个Qemu进程,而虚拟机的执行线程(如CPU线程、I/O线程等)对应Qemu进程的一个线程。下面通过一个虚拟机启动过程看看Qemu是如何与KVM交互的。

2.2.1、交互过程
//第一步,获取到KVM句柄kvmfd=open("/dev/kvm",O_RDWR);//第二步,创建虚拟机,获取到虚拟机句柄。vmfd=ioctl(kvmfd,KVM_CREATE_VM,0);//第三步,为虚拟机映射内存,还有其他的PCI,信号处理的初始化。ioctl(kvmfd,KVM_SET_USER_MEMORY_REGION,mem);//第四步,将虚拟机镜像映射到内存,相当于物理机的boot过程,把镜像映射到内存。//第五步,创建vCPU,并为vCPU分配内存空间。ioctl(kvmfd,KVM_CREATE_VCPU,vcpuid);vcpu-kvm_run_mmap_size=ioctl(kvm-dev_fd,KVM_GET_VCPU_MMAP_SIZE,0);//第五步,创建vCPU个数的线程并运行虚拟机。ioctl(kvm-vcpus-vcpu_fd,KVM_RUN,0);//第六步,线程进入循环,并捕获虚拟机退出原因,做相应的处理。for(;;){ioctl(KVM_RUN)switch(exit_reason){caseKVM_EXIT_IO:/**/caseKVM_EXIT_HLT:/**/}}//这里的退出并不一定是虚拟机关机,//虚拟机如果遇到I/O操作,访问硬件设备,缺页中断等都会退出执行,//退出执行可以理解为将CPU执行上下文返回到Qemu。
2.2.2、Qemu源码结构

Qemu软件虚拟化实现的思路是采用二进制指令翻译技术,主要是提取guest代码,然后将其翻译成TCG中间代码,最后再将中间代码翻译成host指定架构的代码,如x86体系就翻译成其支持的代码形式,ARM架构同理。

所以,从宏观上看,源码结构主要包含以下几个部分:

/:最主要的模拟循环,虚拟机环境初始化,和CPU的执行。

/target-arch/:将guest代码翻译成不同架构的TCG操作码。

/tcg/:主要的TCG代码。

/tcg/arch/:将TCG代码转化生成主机代码。

/:主要寻找下一个二进制翻译代码块,如果没有找到就请求得到下一个代码块,并且操作生成的代码块。

其中,涉及的主要几个函数如下:

函数

路径

注释

main_loop

{/}

很多条件的判断,如电源是否断等

qemu_main_loop_start

{/}

分时运行CPU核

structCPUState

{/target-xyz/}

CPU状态结构体

cpu_exec

{/}

主要的执行循环

structTranslationBlock

{/}

TB(二进制翻译代码块)结构体

cpu_gen_code

{}

初始化真正代码生成

tcg_gen_code

{/tcg/}

tcg代码翻译成host代码

知道了这个总体的代码结构,再去具体了解每一个模块可能会相对容易一点。

2.2.3、Qemu的使用2.2.3.1、源码下载
centos:sudoapt-getinstallqemuubuntu:sudoyuminstallqemu-y安装包:$wget$:$gitclonegit:///
2.2.3.2、编译及安装
$//如果使用的是git下载的源码,执行cdqemu$./configure--enable-kvm--enable-debug--enable-vnc--enable-werror--target-list="x86_64-softmmu"$make-j8$sudomakeinstall

configure脚本用于生成Makefile,其选项可以用./configure--help查看。

这里使用到的选项含义如下:

--enable-kvm:编译KVM模块,使Qemu可以利用KVM来访问硬件提供的虚拟化服务。

--enable-vnc:启用VNC。

--enalbe-werror:编译时,将所有的警告当作错误处理。

--target-list:选择目标机器的架构。默认是将所有的架构都编译,但为了更快的完成编译,指定需要的架构即可。

安装好之后,会生成如下应用程序:

ivshmem-client/server:这是一个guest和host共享内存的应用程序,遵循C/S的架构。

qemu-ga:这是一个不利用网络实现guest和host之间交互的应用程序(使用virtio-serial),运行在guest中。

qemu-io:这是一个执行QemuI/O操作的命令行工具。

qemu-system-x86_64:Qemu的核心应用程序,虚拟机就由它创建的。

qemu-img:创建虚拟机镜像文件的工具,下面有例子说明。

qemu-nbd:磁盘挂载工具。

下面通过创建虚拟机操作来对这些工具有个初步的认识。

2.2.3.3、创建虚拟机

使用qemu-img创建虚拟机镜像

虚拟机镜像用来模拟虚拟机的硬盘,在启动虚拟机之前需要创建镜像文件。

-f选项用于指定镜像的格式,qcow2格式是Qemu最常用的镜像格式,采用来写时复制技术来优化性能。是镜像文件的名字,10G是镜像文件大小。镜像文件创建完成后,可使用qemu-system-x86来启动x86架构的虚拟机.

使用qemu-system-x86来启动x86架构的虚拟机

Copyqemu-system-x86_64

因为中并未给虚拟机安装操作系统,所以会提示“Nobootabledevice”,无可启动设备。

启动VM安装操作系统镜像

Copyqemu-system-x86_64-/Centos-Desktop-x86_64-20-1.iso

-m指定虚拟机内存大小,默认单位是MB,-enable-kvm使用KVM进行加速,-cdrom添加fedora的安装镜像。可在弹出的窗口中操作虚拟机,安装操作系统,安装完成后重起虚拟机便会从硬盘()启动。之后再启动虚拟机只需要执行:

Copyqemu-system-x86_64-

qemu-img支持非常多种的文件格式,可以通过qemu-img-h查看.其中raw和qcow2是比较常用的两种,raw是qemu-img命令默认的,qcow2是qemu目前推荐的镜像格式,是功能最多的格式。这些知识后面会有文章来专门讲述。

2.3、KVM和Libvirt

libvirt是一套实现Linux虚拟化功能的开源API,旨在提供一种单一的方式管理多种不同的虚拟化方案。libvirt由一套API库,一个libvirtd服务,以及一个virsh命令行管理工具组成。虽然libvirt是C开发的,但是可以很好的支持主流的编程语言,包括C,Python,Perl,Java等等。

最新的发行版还包含了一系列基于libvirt的工具,用于简化虚拟机的维护管理:

virt-install:一个创建虚拟机的工具,支持从本地镜像或者网络镜像(NFS、FTP等等)启动。

virsh:一个交互式/批处理shell工具,可以用于完成虚拟机的日常管理工作。

virt-manager:一个通用的图形化管理工具,可以用来管理本地或远程的Hypervisor及其虚拟机。

virt-viewer:一个轻量级的、能够安全连接到远程虚拟机的图形控制台工具。

简单的说,它是一系列提供出来的库函数,用以其他技术调用,来管理机器上的虚拟机。包括各种虚拟机技术,kvm、xen与lxc等,都可以调用libvirt提供的api对虚拟机进行管理。有这么多的虚拟机技术,它为何能提供这么多的管理功能那。是因为它的设计理念,它是面向驱动的架构设计。对任何一种虚拟机技术都开发设计相对于该技术的驱动。这样不同虚拟机技术就可以使用不同驱动,而且相互直接不会影响,方便扩展。而且libvirt提供了多种语言的编程接口,可以直接通过编程,调用libvirt提供的对外接口实现对虚拟机的操作。如今流行的云计算中的IaaS是与该库联系相当密切的。通过下图可以看出它的架构设计思想。

2.4、KVM-QEMU-libvirt关系图

2.5、KVM与Hypervisor

KVM是hypervisor的一种实现,开源的

2.5.1、Hypervisor是什么

Hypervisor是一种运行在物理服务器和操作系统之间的中间软件层(可以是软件程序,也可以是固件程序),可允许多个操作系统和应用共享一套基础物理硬件,因此也可以看作是虚拟环境中的“元”操作系统,它可以协调访问服务器上的所有物理设备和虚拟机,也叫虚拟机监视器VMM(VirtualMachineMonitor)。

Hypervisor是所有虚拟化技术的核心。非中断地支持多工作负载迁移的能力是Hypervisor的基本功能。当服务器启动并执行Hypervisor时,它会给每一台虚拟机分配适量的内存、CPU、网络和磁盘,并加载所有虚拟机的客户操作系统。

Hypervisor翻译过来就是超级监督者,被引申用为超级管理程序、超多功能管理器、虚拟机管理器、VMM。

2.5.2、Hypervisor分类2.5.2.1、Type-I(裸金属型)

指VMM直接运作在裸机上,使用和管理底层的硬件资源,GuestOS对真实硬件资源的访问都要通过VMM来完成,作为底层硬件的直接操作者,VMM拥有硬件的驱动程序。裸金属虚拟化中Hypervisor直接管理调用硬件资源,不需要底层操作系统,也可以理解为Hypervisor被做成了一个很薄的操作系统。这种方案的性能处于主机虚拟化与操作系统虚拟化之间。

2.5.2.2、Type-II型(宿主型)

指VMM之下还有一层宿主操作系统,由于GuestOS对硬件的访问必须经过宿主操作系统,因而带来了额外的性能开销,但可充分利用宿主操作系统提供的设备驱动和底层服务来进行内存管理、进程调度和资源管理等。主机虚拟化中VM的应用程序调用硬件资源时需要经过:VM内核-Hypervisor-主机内核,导致性能较差。

2.6、KVM使用

创建KVM虚拟机常用的方法:

使用qemu-kvm命令创建虚拟机;

使用virt-manager工具创建虚拟机;

使用virsh工具创建虚拟机;

使用Python调用libvirt接口创建虚拟机。

2.6.1、准备磁盘镜像

创建KVM虚拟机前需准备虚拟机的磁盘镜像。虚拟机镜像用来模拟虚拟机的硬盘,在启动虚拟机之前需要创建镜像文件。两种常用方法:

使用qemu-img命令创建虚拟机镜像:

virt-manager

2.6.2.3、使用virsh工具创建虚拟机

使用virsh工具来创建虚拟机的话,需要再准备一个xml配置文件。这个xml文件对要创建的虚拟机进行了详细的配置。具体xml内容与配置方法可以参考libvirt相关文档。()

创建虚拟机命令:

[root@localhost~]#

其中,定义了要创建的虚拟机配置信息。

2.6.2.4、使用Python调用libvirt接口创建虚拟机

libvirt提供了支持主流编程语言的库,本文以Python为例,介绍创建虚拟机的过程。

参考:

【虚拟机】虚拟化技术以及KVM、QEMU与libvirt介绍_libvirt介绍和使用-CSDN博客