带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

点击查看第一章
点击查看第二章

第3章

构建KVM环境
通过第2章了解KVM的基本原理之后,你是否迫不及待地想实践一下如何使用KVM来构建自己的虚拟化环境呢?
本章将介绍如何通过整套的流程与方法来构建KVM环境,其中包括:硬件系统的配置、宿主机(Host)操作系统的安装、KVM的编译与安装、QEMU的编译与安装、客户机(Guest)的安装,直到最后启动你的第一个KVM客户机。

3.1 硬件系统的配置

我们知道,KVM从诞生伊始就需要硬件虚拟化扩展的支持,所以这里需要特别讲解一下硬件系统的配置。
KVM最初始的开发是基于x86和x86-64处理器架构上的Linux系统进行的,目前,KVM被移植到多种不同处理器架构之上,包括AIM联盟(Apple–IBM–Motorola)的PowerPC架构、IBM的S/390架构、ARM架构(2012年开始)等。其中,在x86-64上面的功能支持是最完善的(主要原因是Intel/AMD的x86-64架构在桌面和服务器市场上的主导地位及其架构的开放性,以及它的开发者众多),本书也采用基于Intel x86-64架构的处理器作为基本的硬件环境。
在x86-64架构的处理器中,KVM需要的硬件虚拟化扩展分别为Intel的虚拟化技术(Intel VT)和AMD的AMD-V技术。其中,Intel在2005年11月发布的奔腾四处理器(型号:662 和672)中第一次正式支持VT技术(Virtualization Technology),之后不久的2006年5月AMD也发布了支持AMD-V的处理器。现在比较流行的针对服务器和桌面的Intel处理器多数都是支持VT技术的,本节着重讲述与英特尔的VT技术相关的硬件设置。
首先处理器(CPU)要在硬件上支持VT技术,还要在BIOS中将其功能打开,KVM才能使用到。目前,多数流行的服务器和部分桌面处理器的BIOS都默认将VT打开了。
在BIOS中,VT的选项通过“Advanced→Processor Configuration”来查看和设置,它的标识通常为“Intel(R) Virtualization Technology”或“Intel VT”等类似的文字说明。
除了支持必需的处理器虚拟化扩展以外,如果服务器芯片还支持VT-d(Virtualization Technology for Directed I/O),建议在BIOS中将其打开,因为后面一些相对高级的设备的直接分配功能会需要硬件VT-d技术的支持。VT-d是对设备I/O的虚拟化硬件支持,在BIOS中的位置可能为“Advanced→Processor Configuration”或“Advanced→System Agent (SA) Configuration”,它在BIOS中的标志一般为“Intel(R) VT for Directed I/O”或“Intel VT-d”。
下面以一台Intel Haswell-UP平台的服务器为例,来说明在BIOS中的设置。
1)BIOS中的Advanced选项,如图3-1所示。

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

2)BIOS中Enabled的VT和VT-d选项,如图3-2所示。

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

对于不同平台或不同厂商的BIOS,VT和VT-d等设置的位置可能是不一样的,需要根据实际的硬件情况和BIOS中的选项来灵活设置。
设置好了VT和VT-d的相关选项,保存BIOS的设置并退出,系统重启后生效。在Linux系统中,可以通过检查/proc/cpuinfo文件中的CPU特性标志(flags)来查看CPU目前是否支持硬件虚拟化。在x86和x86-64平台中,Intel系列CPU支持虚拟化的标志为“vmx”,AMD系列CPU的标志为“svm”。所以可以用以下命令行查看“vmx”或者“svm”标志:
[root@kvm-host ~]# grep -E "svm|vmx" /proc/cpuinfo
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm ida arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt

3.2 安装宿主机Linux系统

KVM是基于内核的虚拟化技术的,要运行KVM虚拟化环境,安装一个Linux操作系统的宿主机(Host)是必需的。由于Redhat公司是目前对KVM项目投入最多的企业之一,从RHEL 6(RedHat Enterprise Linux 6)开始,其系统自带的虚拟化方案就采用了KVM;而从RHEL 7开始,更是只支持KVM的虚拟化。而且RHEL也是最流行的企业级Linux发行版之一,所以本节选用RHEL来讲解Linux系统的安装步骤和过程,并且本章后面的编译和运行都是在这个系统上进行的。
当然,KVM作为流行的开源虚拟机之一,可以在绝大多数流行的Linux系统上编译和运行,所以依然可以选择RHEL之外的其他Linux发行版,如CentOS、Fedora、Ubuntu、Debian、OpenSuse等系统都是不错的选择。
本节内容基于目前最新的RHEL版本—RHEL 7.3 Server版的系统来简单介绍,普通Linux安装的基本过程不再详细描述,这里主要说明安装过程中一些值得注意的地方。
在选择哪些安装包(SOFTWARE SELECTION)时(图3-3),点进去选择“Server with GUI”,而不是默认的“Minimal Install”,如图3-4所示。

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境


在选择了“Server with GUI”之后,右侧还有可以额外增加的组件供选择(见图3-4),我们需要选上“Development Tools”,因为在本书的KVM编译过程中以及其他实验中可能会用到,其中包括一些比较重要的软件包,比如:gcc、git、make等(一般被默认选中)。可以看到还有“Virtualization Hypervisor”“Virtualization Tools”,这里可以暂时不选它们(选上也没有关系),因为在本章中会自己编译KVM和QEMU,而在附录A介绍发行版中的KVM时,我们会安装Virtualization Host环境,并使用发行版中自带的KVM Virtualization功能。

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

然后,单击“Done”按钮并继续进行后面的安装流程。可以安装相应的软件包,安装过程的一个快照如图3-5所示。
在安装完所有软件包后,系统会提示安装完成需要重启系统,重启后即可进入RHEL 7.3系统中。至此,Linux系统就安装完毕了,这就是在本书中作为宿主机(Host)的操作系统,后面的编译和实验都是在这个宿主机上进行的(当然,我们会使用本章讲述的自己编译的kernel和QEMU来进行实验)。


带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

3.3 编译和安装KVM

3.3.1 下载KVM源代码

KVM作为Linux kernel中的一个module而存在,是从Linux 2.6.20版本开始被完全正式加入内核的主干开发和正式发布代码中。所以,只需要下载2.6.20版本,Linux kernel代码即可编译和使用KVM。当然,如果是为了学习KVM,推荐使用最新正式发布或者开发中的kernel版本,如果是实际部署到生产环境中,还需要自己选择适合的稳定版本进行详尽的功能和性能测试。如果你想使用最新的处于开发中的KVM代码,需要自己下载KVM的代码仓库,本节就是以此为例来讲解的。
总的来说,下载最新KVM源代码,主要有以下3种方式:
1)下载KVM项目开发中的代码仓库kvm.git。
2)下载Linux内核的代码仓库linux.git。
3)打包下载Linux内核的源代码(Tarball格式)。
1.下载kvm.git
KVM项目的代码是托管在Linux内核官方源码网站http://git.kernel.org
上的,可以到上面查看和下载。该网页上virt/kvm/kvm.git 即KVM项目的代码,它是最新的、功能最丰富的KVM源代码库(尽管并非最稳定的)。目前,kvm.git的最主要维护者(maintainer)是来自Redhat公司的Paolo Bonzini和Radim Krˇcmáˇr。从http://git.kernel.org/?p=virt/kvm/kvm.git
网页可以看到,kvm.git的下载链接有以下3个URL,可用于下载最新的KVM的开发代码仓库。
git://git.kernel.org/pub/scm/virt/kvm/kvm.git
http://git.kernel.org/pub/scm/virt/kvm/kvm.git
https://git.kernel.org/pub/scm/virt/kvm/kvm.git
这3个URL下载的内容完全一致,根据自己实际情况选择其中一个下载即可。Linux内核相关的项目一般都使用Git作为源代码管理工具,KVM当然也是用Git管理源码的。可以使用git clone命令来下载KVM的源代码,也可以使用Git工具的其他命令对源码进行各种管理。这里不详述Git的各种命令,有兴趣的读者可以参考其他文稿。
kvm.git的下载方式和过程为以下命令行所示:
[root@kvm-host ~]# git clone
git://git.kernel.org/pub/scm/virt/kvm/kvm.git
Cloning into 'kvm'...
remote: Counting objects: 5017872, done.
remote: Compressing objects: 100% (938249/938249), done.
Receiving objects: 100% (5017872/5017872), 1006.69 MiB | 60.72 MiB/s, done.
remote: Total 5017872 (delta 4229078), reused 4826094 (delta 4038351)
Resolving deltas: 100% (4229078/4229078), done.
Checking out files: 100% (55914/55914), done.
[root@kvm-host ~]# cd kvm/
[root@kvm-host kvm]# pwd
/root/kvm
2.下载linux.git
Linux内核的官方网站为http://kernel.org
其中源代码管理网站为http://git.kernel.org
可以在那里找到最新的linux.git代码。在源码管理网站上,我们看到有多个linux.git,我们选择Linus Torvalds的源码库(也即是Linux内核的主干)。在内核源码的网页http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git 中可以看到,其源码仓库也有以下3个链接可用:
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
这3个URL中源码内容是完全相同的,可以使用git clone命令复制到本地,其具体操作方式与前一种(kvm.git)的下载方式完全一样。
3.下载Linux的Tarball
在Linux官方网站(http://kernel.org
上,也提供Linux内核的Tarball文件下载。除了在其首页上单击一些Tarball之外,也可以到以下网址下载Linux内核的各个版本的Tarball:
□ftp://ftp.kernel.org/pub/linux/kernel。
http://www.kernel.org/pub/linux/kernel
kernel.org还提供一种rsync的方式下载,此处不详细叙述,请参见其官网首页的提示。
以用wget下载linux-4.8.1.tar.xz 为例,命令行代码如下:
[root@kvm-host ~]# wget
https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.8.1.tar.xz

4.通过kernel.org的镜像站点下载
由于Linux的源代码量比较大,如果只有美国一个站点可供下载,那么速度会较慢,服务器压力也较大。所以,kernel.org在世界上多个国家和地区都有一些镜像站点,而且一些Linux开源社区的爱好者们也自发建立了不少kernel.org的镜像,在中国的镜像站点中,推荐大家从以下两个镜像站点下载Linux相关的代码及其他源码,访问速度比较快。
□清华大学开源镜像站:http://mirror.tuna.tsinghua.edu.cn
其中的链接地址https://mirror.tuna.tsinghua.edu.cn/kernel
http://www.kernel.org/pub/linux/kernel
是同步的,用起来比较方便。
□北京交通大学的一个开源镜像站:http://mirror.bjtu.edu.cn/kernel/linux/kernel
还有以下两个镜像站推荐给大家:
□网易开源镜像站,http://mirrors.163.com
□搜狐开源镜像站,http://mirrors.sohu.com

3.3.2 配置KVM

上面3种方式下载的源代码都可以同样地进行配置和编译,本章以开发中的最新源代码仓库kvm.git来讲解KVM的配置和编译等。KVM是作为Linux内核中的一个module而存在的,而kvm.git是一个包含了最新的KVM模块开发中代码的完整的Linux内核源码仓库。它的配置方式与普通的Linux内核配置完全一样,只是需要注意将KVM相关的配置选择为编译进内核或者编译为模块。
在kvm.git(Linux kernel)代码目录下,运行“make help”命令可以得到一些关于如何配置和编译kernel的帮助手册。命令行如下:

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境


对KVM或Linux内核配置时常用的一些配置命令解释如下。
1)make config:基于文本的最为传统也是最为枯燥的一种配置方式,但是它可以适用于任何情况之下。这种方式会为每一个内核支持的特性向用户提问,如果用户回答“y”,则把特性编译进内核;回答“m”,则把特性作为模块进行编译;回答“n”,则表示不对该特性提供支持;输入“?”则显示该选项的帮助信息。在了解之后再决定处理该选项的方式。在回答每个问题前必须考虑清楚,如果在配置过程中因为失误而给了错误的回答,就只能按“Ctrl+c”组合键强行退出然后重新配置了。
2)make oldconfig:make oldconfig和make config类似,但是它的作用是在现有的内核设置文件基础上建立一个新的设置文件,只会向用户提供有关新内核特性的问题。在新内核升级的过程中,make oldconfig非常有用,用户将现有的配置文件.config复制到新内核的源码中,执行make oldconfig,此时,用户只需要回答那些针对新增特性的问题。
3)make silentoldconfig:和上面make oldconfig一样,只是额外悄悄地更新选项的依赖关系。
4)make olddefconfig:和上面make silentoldconfig一样,但不需要手动交互,而是对新选项以其默认值配置。
5)make menuconfig:基于终端的一种配置方式,提供了文本模式的图形用户界面,用户可以通过移动光标来浏览所支持的各种特性。使用这种配置方式时,系统中必须安装ncurses库,否则会显示“Unable to find the ncurses libraries”的错误提示。其中“Y”“N”“M”“?”输入键的选择功能与前面make config中介绍的一致。
6)make xconfig:基于X Window的一种配置方式,提供了漂亮的配置窗口,不过只能在X Server上运行X桌面应用程序时使用。它依赖于QT,如果系统中没有安装QT库,则会出现“Unable to find any QT installation”的错误提示。
7)make gconfig:与make xconfig类似,不同的是make gconfig依赖于GTK库。
8)make defconfig:按照内核代码中提供的默认配置文件对内核进行配置(在Intel x86-64平台上,默认配置为arch/x86/configs/x86_64_defconfig),生成.config文件可以用作初始化配置,然后再使用make menuconfig进行定制化配置。
9)make allyesconfig:尽可能多地使用“y”输入设置内核选项值,生成的配置中包含了全部的内核特性。
10)make allnoconfig:除必需的选项外,其他选项一律不选(常用于嵌入式Linux系统的编译)。
11)make allmodconfig:尽可能多地使用“m”输入设置内核选项值来生成配置文件。
12)make localmodconfig:会执行 lsmod 命令查看当前系统中加载了哪些模块(Modules),并最终将原来的.config 中不需要的模块去掉,仅保留前面 lsmod 命令查出来的那些模块,从而简化了内核的配置过程。这样做确实方便了很多,但是也有个缺点:该方法仅能使编译出的内核支持当前内核已经加载的模块。因为该方法使用的是 lsmod 查询得到的结果,如果有的模块当前没有被加载,那么就不会编到新的内核中。
下面以make menuconfig为例,介绍一下如何选择KVM相关的配置(系统中要安装好ncurses-devel包)。运行make menuconfig后显示的界面如图3-6所示。
选择了Virtualization之后,进入其中进行详细配置,包括选中KVM、选中对处理器的支持(比如:KVM for Intel processors support,KVM for AMD processors support)等,如图3-7所示。

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

提示:为了确保生成的.config文件生成的kernel是实际可以工作的(直接make defconfig 生成的.config文件编译出来的kernel常常是不能工作的),最佳实践是以你当前使用的config(比如,我们安装好RHEL 7.3的OS以后,/boot/config-3.10.0-xxx.x86_64)为基础,将它复制到你的linux 目录下,重命名为.config,然后通过make olddefconfig更新补充一下这个.config。
在配置完成之后,就会在kvm.git目录下面生成一个.config文件。最好检查一下KVM相关的配置是否正确。在本次配置中,与KVM直接相关的几个配置项主要情况如下:

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

3.3.3 编译KVM

在对KVM源代码进行了配置之后,编译KVM就是一件比较容易的事情了。它的编译过程完全是一个普通Linux内核编译的过程,需要经过编译kernel、编译bzImage和编译module等3个步骤。编译bzImage这一步不是必需的,在本章示例中,config中使用了initramfs,所以这里需要这个bzImage,用于生成initramfs image。另外,在最新的Linux kernel代码中,根据makefile中的定义可以看出,直接执行“make”或“make all”命令就可以将这里提及的3个步骤全部包括在内。本节是为了更好地展示编译的过程,才将编译的步骤分为这3步来解释。
1)编译kernel的命令为“make vmlinux”,其编译命令和输出如下:
[root@kvm-host kvm]# make vmlinux -j 20

LINK    vmlinux
LD      vmlinux.o
MODPOST vmlinux.o
GEN     .version
CHK     include/generated/compile.h
UPD     include/generated/compile.h
CC      init/version.o
LD      init/built-in.o
KSYM    .tmp_kallsyms1.o
KSYM    .tmp_kallsyms2.o
LD      vmlinux #这里就是编译、链接后生成了启动所需的Linux kernel文件
SORTEX  vmlinux
SYSMAP  System.map 

其中,编译命令中的“-j”参数并非必需的,它是让make工具用多任务(job)来编译。比如,上面命令中提到的“-j 20”,会让make工具最多创建20个GCC进程,同时来执行编译任务。在一个比较空闲的系统上,有一个推荐值作为-j参数的值,即大约为2倍于系统上的CPU的core的数量(CPU超线程也算core)。如果-j后面不跟数字,则make会根据现在系统中的CPU core的数量自动安排任务数(通常比core的数量略多一点)。
2)执行编译bzImage的命令“make bzImage”,其输出如下:
[root@kvm-host kvm]# make bzImage

CHK     include/config/kernel.release
CHK     include/generated/uapi/linux/version.h
CHK     include/generated/utsrelease.h

LD      arch/x86/boot/setup.elf
OBJCOPY arch/x86/boot/setup.bin
OBJCOPY arch/x86/boot/vmlinux.bin
HOSTCC  arch/x86/boot/tools/build
BUILD   arch/x86/boot/bzImage #这里生成了我们需要的bzImage文件

Setup is 17276 bytes (padded to 17408 bytes).
System is 5662 kB
CRC 3efff614
Kernel: arch/x86/boot/bzImage is ready (#2)
3)编译kernel和bzImage之后编译内核的模块,命令为“make modules”,其命令行输出如下:
[root@kvm-host kvm]# make modules -j 20

IHEX2FW firmware/emi26/loader.fw
IHEX2FW firmware/emi26/firmware.fw
IHEX2FW firmware/emi26/bitstream.fw
IHEX2FW firmware/emi62/loader.fw
IHEX2FW firmware/emi62/bitstream.fw
IHEX2FW firmware/emi62/spdif.fw
IHEX2FW firmware/emi62/midi.fw
H16TOFW firmware/edgeport/boot2.fw
H16TOFW firmware/edgeport/boot.fw
H16TOFW firmware/edgeport/down.fw
H16TOFW firmware/edgeport/down2.fw
IHEX2FW firmware/whiteheat_loader.fw
IHEX2FW firmware/whiteheat.fw
IHEX2FW firmware/keyspan_pda/keyspan_pda.fw
IHEX2FW firmware/keyspan_pda/xircom_pgs.fw 

3.3.4 安装KVM

编译完KVM之后,下面介绍如何安装KVM。
KVM的安装包括两个步骤:安装module,安装kernel与initramfs。
1.安装module
通过“make modules_install”命令可以将编译好的module安装到相应的目录中,默认情况下module被安装到/lib/modules/$kernel_version/kernel目录中。
[root@kvm-host kvm]# make modules_install

INSTALL /lib/firmware/whiteheat.fw
INSTALL /lib/firmware/keyspan_pda/keyspan_pda.fw
INSTALL /lib/firmware/keyspan_pda/xircom_pgs.fw
DEPMOD  4.8.0+ 

安装好module之后,可以查看一下相应的安装路径,可看到kvm模块也已经安装。如下所示:
[root@kvm-host kvm]# ll /lib/modules/4.8.0+/kernel/
total 16
drwxr-xr-x 3 root root 16 Oct 15 15:05 arch
drwxr-xr-x 3 root root 4096 Oct 15 15:05 crypto
drwxr-xr-x 66 root root 4096 Oct 15 15:06 drivers
drwxr-xr-x 26 root root 4096 Oct 15 15:06 fs
drwxr-xr-x 3 root root 18 Oct 15 15:06 kernel
drwxr-xr-x 4 root root 152 Oct 15 15:06 lib
drwxr-xr-x 2 root root 31 Oct 15 15:06 mm
drwxr-xr-x 32 root root 4096 Oct 15 15:06 net
drwxr-xr-x 10 root root 135 Oct 15 15:06 sound
drwxr-xr-x 3 root root 16 Oct 15 15:06 virt
[root@kvm-host kvm]# ll /lib/modules/4.8.0+/kernel/arch/x86/kvm/
total 11256
-rw-r--r-- 1 root root 1940806 Oct 15 15:05 kvm-intel.ko
-rw-r--r-- 1 root root 9583878 Oct 15 15:05 kvm.ko
2.安装kernel和initramfs
通过“make install”命令可以安装kernel和initramfs,命令行输出如下:
[root@kvm-host kvm]# make install
sh ./arch/x86/boot/install.sh 4.8.0+ arch/x86/boot/bzImage \

System.map "/boot" 

[root@kvm-host kvm]# ll /boot -t
......
drwx------. 6 root root 103 Oct 15 15:12 grub2
-rw-r--r-- 1 root root 58106303 Oct 15 15:11 initramfs-4.8.0+.img
lrwxrwxrwx 1 root root 23 Oct 15 15:10 System.map -> /boot/System.map-4.8.0+
lrwxrwxrwx 1 root root 20 Oct 15 15:10 vmlinuz -> /boot/vmlinuz-4.8.0+
-rw-r--r-- 1 root root 3430941 Oct 15 15:10 System.map-4.8.0+
-rw-r--r-- 1 root root 5815104 Oct 15 15:10 vmlinuz-4.8.0+
可见,在/boot目录下生成了内核(vmlinuz)和initramfs等内核启动所需的文件。
在运行make install之后,在grub配置文件(如:/boot/grub2/grub.cfg)中也自动添加了一个grub选项,如下所示:
menuentry 'Redhat Enterprise Linux Server (4.8.0+) 7.2 (Maipo)' ... {

load_video
insmod gzio
insmod part_msdos
insmod xfs
set root='hd1,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
    search --no-floppy --fs-uuid --set=root --hint-bios=hd1,msdos1 --hint-efi=hd1, msdos1 --hint-baremetal=ahci1,msdos1  da2e2d53-4b33-4bfe-a649- 73fba55a7a9d
else
    search --no-floppy --fs-uuid --set=root da2e2d53-4b33-4bfe-a649-73fba55a7a9d
fi
linux16 /vmlinuz-4.8.0+ root=/dev/mapper/rhel-root ro rd.lvm.lv=rhel/root crashkernel=auto rd.lvm.lv=rhel/swap vconsole.font=latarcyrheb-sun16 vconsole.keymap=us rhgb /dev/disk/by-uuid/19d79b0d-898f-4d34-a895-c842fa65e9b9 LANG=en_US.UTF-8 console=ttyS0,115200 console=tty0 intel_iommu=on
initrd16 /initramfs-4.8.0+.img

}
检查了grub之后,重新启动系统,选择刚才为了KVM而编译、安装的内核启动。
系统启动后,登录进入系统,通常情况下,系统启动时默认已经加载了kvm和kvm_intel这两个模块。如果没有加载,手动用modprobe命令依次加载kvm和kvm_intel模块。
[root@kvm-host kvm]# modprobe kvm
[root@kvm-host kvm]# modprobe kvm_intel
[root@kvm-host kvm]# lsmod | grep kvm
kvm_intel 192512 0
kvm 577536 1 kvm_intel
确认KVM相关的模块加载成功后,检查/dev/kvm这个文件,它是kvm内核模块提供给用户空间的QEMU程序使用的一个控制接口,它提供了客户机(Guest)操作系统运行所需要的模拟和实际的硬件设备环境。
[root@kvm-host kvm]# ls -l /dev/kvm
crw-rw-rw-+ 1 root kvm 10, 232 Oct 9 15:22 /dev/kvm

3.4 编译和安装QEMU

除了在内核空间的KVM模块之外,在用户空间需要QEMU来模拟所需要的CPU和设备模型,以及启动客户机进程,这样才有了一个完整的KVM运行环境。
在编译和安装了KVM并且启动到编译的内核之后,下面来看一下QEMU的编译和安装。

3.4.1 曾经的qemu-kvm

在上一版中,我们是以qemu-kvm为例来讲解QEMU/KVM的。qemu-kvm原本是kernel社区维护的专门用于KVM的QEMU的分支。
在2012年年末的时候,这个分支并入了主流的QEMU(git://git.qemu-project.org/qemu.git)。从此,不再需要特殊的qemu-kvm,而只是通用的QEMU加上--enable-kvm选项就可以创建KVM guest了。

3.4.2 下载QEMU源代码

在并入主流QEMU以后,目前的QEMU项目针对KVM/x86的部分依然是由Redhat公司的 Paolo Bonzini作为维护者(Maintainer),代码的git url托管在qemu-project.org上。
QEMU开发代码仓库的网页连接为:http://git.qemu.org/qemu.git
其中,可以看到有如下2个URL链接可供下载开发中的最新qemu-kvm的代码仓库。
git://git.qemu.org/qemu.git
http://git.qemu.org/git/qemu.git
可以根据自己实际需要选择当中任一个,用git clone命令下载即可,它们是完全一样的。
另外,也可以到以下下载链接中根据需要下载最近几个发布版本的代码压缩包。
http://wiki.qemu.org/Download
在本节后面讲解编译时,是以下载开发中的最新的qemu.git为例的。获取其代码仓库过程如下:
[root@kvm-host ~]# git clone git://git.qemu.org/qemu.git
Cloning into 'qemu'...
remote: Counting objects: 294725, done.
remote: Compressing objects: 100% (59425/59425), done.
remote: Total 294725 (delta 238595), reused 289874 (delta 234513)
Receiving objects: 100% (294725/294725), 94.23 MiB | 37.66 MiB/s, done.
Resolving deltas: 100% (238595/238595), done.
[root@kvm-host ~]# cd qemu
[root@kvm-host qemu]# ls
accel.c CODING_STYLE dtc kvm-all.c numa.c qemu-io.c README target-mips trace

3.4.3 配置和编译QEMU

QEMU的配置并不复杂,通常情况下,直接运行代码仓库中configure文件进行配置即可。当然,如果对其配置不熟悉,可以运行“./configure --help”命令查看配置的一些选项及其帮助信息。
显示配置的帮助信息如下:
[root@kvm-host qemu]# ./configure --help

Usage: configure [options]
Options: [defaults in brackets after descriptions]

Standard options:

--help                  print this message
--prefix=PREFIX         install in PREFIX [/usr/local]
--interp-prefix=PREFIX  where to find shared libraries, etc.
                        use %M for cpu name [/usr/gnemul/qemu-%M]
--target-list=LIST      set target list (default: build everything)
                        Available targets: aarch64-softmmu alpha-softmmu 
                        arm-softmmu cris-softmmu i386-softmmu lm32-softmmu 
                        m68k-softmmu microblazeel-softmmu microblaze-softmmu 
                        mips64el-softmmu mips64-softmmu mipsel-softmmu 
                        mips-softmmu moxie-softmmu or32-softmmu 
                        ppc64-softmmu ppcemb-softmmu ppc-softmmu 
                        s390x-softmmu sh4eb-softmmu sh4-softmmu 
                        sparc64-softmmu sparc-softmmu tricore-softmmu 
                        unicore32-softmmu x86_64-softmmu xtensaeb-softmmu 
                        xtensa-softmmu aarch64-linux-user alpha-linux-user 
                        armeb-linux-user arm-linux-user cris-linux-user 
                        i386-linux-user m68k-linux-user 
                        microblazeel-linux-user microblaze-linux-user 
                        mips64el-linux-user mips64-linux-user 
                        mipsel-linux-user mips-linux-user 
                        mipsn32el-linux-user mipsn32-linux-user 
                        or32-linux-user ppc64abi32-linux-user 
                        ppc64le-linux-user ppc64-linux-user ppc-linux-user 
                        s390x-linux-user sh4eb-linux-user sh4-linux-user 
                        sparc32plus-linux-user sparc64-linux-user 
                        sparc-linux-user tilegx-linux-user 
                        unicore32-linux-user x86_64-linux-user

Advanced options (experts only):

NOTE: The object files are built at the place where configure is launched
以上configure选项中我们特别提一下“--target-list”,它指定QEMU对客户机架构的支持。可以看到,对应的选项非常多,表面上QEMU对客户机的架构类型的支持是非常全面的。由于在本书中(也是多数的实际使用场景)我们只使用x86架构的客户机,因此指定“--target-list= x86_64-softmmu”,可以节省大量的编译时间。
执行configure文件进行配置的过程如下:
[root@kvm-host qemu]# ./configure --target-list=x86_64-softmmu
Install prefix /usr/local
BIOS directory /usr/local/share/qemu
...
ELF interp prefix /usr/gnemul/qemu-%M
Source path /root/qemu

C compiler cc
Host C compiler cc
...
QEMU_CFLAGS -I/usr/include/pixman-1 -Werror -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -fPIE -DPIE -m64 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv -Wendif-labels -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-strong
LDFLAGS -Wl,--warn-common -Wl,-z,relro -Wl,-z,now -pie -m64 -g

...
host CPU x86_64
host big endian no
target list x86_64-softmmu #这里就是我们--target-list指定的
...
VNC support yes #通常需要通过VNC连接到客户机中。默认
...
KVM support yes #这是对KVM的支持。默认
...
在配置完以后,qemu目录下会生成config-host.mak和config.status文件。config-host.mak里面可以查看你通过上述configure之后的结果,它会在后续make中被引用。config.status是为用户贴心设计的,便于后续要重新configure时,只要执行“./config.status”就可以恢复上一次configure的配置。这对你苦心配置了很多选项,而后又忘了的情况非常有用。
经过配置之后,编译就很简单了,直接执行make即可。
最后,编译生成x86_64-softmmu /qemu-system-x86_64文件,就是我们需要的用户空间用于其KVM客户机的工具了(在多数Linux发行版中自带的qemu-kvm软件包的命令行是qemu-kvm,只是名字不同的downstream,用户可以等同视之)。

3.4.4 安装QEMU

编译完成之后,运行“make install”命令即可安装QEMU。
QEMU安装过程的主要任务有这几个:创建QEMU的一些目录,复制一些配置文件到相应的目录下,复制一些firmware文件(如:sgabios.bin、kvmvapic.bin)到目录下,以便qemu命令行启动时可以找到对应的固件供客户机使用;复制keymaps到相应的目录下,以便在客户机中支持各种所需键盘类型;复制qemu-system-x86_64、qemu-img等可执行程序到对应的目录下。下面的一些命令行检查了QEMU被安装之后的系统状态。

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境
带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

由于QEMU是用户空间的程序,安装之后不用重启系统,直接用qemu-system-x86_64、qemu-img这样的命令行工具就可以了。

3.5 安装客户机

安装客户机(Guest)之前,我们需要创建一个镜像文件或者磁盘分区等,来存储客户机中的系统和文件。关于客户机镜像有很多种制作和存储方式(将在第4章中进行详细的介绍),本节只是为了快速地演示安装一个客户机,采用了本地创建一个镜像文件,然后将镜像文件作为客户机的硬盘,将客户机操作系统(以RHEL 7为例)安装在其中。
首先,需要创建一个镜像文件。我们使用上节中生成好的qemu-img工具来完成这个任务。它不仅用于创建guest,还可以在后续管理guest image。详见“qemu-img --help”及“man qemu-img”。
[root@kvm-host ~]# qemu-img create -f raw rhel7.img 40G
Formatting 'rhel7.img', fmt=raw size=42949672960
上述就是用qemu-img create命令创建了一个空白的guest image,以raw格式,image文件的名字是“rhel7.img”, 大小是40G。虽然我们看到它的大小是40G,但是它并不占用任何磁盘空间。
[root@kvm-host ~]# ls -lh rhel7.img
-rw-r--r-- 1 root root 40G Oct 15 10:44 rhel7.img
[root@kvm-host ~]# du -h rhel7.img
0 rhel7.img
这是因为qemu-img聪明地为你按实际需求分配文件的实际大小,它将随着image实际的使用而增大。qemu-img也支持设置参数让你可以一开始就实际占有40G(当然建立的过程也就比较耗时,还会占用你更大空间。所以qemu-img默认的方式是按需分配的),如下:
[root@kvm-host ~]# qemu-img create -f raw -o preallocation=full rhel7.img 40G
Formatting 'rhel7.img', fmt=raw size=42949672960 preallocation=full
[root@kvm-host ~]# ls -lh rhel7.img
-rw-r--r-- 1 root root 40G Oct 15 10:58 rhel7.img
[root@kvm-host ~]# du -h rhel7.img
40G rhel7.img
除raw格式以外,qemu-img还支持创建其他格式的image文件,比如qcow2,甚至是其他虚拟机用到的文件格式,比如VMware的vmdk、vdi、vhd等。不同的文件格式会有不同的“-o”选项。
创建完空白guest image之后,我们将RHEL 7安装所需的ISO文件准备好。
[root@kvm-host ~]# ls -l RHEL-7.2-20151030.0-Server-x86_64-dvd1.iso
-rw-r--r-- 1 root root 4043309056 Oct 30 2015 RHEL-7.2-20151030.0-Server-x86_64-dvd1.iso
启动客户机,并在其中用准备好的ISO安装系统,命令行如下:
qemu-system-x86_64 -enable-kvm -m 8G -smp 4 -boot once=d -cdrom RHEL-7.2-20151030.0-Server-x86_64-dvd1.iso rhel7.img
其中,-m 8G是给客户机分配8G内存,-smp 4是指定客户机为对称多处理器结构并分配4个CPU,-boot once=d 是指定系统的启动顺序为首次光驱,以后再使用默认启动项(硬盘),-cdrom ** 是分配客户机的光驱。默认情况下,QEMU会启动一个VNC server端口(5900),可以用vncviwer工具来连接到QEMU的VNC端口查看客户机。
通过启动时的提示,这里可以使用“vncviewer :5900”命令连接到QEMU启动的窗口。根据命令行指定的启动顺序,当有CDROM时,客户机默认会从光驱引导,启动后即可进入客户机系统安装界面,如图3-8所示。

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

可以选择Install安装客户机操作系统,和安装普通Linux系统类似,根据需要做磁盘分区、选择需要的软件包等。安装过程中的一个快照如图3-9所示。

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

在系统安装完成后,客户机中安装程序提示信息,如图3-10所示。

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

和普通的Linux系统安装一样,安装完成后,重启系统即可进入刚才安装的客户机操作系统。

3.6 启动第一个KVM客户机

在安装好了系统之后,就可以使用镜像文件来启动并登录到自己安装的系统之中了。通过如下的简单命令行即可启动一个KVM的客户机。
[root@kvm-host ~]#qemu-system-x86_64 -m 8G -smp 4 /root/rhel7.img
VNC server running on ‘::1:5900’
用vncviwer命令(此处命令为vncviwer :5900)查看客户机的启动情况。
客户机启动完成后的登录界面如图3-11所示。


带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

在通过VNC链接到QEMU窗口后,可以按组合键Ctrl+Alt+2切换到QEMU监视器窗口。在监视器窗口中可以执行一些命令,比如执行“info kvm”命令来查看当前QEMU是否使用KVM,如图3-12所示(显示为kvm support: enabled)。

带你读《KVM实战:原理、进阶与性能调优》之三:构建KVM环境

用组合键Ctrl+Alt+1切换回普通的客户机查看窗口,就可以登录或继续使用客户机系统了。至此,你就已经启动属于自己的第一个KVM客户机了,尽情享受KVM虚拟化带来的快乐吧!

3.7 本章小结

本章主要讲解了如何一步一步地构建属于自己的KVM虚拟化环境。硬件和BIOS中虚拟化技术的支持是KVM运行的先决条件,编译KVM和QEMU是掌握KVM必需的、最基础的也是不可或缺的技能。其中的配置和编译KVM(或Linux kernel)是最复杂也是非常重要的环节,理解这些环节对Linux kernel相关技术(包括KVM)的学习具有非常重要的价值。
通过本章,相信你已经对KVM的虚拟化环境的构建比较了解了,请自己动手构建一套自己的KVM虚拟化系统吧。也许在构建环境过程中你会碰到这样那样的问题,不过只有当你把它们都解决之后才能真正理解。然后,继续看后面的章节来了解KVM虚拟化都提供了哪些功能、命令行,以及它们的基本原理。

上一篇:操作系统之存储管理(下)


下一篇:十年了,除了炒币,区块链还能不能好了?