KVM实战原理进阶与性能调优.pdf
http://www.100md.com
2020年11月27日
![]() |
| 第1页 |
![]() |
| 第7页 |
![]() |
| 第13页 |
![]() |
| 第23页 |
![]() |
| 第33页 |
![]() |
| 第393页 |
参见附件(16220KB,542页)。
KVM实战:原理、进阶与性能调优是一部兼具实战性、系统性又不乏深度的KVM虚拟化技术指南,既能让新人快速掌握KVM的基础知识,又能满足有经验的读者进阶学习的需求。两位作者来自于Intel和阿里云,是国内早期的KVM布道者之一,是虚拟化和云计算方面的专家

内容简介
本书两位作者来自于阿里云和Intel,在云计算和KVM方面有深入的研究,他们将自己的经验倾囊相授,带你全面了解KVM的各种技术细节。
本书在逻辑上分为三大部分:
第一部分 基础篇(第1~5章)
以云计算、虚拟化的概念开篇,首先,详细介绍了KVM的原理和基础架构,以及KVM生产环境的构建;然后,详细讲解了libvirt、virsh、virt-manager等KVM主流管理工具,以及包括CPU、内存、存储、网络、图形界面等在内的各种核心基础功能。这部分内容将帮助读者打下扎实的KVM虚拟化技术基础。
第二部分 进阶篇(第6~9章)
从设备管理、内存管理、动态迁移、嵌套虚拟化、安全、CPU指令性能优化等几个特定的相对高阶的知识点详细展开。相信通过这部分内容的系统学习,读者可以对半虚拟化驱动、设备直接分配、设备热插拔、大页内存、NUMA、嵌套虚拟化、安全特性、CPU新指令集等一系列热门及高阶的名词和技术都会有比较深入的理解,并能培养起可以真正动手实践的能力。
第三部分 性能测试与调优篇(第10章)
从CPU、内存、网络、磁盘等各个方面来介绍性能评估工具与测试参考结果,同时介绍了CPU新指令(如AVX2等)、THP、KSM、NUMA等对性能的影响。读者可以根据本篇介绍的方法来对云服务器做性能评估,也可以对自己搭建的虚拟化环境做性能调优。
相对于上一本书的修改
总体来说,我们对上一本书里所有的用例、图例都做了大量修改更新,实验环境采用笔者写作时的最新技术:硬件平台采用Intel Broadwell Xeon Server,KVM(内核)为4.8版本,QEMU为2.7版本,操作系统环境是RHEL 7.3。文中注释改成脚注的形式,而不是像上一本书那样出现在每章末尾。我们认为这样更方便读者阅读。当然,文字表述上也进行了许多修改。
另外,我们对章节的结构也进行了重新组织,全书共分3篇,10章:第一篇“KVM虚拟化基础”(第1章~第5章),第二篇“KVM虚拟化进阶”(第6章~第9章),第三篇“性能测试与调优”(第10章)。
除了上述的总体修改外,各章主要修改内容如下。
第1章,我们重新组织了结构,精简了一些文字介绍,加入了一些数据图表以便于读者的理解。加入了云计算几种服务模型的描述和图示。加入了一节关于容器(Container)的简介,以便读者对比学习。
第2章,对上一本书相关章节进行了更为系统的梳理,介绍了硬件虚拟化技术、KVM、QEMU、与KVM配合的组件以及相关工具链。
第5章,着重对其中的网络配置一节进行了更新。将上一本书中的第5章拆分成了第6章、第7章、第8章和第9章,并分别进行了内容扩充。
第6章,对应上一本书中的第5章的半虚拟化、设备直接分配、热插拔这3节,并分别进行了补充。在半虚拟化驱动一节中,我们新增了“内核态的vhost-net后端以及网卡多队列”“使用用户态的vhost-user作为后端驱动”“对Windows客户机的优化”这3小节。在设备直接分配一节中,我们使用VFIO替换掉了已经被废弃的Legacy passthrough。在热插拔一节,我们将内存热插拔独立出来,并着重更新,因为在上一本书出版时它还未被完全支持。除此之外,我们还新增了磁盘热插拔和网络接口的热插拔两节。
第7章,我们将上一本书中的第4章中内存大页部分和上一本书中的第5章中的KSM、透明大页等内容凑在一起,组成了KVM内存管理高级技巧,同时新增了NUMA(非统一内存访问架构)一节。
第8章,由上一本书中的第5章的“动态迁移”和“迁移到KVM虚拟化环境”两节组成。
第9章,在上一本书中的第5章的“嵌套虚拟化”“KVM安全”等内容的基础上,新增了“CPU指令相关的性能优化”一节,着重介绍了最近几年Intel的一些性能优化新指令在虚拟化环境中的应用。
第10章,对应上一本书中的第8章,专门讲KVM性能测试与优化。我们在最新的软硬件环境中重做了CPU、内存、网络、磁盘的性能测试,获取了最新的数据,尤其对一些测试工具(benchmark)进行了重新选取,比如磁盘性能测试,我们放弃了IOzone和Bonnie++,而选用业界更认可的fio。另外,我们还加入了“CPU指令集对性能的提升”和“其他的影响客户机性能的因素”两节进行分析,希望对读者进行虚拟化系能调优有所启示。
上一本书中的第7章“Linux发行版中的KVM”和第9章“参与KVM开源社区”分别作为本书的附录A和附录B,并进行了相应的内容更新。
其他章节的内容保持不变,即第3章为上一本书的第3章且内容不变;第4章为上一本书的第6章,内容不变。
KVM的现状
至本书写作时,KVM已经10周岁了。10年之间,得益于与Linux天然一体以及Redhat的倾力打造,KVM已经成为Openstack用户选择的最主流的Hypervisor(因为KVM是Dpenstack的默认Hypervisor)。来自Openstack的调查显示,KVM占到87%以上的部署份额,并且(笔者认为)还会继续增大。可以说,KVM已经主宰了公有云部署的Hypervisor市场;而在私有云部署方面,尤其大公司内部私有云部署,还是VMware的地盘,目前受到HyperV的竞争。
功能上,虚拟化发展到今天,各个Hypervisor的主要功能都趋同。KVM作为后起之秀,并且在公有云上广泛部署,其功能的完备性是毋庸置疑的。并且由于其开源性,反而较少一些出于商业目的的限制,比如一篇文章
(ftp//public.dhe.ibm.com/inux/s/Clabby-Analytics-VMware-v_KVM.)中比较VMware EXS与KVM,就是一个例子
性能上,作为同样开源的Hypervisor,KVM和Xen都很优秀,都能达到原生系统95%
以上的效率(CPU、内存、网络、磁盘等benchmark衡量),KVM甚至还略微好过Xen-
点点,与微软的Hyper-V相比,KVM似乎略逊于最新的Windows 2016上的HyperV,而好于Windows 2012 R2上的HyperV,但这是微软的一家之言,笔者没有重新测试验证。
其他与诸如VMware EXS等的性能比较,网上也可以找到很多,读者可以自行搜索。总的来说,即使各有优劣,虚拟化技术发展到今天已经成熟,KVM也是如此。
什么是Xen
Xen的出现要早于KVM,可以追溯到20世纪90年代。剑桥大学的lan Pratt和Keir Fraser在一个叫作Xenoserver的研究项目中开发了Xen虚拟机。在那个年代,硬件虚拟化还没有出现,所以Xen最开始采用的是半虚拟化的解决方案。
Xen在2002年开源,并在2003年发布了1.0版本、2004年发布了2.0版本,随即被Redhat,Novell和Sun的Linux发行版集成,作为其虚拟化组件。2005年的3.0版本开始加入Intel和AMD的硬件虚拟化的支持,以及Intel的IA64架构,从此,Xen也提供全虚拟化解决方案(HVM),可以运行完全没有修改的客户机操作系统。2007年10月,思杰公司出资5亿美元收购了XenSource,变成了Xen项目的东家。2013年,Xen成为Linux基金会赞助的合作项目。
Xen在架构上是一个典型的Type 1 Hypervisor,与KVM形成鲜明对比,如图1-8所示。
严格来说,它没有宿主机的概念,而是由Xen Hypervisor(VMM)完全管控硬件,但用户却看不见、摸不着它,只能通过特殊的0号虚拟机(Dom0),通过其中x工具栈(tool stack)与Xen Hypervisor交互来管理其他普通虚拟机(DomU)。0号虚拟机是一个运行修改过的半虚拟化的内核的Linux虚拟机。从架构上,Xen的虚拟化方案既利用了Linux内核的10部分(Dom0的内核),将Linux内核的CPU、内存管理等核心部分排除在外由自己接手(Xen Hypervisor),所以,一开始就受到了Linux内核开发人员的抵制,致使Linux内核作为Dom0对Xen的支持部分一直不能合入Linux内核社区。一直到2010年,在采用基于内核的PVOPS方式大量重写了Xen代码以后,才勉强合入Linux内核社区。2011年,从Linux内核2.6.37版本开始,正式支持Xen Dom0
KVM实战原理进阶与性能调优截图




云计算与虚拟化技术丛书
KVM实战:原理、进阶与性能调优
任永杰 程舟 著
ISBN:978-7-111-61981-9
本书纸版由机械工业出版社于2019年出版,电子版由华章分社(北京华章图文信息有限公
司,北京奥维博世图书发行有限公司)全球范围内制作与发行。
版权所有,侵权必究
客服热线:+ 86-10-68995265
客服信箱:service@bbbvip.com
官方网址:www.hzmedia.com.cn
新浪微博 @华章数媒
微信公众号 华章电子书(微信号:hzebook)目录 前言
第一篇 KVM虚拟化基础
第1章 虚拟化简介
1.1 云计算概述
1.1.1 什么是云计算
1.1.2 云计算的历史
1.1.3 云计算的几种服务模型
1.2 虚拟化技术
1.2.1 什么是虚拟化
1.2.2 软件虚拟化和硬件虚拟化
1.2.3 半虚拟化和全虚拟化
1.2.4 Type1和Type2虚拟化
1.3 KVM简介
1.3.1 KVM的历史
1.3.2 KVM的功能概览
1.3.3 KVM的现状
1.3.4 KVM的展望
1.4 其他的虚拟化解决方案简介
1.4.1 Xen
1.4.2 VMware
1.4.3 HyperV
1.4.4 Container
1.5 本章小结
第2章 KVM原理简介
2.1 硬件虚拟化技术
2.1.1 CPU虚拟化
2.1.2 内存虚拟化
2.1.3 IO虚拟化
2.1.4 Intel虚拟化技术发展
2.2 KVM架构概述
2.3 KVM内核模块
2.4 QEMU用户态设备模拟
2.5 与QEMUKVM结合的组件
2.6 KVM上层管理工具
2.7 本章小结
第3章 构建KVM环境
3.1 硬件系统的配置
3.2 安装宿主机Linux系统
3.3 编译和安装KVM
3.3.1 下载KVM源代码
3.3.2 配置KVM
3.3.3 编译KVM
3.3.4 安装KVM
3.4 编译和安装QEMU3.4.1 曾经的qemu-kvm
3.4.2 下载QEMU源代码
3.4.3 配置和编译QEMU
3.4.4 安装QEMU
3.5 安装客户机
3.6 启动第一个KVM客户机
3.7 本章小结
第4章 KVM管理工具
4.1 libvirt
4.1.1 libvirt简介
4.1.2 libvirt的安装与配置
4.1.3 libvirt域的XML配置文件
4.1.4 libvirt API简介
4.1.5 建立到Hypervisor的连接
4.1.6 libvirt API使用示例
4.2 virsh
4.2.1 virsh简介
4.2.2 virsh常用命令
4.3 virt-manager
4.3.1 virt-manager简介
4.3.2 virt-manager编译和安装
4.3.3 virt-manager使用
4.4 virt-viewer、virt-install、virt-top和libguestfs
4.4.1 virt-viewer
4.4.2 virt-install
4.4.3 virt-top
4.4.4 libguestfs
4.5 云计算管理平台
4.5.1 OpenStack简介
4.5.2 ZStack简介
4.6 本章小结
第5章 KVM核心基础功能
5.1 硬件平台和软件版本说明
5.2 CPU配置
5.2.1 vCPU的概念
5.2.2 SMP的支持
5.2.3 CPU过载使用
5.2.4 CPU模型
5.2.5 进程的处理器亲和性和vCPU的绑定
5.3 内存配置
5.3.1 内存设置基本参数
5.3.2 EPT和VPID简介
5.3.3 内存过载使用
5.4 存储配置
5.4.1 存储配置和启动顺序
5.4.2 qemu-img命令5.4.3 QEMU支持的镜像文件格式
5.4.4 客户机存储方式
5.5 网络配置
5.5.1 用QEMU实现的网络模式
5.5.2 使用直接的网桥模式
5.5.3 用网桥实现NAT模式
5.5.4 QEMU内部的用户模式网络
5.5.5 其他网络选项
5.6 图形显示
5.6.1 SDL的使用
5.6.2 VNC的使用
5.6.3 VNC显示中的鼠标偏移
5.6.4 非图形模式
5.6.5 显示相关的其他选项
5.7 本章小结
第二篇 KVM虚拟化进阶
第6章 KVM设备高级管理
6.1 半虚拟化驱动
6.1.1 virtio概述
6.1.2 安装virtio驱动
6.1.3 使用virtio_balloon
6.1.4 使用virtio_net
6.1.5 使用virtio_blk
6.1.6 内核态的vhost-net后端以及网卡多队列
6.1.7 使用用户态的vhost-user作为后端驱动
6.1.8 kvm_clock配置
6.1.9 对Windows客户机的优化
6.2 设备直接分配(VT-d)
6.2.1 VT-d概述
6.2.2 VFIO简介
6.2.3 VT-d环境配置
6.2.4 VT-d操作示例
6.2.5 SR-IOV技术
6.3 热插拔
6.3.1 PCI设备热插拔
6.3.2 PCI设备热插拔示例
6.3.3 CPU的热插拔
6.3.4 内存的热插拔
6.3.5 磁盘的热插拔
6.3.6 网卡接口的热插拔
6.4 本章小结
第7章 KVM内存管理高级技巧
7.1 大页
7.1.1 大页的介绍
7.1.2 KVM虚拟化对大页的利用
7.2 透明大页7.3 KSM
7.3.1 KSM基本原理
7.3.2 KSM操作实践
7.3.3 QEMU对KSM的控制
7.4 与NUMA相关的工具
7.4.1 numastat
7.4.2 numad
7.4.3 numactl
7.5 本章小结
第8章 KVM迁移
8.1 动态迁移
8.1.1 动态迁移的概念
8.1.2 动态迁移的效率和应用场景
8.1.3 KVM动态迁移原理
8.1.4 KVM动态迁移实践
8.1.5 VT-dSR-IOV的动态迁移
8.2 迁移到KVM虚拟化环境
8.2.1 virt-v2v工具介绍
8.2.2 从Xen迁移到KVM
8.2.3 从VMware迁移到KVM
8.2.4 从VirtualBox迁移到KVM
8.2.5 从物理机迁移到KVM虚拟化环境(P2V)
8.3 本章小结
第9章 其他高级功能
9.1 嵌套虚拟化
9.1.1 嵌套虚拟化的基本概念
9.1.2 KVM嵌套KVM
9.2 KVM安全
9.2.1 SMEPSMAPMPX
9.2.2 控制客户机的资源使用——cgroups
9.2.3 SELinux和sVirt
9.2.4 其他安全策略
9.3 CPU指令相关的性能优化
9.3.1 AVXAVX2AVX512
9.3.2 XSAVE指令集
9.3.3 AES新指令
9.3.4 完全暴露宿主机CPU特性
9.4 QEMU监控器
9.4.1 QEMU monitor的切换和配置
9.4.2 常用命令介绍
9.5 qemu命令行参数
9.5.1 回顾已用过的参数
9.5.2 其他常用参数
9.6 本章小结
第三篇 性能测试与调优
第10章 KVM性能测试及参考数据10.1 虚拟化性能测试简介
10.2 CPU性能测试
10.2.1 CPU性能测试工具
10.2.2 测试环境配置
10.2.3 性能测试方法
10.2.4 性能测试数据
10.3 内存性能测试
10.3.1 内存性能测试工具
10.3.2 测试环境配置
10.3.3 性能测试方法
10.3.4 性能测试数据
10.4 网络性能测试
10.4.1 网络性能测试工具
10.4.2 测试环境配置
10.4.3 性能测试方法
10.4.4 性能测试数据
10.5 磁盘IO性能测试
10.5.1 磁盘IO性能测试工具
10.5.2 测试环境配置
10.5.3 性能测试方法
10.5.4 性能测试数据
10.6 CPU指令集对性能的提升
10.7 其他影响客户机性能的因素
10.8 本章小结
附录A Linux发行版中的KVM
附录B 参与KVM开源社区前言
为什么要写这本书
自《KVM虚拟化技术:实战与原理解析》(以下简称“上一本书”)出版以来,受到
了读者的热烈欢迎,几度脱销重印。这给了笔者强烈的鼓舞和责任感,觉得有必要与时俱
进给读者介绍最新的KVM虚拟化技术的相关知识。
从上一本书出版后到现在近5年时间里,国内虚拟化技术迅速普及,云计算应用风起
云涌,阿里云、腾讯云、华为云等国内云服务提供商迅速崛起,使得云计算、虚拟化不再
是原来象牙塔里虚无缥缈的技术概念,而是与普通大众日常生活息息相关的新名词,KVM被这几大云服务提供商广泛采用[1]
,使得它成为云计算世界里事实上的虚拟化标
准。在这样的市场背景下,以Intel为代表的x86硬件厂商,这些年也愈加重视虚拟化技术
的硬件支持与创新[2]
,ARM平台的硬件虚拟化支持也愈加完善。硬件层面的创新也促使
QEMU、KVM在软件层面日新月异。比如,从2013年第1版发行至今,KVM(内核)版
本从3.5发展到了4.8;QEMU版本从1.3发展到了2.7;专门针对KVM的qemu-kvm代码树已
经废弃(被合并到了主流QEMU中)……因此,上一本书中的很多用例、方法和结论等,在新的代码环境下已经有些不合时宜,甚至会出错。我们有必要给读者提供最新且正确的
信息。
相对于上一本书的修改
总体来说,我们对上一本书里所有的用例、图例都做了大量修改更新,实验环境采用
笔者写作时的最新技术:硬件平台采用Intel Broadwell Xeon Server,KVM(内核)为4.8
版本,QEMU为2.7版本,操作系统环境是RHEL 7.3。文中注释改成脚注的形式,而不是
像上一本书那样出现在每章末尾。我们认为这样更方便读者阅读。当然,文字表述上也进
行了许多修改。
另外,我们对章节的结构也进行了重新组织,全书共分3篇,10章:第一篇“KVM虚
拟化基础”(第1章~第5章),第二篇“KVM虚拟化进阶”(第6章~第9章),第三篇“性
能测试与调优”(第10章)。
除了上述的总体修改外,各章主要修改内容如下。
第1章,我们重新组织了结构,精简了一些文字介绍,加入了一些数据图表以便于读
者的理解。加入了云计算几种服务模型的描述和图示。加入了一节关于容器(Container)
的简介,以便读者对比学习。
第2章,对上一本书相关章节进行了更为系统的梳理,介绍了硬件虚拟化技术、KVM、QEMU、与KVM配合的组件以及相关工具链。
第5章,着重对其中的网络配置一节进行了更新。将上一本书中的第5章拆分成了第6
章、第7章、第8章和第9章,并分别进行了内容扩充。第6章,对应上一本书中的第5章的半虚拟化、设备直接分配、热插拔这3节,并分别
进行了补充。在半虚拟化驱动一节中,我们新增了“内核态的vhost-net后端以及网卡多队
列”“使用用户态的vhost-user作为后端驱动”“对Windows客户机的优化”这3小节。在设备直
接分配一节中,我们使用VFIO替换掉了已经被废弃的Legacy passthrough。在热插拔一
节,我们将内存热插拔独立出来,并着重更新,因为在上一本书出版时它还未被完全支
持。除此之外,我们还新增了磁盘热插拔和网络接口的热插拔两节。
第7章,我们将上一本书中的第4章中内存大页部分和上一本书中的第5章中的KSM、透明大页等内容凑在一起,组成了KVM内存管理高级技巧,同时新增了NUMA(非统一
内存访问架构)一节。
第8章,由上一本书中的第5章的“动态迁移”和“迁移到KVM虚拟化环境”两节组成。
第9章,在上一本书中的第5章的“嵌套虚拟化”“KVM安全”等内容的基础上,新增
了“CPU指令相关的性能优化”一节,着重介绍了最近几年Intel的一些性能优化新指令在虚
拟化环境中的应用。
第10章,对应上一本书中的第8章,专门讲KVM性能测试与优化。我们在最新的软硬
件环境中重做了CPU、内存、网络、磁盘的性能测试,获取了最新的数据,尤其对一些测
试工具(benchmark)进行了重新选取,比如磁盘性能测试,我们放弃了IOzone和
Bonnie++,而选用业界更认可的fio。另外,我们还加入了“CPU指令集对性能的提
升”和“其他的影响客户机性能的因素”两节进行分析,希望对读者进行虚拟化系能调优有
所启示。
上一本书中的第7章“Linux发行版中的KVM”和第9章“参与KVM开源社区”分别作为本
书的附录A和附录B,并进行了相应的内容更新。
其他章节的内容保持不变,即第3章为上一本书的第3章且内容不变;第4章为上一本
书的第6章,内容不变。
读者对象
本书适合对Linux下虚拟化或云计算基础技术感兴趣的读者阅读,包括Linux运维工程
师、KVM开发者、云平台开发者、虚拟化方案决策者、KVM的用户以及其他对KVM虚拟
机感兴趣的计算机爱好者。希望本书对这些读者了解KVM提供以下帮助。
·Linux运维工程师:了解KVM的使用方法、功能和基本的性能数据,能够搭建高性
能的KVM虚拟化系统,并应用于生产环境中。
·KVM开发者:了解KVM的基本原理和功能,也了解其基本用法和一些调试方法,以
及如何参与到KVM开源社区中去贡献代码。
·云平台开发者:了解底层KVM虚拟化的基本原理和用法,以促进云平台上层应用的
开发和调试的效率。
·虚拟化方案决策者:了解KVM的硬件环境需求和它的功能、性能概况,以便在虚拟化技术选型时做出最优化的决策。
·普通用户:了解KVM的功能和如何使用KVM,用掌握的KVM虚拟化技术来促进其
他相关的学习、开发和测试。
如何阅读本书
前面已经提到,本书相比上一本书内容更加集中,分类更加合理。如果读者朋友对
KVM没有什么了解,笔者建议按本书章节顺序阅读,通读一遍之后再对感兴趣的章节进
行仔细阅读。对于已有一定KVM知识基础的读者,可以根据自己的兴趣和已经掌握的知
识情况来有选择地阅读各个章节。当然,笔者建议今后可能会经常使用KVM的读者,在
阅读本书时,可以根据书中示例或者其他示例来进行实际操作。如果是开发者,也可以查
看相应的源代码。
勘误和支持
KVM、QEMU等开源社区非常活跃,QEMUKVM发展迅速,每天都有新的功能加进
去,或者原有功能被改进。特别是qemu命令行参数很可能会有改动,故本书中qemu命令
行参数只能完全适用于本书中提及的QEMU版本,读者若使用不同的版本,命令行参数可
能并不完全相同。例如,本书写作时,“-enable-kvm”已经被社区标为“将要废弃”,很可能
在读者拿到本书的时候,需要用“-accel kvm”来代替它。
由于KVM和QEMU的发展变化比较快,加之笔者的技术水平有限,编写时间仓促,书中难免会出现一些错误或者不准确的地方,恳请读者朋友批评指正。读者朋友对本书相
关内容有任何的疑问、批评和建议,都可以通过笔者之一(任永杰)的博客网站
http:smilejay.com进行讨论。也可以发邮件给我们(smile665@gmail.com、Robert.Ho@outlook.com),笔者会尽力回复并给读者以满意的答案。全书中涉及的示例
代码程序(不包含单行的命令)和重要的配置文件,都可以从网站
https:github.comsmilejaykvm-book查看和下载。
如果读者朋友们有更多的宝贵意见或者任何关于KVM虚拟化技术的讨论,也都欢迎
发送电子邮件至邮箱smile665@gmail.com、Robert.Ho@outlook.com,我们非常期待能够得
到朋友们的真挚反馈。
[1] 全球最大的云服务提供商Amazon,在2017年11月也宣布开始采用KVM作为它的虚拟
化技术,大有启用KVM而放弃Xen之势。
[2] 硬件虚拟化支持是每一代Intel CPU的最核心功能之一,也是每一代新平台新功能和性
能提升的领域。第一篇 KVM虚拟化基础
·第1章 虚拟化简介
·第2章 KVM原理简介
·第3章 构建KVM环境
·第4章 KVM管理工具
·第5章 KVM核心基础功能第1章 虚拟化简介
在写作上一本书的时候(2013年),云计算虽然已经在国际上提出多年,但在国内还
是刚刚兴起。到写作本书时这短短4年内,国内云计算已经翘首追赶,紧跟国际的步伐。
例如阿里云,截至笔者写作时,阿里云已经连续7个季度3位数的同比增长率。老牌公司微
软也在这几年加速追赶,在这个新的领域跻身一线。1.1 云计算概述
1.1.1 什么是云计算
一直以来,云计算(Cloud Computing)的定义也如同它的名字一样,云里雾里,说
不清楚。维基百科里是这样定义的:是一种基于互联网的计算方式,通过这种方式,共享
的软硬件资源和信息可以按需求提供给计算机各种终端和其他设备[1]。以前,我们的信息
处理(计算)是由一个实实在在的计算机来完成的,它看得见,摸得着。后来,随着计算
硬件、网络技术、存储技术的飞速发展,人们发现,每个人独自拥有一台计算机似乎有些
浪费,因为它大多数时候是空闲的。那么,如果将计算资源集中起来,大家共享,类似现
代操作系统那样分时复用,将是对资源的极大节省和效率的极大提升,经济学上的解释也
就是边际效应(成本)递减。科技行业的发展,根源也是经济利益的推动。在这样的背景
下,云计算应运而生了。它就是把庞大的计算资源集中在某个地方或是某些地方,而不再
是放在身边的那台计算机了;用户的每一次计算,都发生在那个被称为云的他看不见摸不
着的某个地方。
以CPU为例,图1-1和图1-2摘选了从2000年到2017年上市的Intel桌面CPU的参数(主
频、核数、LLC[2]
、制造工艺),从中可以大概看到CPU处理能力的飞速提升。它的另一
面也就意味着,个人单独拥有一台计算机,从资源利用效率角度来看,被大大闲置了的。
图1-1 Intel CPU处理能力的主要参数图1-2 Intel CPU LLC的发展及制造工艺的演进
[1] https:zh.wikipedia.orgwiki%E9%9B%B2%E7%AB%AF%E9%81%8B%E7%AE%97。
[2] Last Level Cache指介于CPU core和RAM之间的最后一层缓存。Pentium时代通常最多到
L2 Cache。现在的Core i3i5i7都有L3 Cache,并且越来越大。1.1.2 云计算的历史
正式的云计算的产品始发于2006年,那年8月,亚马逊(Amazon)发布了“弹性计算
云”(Elastic Compute Cloud)。2008年10月,微软宣布了名为Azure的云计算产品,并在
2010年2月正式发布Windows Azure[1]。Google也从2008年开始进入云计算时代,那年4
月,其发布了Google App Engine Beta,但直到2013年12月,其Google Compute Engine对
标AWS EC2才正式可用。
2010年7月,NASA和Rackspace共同发布了著名的开源项目Openstack。
从国内来看,2009年,阿里巴巴率先成立了阿里云部门,一开始只对内服务于其自身
的电商业务,如淘宝、天猫。2011年7月,阿里云开始正式对外销售云服务。
无论是国内还是国外,云计算的市场都快速发展。“Amazon把云计算做成一个大生意
没有花太长的时间:不到两年时间,Amazon上的注册开发人员达44万人,还有为数众多
的企业级用户。有第三方统计机构提供的数据显示,Amazon与云计算相关的业务收入已
达1亿美元。云计算是Amazon增长最快的业务之一。”[2]
国内的阿里云也在2013年以后快
速蓬勃发展。无论是国际巨头AWS(亚马逊)还是国内的阿里云,这些年都是快速增
长,尤其阿里云,虽然体量暂时还远不及AWS,但一直都是超过100%的增长,让人侧
目,如图1-3所示。
图1-3 云计算营收对比:2013—2017年度亚马逊AWS和阿里云[3]
[1] 2014年3月,Windows Azure更名为Microsoft Azure。
[2] 刘鹏:云计算发展现状。http:www.chinacloud.cnshow.aspx?id=754cid=11。[3] 数据整理自网络。阿里财年始于前一年4月,这里以大约自然年表示,比如2015年数据
来自于阿里2016财报。另外阿里云2013、2014年度数据包括其internet infrastructure收入,2015年开始才将阿里云单独出来。换算时,美元兑人民币汇率假设为6.8。微软的Azure营
收没有单独披露。Google cloud营收也未能单独获得。1.1.3 云计算的几种服务模型
“云计算是推动IT转向以业务为中心模式的一次重大变革。它着眼于运营效率、竞争
力和快速响应等实际成果。这意味着IT的作用正在从提供IT服务逐步过渡到根据业务需求
优化服务的交付和使用。这种全新的模式将以前的信息孤岛转化为灵活高效的资源池和具
备自我管理能力的虚拟基础架构,从而以更低的成本和以服务的形式提供给用户。IT即服
务将提供业务所需要的一切,并在不丧失对系统的控制力的同时,保持系统的灵活性和敏
捷性。”[1]
云计算的模型是以服务为导向的,根据提供的服务层次不同,可分为:
IaaS(Infrastructure as a Service,基础架构即服务)、PaaS(Platform as a Service,平台即
服务)、SaaS(Software as a Service,软件即服务)。它们提供的服务越来越抽象,用户
实际控制的范围也越来越小,如图1-4所示。
图1-4 云计算服务层次模型[2]
1.SaaS,软件即服务
云服务提供商提供给客户直接使用软件服务,如Google Docs、Microsoft CRM、Salesforce.com等。用户不必自己维护软件本身,只管使用软件提供的服务。用户为该软
件提供的服务付费。
2.PaaS,平台即服务
云服务提供商提供给客户开发、运维应用程序的运行环境,用户负责维护自己的应用
程序,但并不掌控操作系统、硬件以及运作的网络基础架构。如Google App Engine等。平台是指应用程序运行环境(图1-4中的Runtime)。通常,这类用户在云环境中运维的应用
程序会再提供软件服务给他的下级客户。用户为自己的程序的运行环境付费。
3.IaaS,基础设施即服务
用户有更大的自主权,能控制自己的操作系统、网络连接(虚拟的)、硬件(虚拟
的)环境等,云服务提供商提供的是一个虚拟的主机环境。如Google Compute Engine、AWS EC2等。用户为一个主机环境付费。
从图1-4中可以看到,无论是哪种云计算服务模型,虚拟化(Virtualization)都是其基
础。那么什么是虚拟化呢?
[1] 虚拟化和云计算技术回顾与展望。
http:www.ctosay.cncontent40797008418208146787.html。
[2] 图片来源http:inspira.co.inblogbenefits-iaas-vs-paas-vs-saas。1.2 虚拟化技术
1.2.1 什么是虚拟化
维基百科关于虚拟化的定义是:“In computing,virtualization refers to the act of
creating a virtual(rather than actual)version of something,including virtual computer hardware
platforms,storage devices,and computer network resources。”(在计算机领域,虚拟化指
创建某事物的虚拟(而非实际)版本,包括虚拟的计算机硬件平台、存储设备,以及计算
机网络资源)可见,虚拟化是一种资源管理技术,它将计算机的各种实体资源(CPU、内
存、存储、网络等)予以抽象和转化出来,并提供分割、重新组合,以达到最大化利用物
理资源的目的。
广义来说,我们一直以来对物理硬盘所做的逻辑分区,以及后来的LVM(Logical
Volume Manager),都可以纳入虚拟化的范畴。
结合图1-4来看,在没有虚拟化以前(我们抽掉Virtualization层),一个物理的主机
(Sever、Storage、Network层)上面只能支持一个操作系统及其之上的一系列运行环境和
应用程序;有了虚拟化技术,一个物理主机可以被抽象、分割成多个虚拟的逻辑意义上的
主机,向上支撑多个操作系统及其之上的运行环境和应用程序,则其资源可以被最大化地
利用。
图1-5 物理资源虚拟化示意
如图1-5所示的Virtual Machine Monitor(VMM,虚拟机监控器,也称为Hypervisor)
层,就是为了达到虚拟化而引入的一个软件层。它向下掌控实际的物理资源(相当于原本
的操作系统);向上呈现给虚拟机N份逻辑的资源。为了做到这一点,就需要将虚拟机对
物理资源的访问“偷梁换柱”——截取并重定向,让虚拟机误以为自己是在独享物理资源。虚拟机监控器运行的实际物理环境,称为宿主机;其上虚拟出来的逻辑主机,称为客户
机。
虚拟化技术有很多种实现方式,比如软件虚拟化和硬件虚拟化,再比如准虚拟化和全
虚拟化。下面将针对每种实现方式做一个简单的介绍。1.2.2 软件虚拟化和硬件虚拟化
1.软件虚拟化技术
软件虚拟化,顾名思义,就是通过软件模拟来实现VMM层,通过纯软件的环境来模
拟执行客户机里的指令。
最纯粹的软件虚拟化实现当属QEMU。在没有启用硬件虚拟化辅助的时候,它通过软
件的二进制翻译[1]
仿真出目标平台呈现给客户机,客户机的每一条目标平台指令都会被
QEMU截取,并翻译成宿主机平台的指令,然后交给实际的物理平台执行。由于每一条都
需要这么操作一下,其虚拟化性能是比较差的,同时其软件复杂度也大大增加。但好处是
可以呈现各种平台给客户机,只要其二进制翻译支持。
2.硬件虚拟化技术
硬件虚拟化技术就是指计算机硬件本身提供能力让客户机指令独立执行,而不需要
(严格来说是不完全需要)VMM截获重定向。
以x86架构为例,它提供一个略微受限制的硬件运行环境供客户机运行(non-root
mode[2]),在绝大多数情况下,客户机在此受限环境中运行与原生系统在非虚拟化环境
中运行没有什么两样,不需要像软件虚拟化那样每条指令都先翻译再执行,而VMM运行
在root mode,拥有完整的硬件访问控制权限。仅仅在少数必要的时候,某些客户机指令
的运行才需要被VMM截获并做相应处理,之后客户机返回并继续在non-root mode中运
行。可以想见,硬件虚拟化技术的性能接近于原生系统[3]
,并且,极大地简化了VMM的
软件设计架构。
Intel从2005年就开始在其x86 CPU中加入硬件虚拟化的支持——Intel Virtualization
Technology,简称Intel VT。到目前为止,在所有的Intel CPU中,都可以看到Intel VT的身
影。并且,每一代新的CPU中,都会有新的关于硬件虚拟化支持、改进的feature加入。也
因如此,Intel x86平台是对虚拟化支持最为成熟的平台,本书将以Intel x86平台为例介绍
KVM的虚拟化。
[1] 二进制翻译(binary translation)是指将使用某套指令集的二进制代码转换成基于另一
套指令集的。它既可以通过硬件来完成,也可以通过软件来完成。
[2] root与non-root mode是Intel为了硬件虚拟化而引入的与原来的Ring0~Ring3正交的权限
控制机制。详见Intel Sefnare Development Manual第15章。
[3] 本书中,原生系统(Native)是指不使用虚拟化技术的主机系统,即原本的一个物理
主机安装一个操作系统的方式。1.2.3 半虚拟化和全虚拟化
1.半虚拟化[1]
通过上一节的描述,大家可以理解,最理想的虚拟化的两个目标如下:
1)客户机完全不知道自己运行在虚拟化环境中,还以为自己运行在原生环境里。
2)完全不需要VMM介入客户机的运行过程。
纯软件的虚拟化可以做到第一个目标,但性能不是很好,而且软件设计的复杂度大大
增加。
那么如果放弃第一个目标呢?让客户机意识到自己是运行在虚拟化环境里,并做相应
修改以配合VMM,这就是半虚拟化(Para-Virtualization)。一方面,可以提升性能和简
化VMM软件复杂度;另一方面,也不需要太依赖硬件虚拟化的支持,从而使得其软件设
计(至少是VMM这一侧)可以跨平台且是优雅的。“本质上,准虚拟化弱化了对虚拟机特
殊指令的被动截获要求,将其转化成客户机操作系统的主动通知。但是,准虚拟化需要修
改客户机操作系统的源代码来实现主动通知。”典型的半虚拟化技术就是virtio,使用virtio
需要在宿主机VMM和客户机里都相应地装上驱动。
2.全虚拟化
与半虚拟化相反的,全虚拟化(Full Virtualization)坚持第一个理想化目标:客户机
的操作系统完全不需要改动。敏感指令在操作系统和硬件之间被VMM捕捉处理,客户操
作系统无须修改,所有软件都能在虚拟机中运行。因此,全虚拟化需要模拟出完整的、和
物理平台一模一样的平台给客户机,这在达到了第一个目标的同时也增加了虚拟化层
(VMM)的复杂度。
性能上,2005年硬件虚拟化兴起之前,软件实现的全虚拟化完败于VMM和客户机操
作系统协同运作的半虚拟化,这种情况一直延续到2006年。之后以Intel VT-x、VT-d[2]
为
代表的硬件虚拟化技术的兴起,让由硬件虚拟化辅助的全虚拟化全面超过了半虚拟化。但
是,以virtio为代表的半虚拟化技术也一直在演进发展,性能上只是略逊于全虚拟化,加
之其较少的平台依赖性,依然受到广泛的欢迎。
[1] 在《KVM虚拟化技术:实战与原理解析》中称为“准虚拟化”
[2] https:www.intel.comcontentwwwusenvirtualizationvirtualization-technologyintel-
virtualizationtechnology.html。1.2.4 Type1和Type2虚拟化
从软件框架的角度上,根据虚拟化层是直接位于硬件之上还是在一个宿主操作系统之
上,将虚拟化划分为Typel和Type2,如图1-6所示。
Type1(类型1)Hypervisor也叫native或bare-metal Hypervisor。这类虚拟化层直接运
行在硬件之上,没有所谓的宿主机操作系统。它们直接控制硬件资源以及客户机。典型地
如Xen(见1.4.1节)和VMware ESX。
Type2(类型2)Hypervisor运行在一个宿主机操作系统之上,如VMware
Workstation;或系统里,如KVM。这类Hypervisor通常就是宿主机操作系统的一个应用程
序,像其他应用程序一样受宿主机操作系统的管理。比如VMware Workstation就是运行在
Windows或者Linux操作系统上的一个程序而已[1]。客户机是在宿主机操作系统上的一个
抽象,通常抽象为进程。
[1] 将KVM归为Type1或Type2是有争议的,一方面,它是以kernel module的形式加载于
kernel,与kernel融为一体,可以认为它将Linux kernel转变为一个Type1的Hypervisor。另
一方面,在逻辑上,它受制于kernel,所有对硬件资源的管理都是通过kernel去做的,所以
归为Type2。1.3 KVM简介
1.3.1 KVM的历史
KVM全称是Kernel-based Virtual Machine,即基于内核的虚拟机,是采用硬件虚拟化
技术的全虚拟化解决方案[1]。
图1-6 类型1和类型2的Hypervisor
KVM最初是由Qumranet
[2]
公司的Avi Kivity开发的,作为他们的VDI产品的后台虚拟
化解决方案。为了简化开发,Avi Kivity并没有选择从底层开始新写一个Hypervisor,而是
选择了基于Linux kernel,通过加载模块使Linux kernel本身变成一个Hypervisor。2006年10
月,在先后完成了基本功能、动态迁移以及主要的性能优化之后,Qumranet正式对外宣布
了KVM的诞生。同月,KVM模块的源代码被正式纳入Linux kernel,成为内核源代码的一
部分。作为一个功能和成熟度都逊于Xen的项目[3]
,在这么快的时间内被内核社区接纳,主要原因在于:
1)在虚拟化方兴未艾的当时,内核社区急于将虚拟化的支持包含在内,但是Xen取
代内核由自身管理系统资源的架构引起了内核开发人员的不满和抵触。
2)Xen诞生于硬件虚拟化技术出现之前,所以它在设计上采用了半虚拟化的方式,这让Xen采用硬件虚拟化技术有了更多的历史包袱,不如KVM新兵上阵一身轻。
2008年9月4日,Redhat公司以1.07亿美元收购了Qumranet公司,包括它的KVM开源项
目和开发人员。自此,Redhat开始在其RHEL发行版中集成KVM,逐步取代Xen,并从
RHEL7开始,正式不支持Xen。[1] 对于某些设备,如硬盘、网卡,KVM也支持virtio的半虚拟化方式。
[2] 这是一家以色列的创业公司,提供桌面虚拟化产品(VDI),KVM就是其后台虚拟化
的VMM。
[3] Xen先于KVM出现,并且在KVM出现时已经是一个成熟的开源VMM。1.3.2 KVM的功能概览
KVM从诞生开始就定位于基于硬件虚拟化支持的全虚拟化实现。它以内核模块的形
式加载之后,就将Linux内核变成了一个Hypervisor,但硬件管理等还是通过Linux kernel
来完成的,所以它是一个典型的Type 2 Hypervisor,如图1-7所示。
图1-7 KVM功能框架[1]一个KVM客户机对应于一个Linux进程,每个vCPU则是这个进程下的一个线程,还
有单独的处理IO的线程,也在一个线程组内。所以,宿主机上各个客户机是由宿主机内
核像调度普通进程一样调度的,即可以通过Linux的各种进程调度的手段来实现不同客户
机的权限限定、优先级等功能。
客户机所看到的硬件设备是QEMU模拟出来的(不包括VT-d透传的设备,详见6.2
节),当客户机对模拟设备进行操作时,由QEMU截获并转换为对实际的物理设备(可能
设置都不实际物理地存在)的驱动操作来完成。
下面介绍一些KVM的功能特性。
1.内存管理
KVM依赖Linux内核进行内存管理。上面提到,一个KVM客户机就是一个普通的
Linux进程,所以,客户机的“物理内存”就是宿主机内核管理的普通进程的虚拟内存。进
而,Linux内存管理的机制,如大页、KSM(Kernel Same Page Merge,内核的同页合
并)、NUMA(Non-Uniform Memory Arch,非一致性内存架构)[2]
、通过mmap的进程间
共享内存,统统可以应用到客户机内存管理上。
早期时候,客户机自身内存访问落实到真实的宿主机的物理内存的机制叫影子页表
(Shadow Page Table)。KVM Hypervisor为每个客户机准备一份影子页表,与客户机自
身页表建立一一对应的关系。客户机自身页表描述的是GVA→GPA[3]
的映射关系;影子
页表描述的是GPA→HPA的映射关系。当客户机操作自身页表的时候,KVM就相应地更
新影子页表。比如,当客户机第一次访问某个物理页的时候,由于Linux给进程的内存通
常都是拖延到最后要访问的一刻才实际分配的,所以,此时影子页表中这个页表项是空
的,KVM Hypervisor会像处理通常的缺页异常那样,把这个物理页补上,再返回客户机
执行的上下文中,由客户机继续完成它的缺页异常。
影子页表的机制是比较拗口,执行的代价也是比较大的。所以,后来,这种靠软件的
GVA→GPA→HVA→HPA的转换被硬件逻辑取代了,大大提高了执行效率。这就是Intel
的EPT或者AMD的NPT技术,两家的方法类似,都是通过一组可以被硬件识别的数据结
构,不用KVM建立并维护额外的影子页表,由硬件自动算出GPA→HPA。现在的KVM默
认都打开了EPTNPT功能。
2.存储和客户机镜像的格式
严格来说,这是QEMU的功能特性。
KVM能够使用Linux支持的任何存储来存储虚拟机镜像,包括具有IDE、SCSI和
SATA的本地磁盘,网络附加存储(NAS)(包括NFS和SAMBACIFS),或者支持iSCSI
和光线通道的SAN。多路径IO可用于改进存储吞吐量和提供冗余。
由于KVM是Linux内核的一部分,它可以利用所有领先存储供应商都支持的一种成熟
且可靠的存储基础架构,它的存储堆栈在生产部署方面具有良好的记录。
KVM还支持全局文件系统(GFS2)等共享文件系统上的虚拟机镜像,以允许客户机
镜像在多个宿主机之间共享或使用逻辑卷共享。磁盘镜像支持稀疏文件形式,支持通过仅
在虚拟机需要时分配存储空间,而不是提前分配整个存储空间,这就提高了存储利用率。KVM的原生磁盘格式为QCOW2,它支持快照,允许多级快照、压缩和加密。
3.实时迁移
KVM支持实时迁移,这提供了在宿主机之间转移正在运行的客户机而不中断服务的
能力。实时迁移对用户是透明的,客户机保持打开,网络连接保持活动,用户应用程序也
持续运行,但客户机转移到了一个新的宿主机上。
除了实时迁移,KVM支持将客户机的当前状态(快照,snapshot)保存到磁盘,以允
许存储并在以后恢复它。
4.设备驱动程序
KVM支持混合虚拟化,其中半虚拟化的驱动程序安装在客户机操作系统中,允许虚
拟机使用优化的IO接口而不使用模拟的设备,从而为网络和块设备提供高性能的IO。
KVM使用的半虚拟化的驱动程序是IBM和Redhat联合Linux社区开发的VirtIO标准;
它是一个与Hypervisor独立的、构建设备驱动程序的接口,允许多种Hypervisor使用一组相
同的设备驱动程序,能够实现更好的对客户机的互操作性。
同时,KVM也支持Intel的VT-d技术,通过将宿主机的PCI总线上的设备透传(pass-
through)给客户机,让客户机可以直接使用原生的驱动程序高效地使用这些设备。这种
使用是几乎不需要Hypervisor的介入的。
5.性能和可伸缩性
KVM也继承了Linux的性能和可伸缩性。KVM在CPU、内存、网络、磁盘等虚拟化性
能上表现出色,大多都在原生系统的95%以上[4]。KVM的伸缩性也非常好,支持拥有多
达288个vCPU和4TB RAM的客户机,对于宿主机上可以同时运行的客户机数量,软件上
无上限[5]。
这意味着,任何要求非常苛刻的应用程序工作负载都可以运行在KVM虚拟机上。
[1] 图片来源:https:en.wikipedia.orgwikiFile:Kernel-based_Virtual_Machine.svg。
[2] 见本书第7章。
[3] GVA:Guest Virtual Address,客户机虚拟地址。GPA:Guest Physical Address,客户
机物理地址。HVA:Host Virtual Address,宿主机虚拟地址。HPA:Host Physical
Address,宿主机物理地址。
[4] 本书第10章有详细测试。
[5] https:access.redhat.comarticles906543。1.3.3 KVM的现状
至本书写作时,KVM已经10周岁了。10年之间,得益于与Linux天然一体以及Redhat
的倾力打造,KVM已经成为Openstack用户选择的最主流的Hypervisor(因为KVM是
Openstack的默认Hypervisor)。来自Openstack的调查显示,KVM占到87%以上的部署份
额[1]
,并且(笔者认为)还会继续增大。可以说,KVM已经主宰了公有云部署的
Hypervisor市场;而在私有云部署方面,尤其大公司内部私有云部署,还是VMware的地
盘,目前受到HyperV的竞争。
功能上,虚拟化发展到今天,各个Hypervisor的主要功能都趋同。KVM作为后起之
秀,并且在公有云上广泛部署,其功能的完备性是毋庸置疑的。并且由于其开源性,反而
较少一些出于商业目的的限制,比如一篇文章
(ftppublic.dhe.ibm.comlinuxpdfsClabby_Analytics_-_VMware_v_KVM.pdf)中比较
VMware EXS与KVM,就是一个例子[2]。
性能上,作为同样开源的Hypervisor,KVM和Xen都很优秀,都能达到原生系统95%
以上的效率(CPU、内存、网络、磁盘等benchmark衡量),KVM甚至还略微好过Xen一
点点[3]。与微软的Hyper-V相比,KVM似乎略逊于最新的Windows 2016上的HyperV,而
好于Windows 2012 R2上的HyperV[4]
,但这是微软的一家之言,笔者没有重新测试验证。
其他与诸如VMware EXS等的性能比较,网上也可以找到很多,读者可以自行搜索。总的
来说,即使各有优劣,虚拟化技术发展到今天已经成熟,KVM也是如此。
[1] http:superuser.openstack.orgarticlesopenstack-user-survey-insights-november-2014。
[2] 事实上,作为商业软件,RHEL、RHEV对KVM的功能也有一些限制,比如客户机数
目,RHEL7限制最多只能启动4个客户机而RHEV则没有。而原生的开源KVM是没有这些
限制的。
[3] https:major.io20140622performance-benchmarks-kvm-vs-xen。
[4] https:blogs.msdn.microsoft.comvirtual_pc_guy20170203hyper-v-vs-kvm-for-openstack-
performance。1.3.4 KVM的展望
经过10年的发展,KVM已经成熟。那么,接下来KVM会怎样进一步发展呢?
1)大规模部署尚有挑战。KVM是Openstack和oVirt
[1]
选择的默认Hypervisor,因而实
际的广泛部署常常是大规模的(large scale,scalability)。这种大规模,一方面指高并
发、高密度,即一台宿主机上支持尽可能多的客户机;另一方面,也指大规模的单个客户
机,即单个客户机配备尽可能多的vCPU和内存等资源,典型的,这类需求来自高性能计
算(HPC)领域。随着硬件尤其是CPU硬件技术的不停发展(物理的processor越来越
多),这种虚拟化的大规模方面的需求也在不停地增大[2]
,并且这不是简单数量的增加,这种增加会伴随着新的挑战等着KVM开发者去解决,比如热迁移的宕机时间
(downtime)就是其中一例。
2)实时性(Realtime)。近几年一个新的趋势就是NFV(Network Functions
Virtualization,网络功能的虚拟化),它指将原先物理的网络设备搬到一个个虚拟的客户
机上,以便更好地实现软件定义网络的愿景。网络设备对实时性的要求是非常高的;而不
巧,NFV的开源平台OPNFV[3]
选择了Openstack,尽管Openstack向下支持各种
Hypervisor,但如前文所说,KVM是其默认以及主要部署的选择,所以NFV实时性的要求
责无旁贷地落到了KVM头上,NFV-KVM[4]
项目应运而生,它作为OPNFV的子项目主要
解决KVM在实时性方面受到的挑战。
3)安全是永恒的主题话题。就像网络病毒永远不停地演变推陈出新一样,新时代的
IT架构的主体,云虚拟化,也会一直受到各类恶意攻击的骚扰,从而陷入道高一尺魔高
一丈的循环。Hypervisor的开发者、应用者会一直从如何更好地隔离客户机、更少的
Hypervisor干预等方面入手,增加虚拟化的安全性。KVM作为Type 2的Hypervisor,天然
地与Host OS有关联,安全性方面的话题更引人注目。同时,硬件厂商如Intel,也会从硬
件层面不停地推出新的安全方面的功能(feature),KVM从软件方面也要跟上脚步,使
能(enable)之。
4)性能调优。如同一句广告词说的:“进无止境”。一方面,新的功能代码的不停引
入总会给性能调优开辟新的空间;另一方面,老的功能的实现也许还有更好的方法。还
有,新的硬件功能的出现,也是性能调优永恒的动力源泉。
[1] https:www.ovirt.org。
[2] 比如,就在本书完稿前不久,KVM对客户机CPU数量的支持就从240个增加到了288
个,以顺应Intel新的Xeon-Phi产品线的功能和性能。
[3] https:www.opnfv.org。
[4] https:wiki.opnfv.orgdisplaykvmNfv-kvm。1.4 其他的虚拟化解决方案简介
1.4.1 Xen
Xen的出现要早于KVM,可以追溯到20世纪90年代。剑桥大学的Ian Pratt和Keir Fraser
在一个叫作Xenoserver的研究项目中开发了Xen虚拟机。在那个年代,硬件虚拟化还没有
出现,所以Xen最开始采用的是半虚拟化的解决方案。
Xen在2002年开源,并在2003年发布了1.0版本、2004年发布了2.0版本,随即被
Redhat、Novell和Sun的Linux发行版集成,作为其虚拟化组件。2005年的3.0版本开始加入
Intel和AMD的硬件虚拟化的支持,以及Intel的IA64架构,从此,Xen也提供全虚拟化解决
方案(HVM),可以运行完全没有修改的客户机操作系统。2007年10月,思杰公司出资5
亿美元收购了XenSource,变成了Xen项目的东家。2013年,Xen成为Linux基金会赞助的
合作项目。
Xen在架构上是一个典型的Type 1 Hypervisor,与KVM形成鲜明对比,如图1-8所示。
严格来说,它没有宿主机的概念,而是由Xen Hypervisor(VMM)完全管控硬件,但用户
却看不见、摸不着它,只能通过特殊的0号虚拟机(Dom0),通过其中xl工具栈(tool
stack)与Xen Hypervisor交互来管理其他普通虚拟机(DomU)。0号虚拟机是一个运行修
改过的半虚拟化的内核的Linux虚拟机。从架构上,Xen的虚拟化方案既利用了Linux内核
的IO部分(Dom0的内核),将Linux内核的CPU、内存管理等核心部分排除在外由自己接
手(Xen Hypervisor),所以,一开始就受到了Linux内核开发人员的抵制,致使Linux内
核作为Dom0对Xen的支持部分一直不能合入Linux内核社区。一直到2010年,在采用基于
内核的PVOPs方式大量重写了Xen代码以后,才勉强合入Linux内核社区。2011年,从
Linux内核2.6.37版本开始,正式支持Xen Dom0。1.4.2 VMware
VMware成立于1998年,是最早专注于虚拟化商业软件(并成功)的公司,从它的名
字也可以看出它对自己的定位和目标。从十几年前虚拟化软件兴起开始,它就是这个市场
的霸主。笔者早年的认知也是虚拟化=VMware。直到最近,在公有云兴起的背景之下,VMware开始受到KVM和Xen等开源项目以及微软AzureHyperV的挑战。VMware最初是
由一对夫妇等几人创立的,2004年被EMC收购。2016年,EMC又被Dell收购,所以现在
VMware是Dell旗下的子公司。
图1-8 Xen的架构
VMware从诞生起就一直专注于虚拟化,其产品线非常全,既有PaaS产品,也有IaaS
产品;既有Hypervisor,也有应用管理、存储管理等配套软件;既有面向个人用户的桌面
级虚拟化产品,也有面向企业的服务器级产品;既有运行于Linux平台上的产品,也有
Windows和Mac平台上的产品。本书只选择最著名的两款产品给大家简单介绍下,更多更
详细的信息大家可以到它的官网查看。
1.VMware Workstation
VMware Workstation是VMware最早的产品,也是最广为人知的产品,1999年发布。
在刚开始的时候,还没有硬件虚拟化技术,所以它是采用二进制翻译的方式实现虚拟化
的。但是由于它的二进制翻译技术独步当时,性能还很出色,尤其跟当时同类产品相比。
可以说,是VMware Workstation奠定了VMware在虚拟化软件行业的地位。VMwareWorkstation是桌面级虚拟化产品,运行在Windows、Linux和Mac操作系统上,是Type 2
Hypervisor。使用它需要购买License,但VMware同时提供了与Workstation功能类似,只
是有所删减的Workstation Player,供大家非商业化地免费使用。
2.VMware ESXi
VMware ESXi是服务器级的虚拟化软件。与Workstation不同,它直接运行在硬件平台
上,是Type1 Hypervisor。在架构上与Xen有些相像,是现在VMware的拳头产品,大多数
大公司的私有云都是用它搭建的。除了vMotion(即Live Migration功能)、HA(High
Availability,指软硬件运行的不间断地冗余备份)等业界常见功能外,ESXi还支持Cisco
Nexus 1000v[1]
,作为分布式虚拟交换机运行在ESXi集群中。
[1] Nexus 1000v是Cisco和VMWare合作的产物。
https:www.vmware.comcompanynewsreleases2008cisco_vmworld08.html。1.4.3 HyperV
与VMware一样,HyperV也是闭源(Close Source,与Opensource相对)的商业软件。
微软从Windows 8Windows Server 2008开始,用它取代原来的Virtual PC,成为Server OS
版本自带的平台虚拟化软件。
HyperV在架构上与Xen类似,也是Type 1 Hypervisor。它有Partition的概念,有一个
Parent Partition,类似于Xen Dom0,有管理硬件资源的权限;HyperV的Child Partion就类
似于普通的客户机DomU。对Hypervisor的请求以及对客户机的管理都要通过Parent
Partition,硬件的驱动也由Parent Partition来完成。客户机看到的都是虚拟出来的硬件资
源,它们对其虚拟硬件资源的访问都会被重定向到Parent Partition,由它来完成实际的操
作,这种重定向是通过VMBus连接Parent Partition的VSP(Virtualization Service Provider)
和child partition的VSC(Virtualization Service Consumer)来完成的,而这个过程对客户机
OS都是透明的。图1-9中,HyperV Hypervisor运行在Ring-1,也就是Intel VMX技术的root
mode(特权模式),而parent partition和child partition的内核都运行在non-root mode的Ring
0和Ring 3,也就是非特权模式的内核态和用户态。这样的架构安全性是比较好的。性能
上如1.3.3节提到的那样,据微软自己说是略好于KVM的。
图1-9 HyperV架构[1]
[1] 图片来源:https:en.wikipedia.orgwikiFile:Hyper-V.png。1.4.4 Container
Container严格来说与前面提到的虚拟化软件不是一个大类,首先,它不是某个虚拟化
软件,而是某类软件的统称,包括Docker和LXC等;其次,它不是硬件平台级的虚拟化技
术,而是软件运行环境的虚拟化,是一种操作系统级的虚拟化技术,与前面提到的不是一
个层次的。
Container技术利用了Linux kernel提供的cgroup、namespace等机制,将应用之间隔离
起来,好像自己是操作系统上的唯一一个应用似的。而Linux kernel除了封装出这些应用
单独的运行环境以外,还可以控制分配给各个应用的资源配额,比如CPU利用率、内存、网络带宽等。
与平台虚拟化技术相比,Container技术省去了启动和维护整个虚拟客户机的开销(硬
件初始化、Kernel boot、init等),因而它非常轻量级,非常适用于PaaS服务模型。但另
一方面,由于各个Contained instance其实还是共用一个OS、一个Kernel,所以安全性比不
上平台虚拟化技术。总而言之,Container和KVM等平台虚拟化技术,目前还是各有所
长,还处在相互取长补短的过程中。1.5 本章小结
本章从云计算的基本概念入手,给读者讲解了SaaS、PaaS、IaaS这3种云服务类型,还讲到了作为云计算底层的虚拟化技术。对于虚拟化技术,着重对KVM的基础架构进行
了介绍,同时对Xen、VMware、HyperV等虚拟化技术以及容器技术也进行了简介。本章
目的在于让读者在开始学习KVM虚拟化技术之前,对虚拟化技术有一个整体的简明扼要
的认识。第2章 KVM原理简介
2.1 硬件虚拟化技术
通过第1章的介绍,大家已经知道KVM虚拟化必须依赖于硬件辅助的虚拟化技术,本
节就来介绍一下硬件虚拟化技术。
最早的硬件虚拟化技术出现在1972年的大型机IBM System370系统上,而真正让硬件
虚拟化技术“走入寻常百姓家”的是2005年年末Intel发布的VT-x硬件虚拟化技术,以及
AMD于2006年发布的AMD-V。本书中除了特别说明,默认以Intel的硬件虚拟化技术作为
代表来介绍。2.1.1 CPU虚拟化
CPU是计算机系统最核心的模块,我们的程序执行到最后都是翻译为机器语言在CPU
上执行的。在没有CPU硬件虚拟化技术之前,通常使用指令的二进制翻译(binary
translation)来实现虚拟客户机中CPU指令的执行,很早期的VMware就使用这样的方案,其指令执行的翻译比较复杂,效率比较低。所以Intel最早发布的虚拟化技术就是CPU虚拟
化方面的,这才为本书的主角——KVM的出现创造了必要的硬件条件。
Intel在处理器级别提供了对虚拟化技术的支持,被称为VMX(virtual-machine
extensions)。有两种VMX操作模式:VMX根操作(root operation)与VMX非根操作
(non-root operation)。作为虚拟机监控器中的KVM就是运行在根操作模式下,而虚拟机
客户机的整个软件栈(包括操作系统和应用程序)则运行在非根操作模式下。进入VMX
非根操作模式被称为“VM Entry”;从非根操作模式退出,被称为“VM Exit”。
VMX的根操作模式与非VMX模式下最初的处理器执行模式基本一样,只是它现在支
持了新的VMX相关的指令集以及一些对相关控制寄存器的操作。VMX的非根操作模式是
一个相对受限的执行环境,为了适应虚拟化而专门做了一定的修改;在客户机中执行的一
些特殊的敏感指令或者一些异常会触发“VM Exit”退到虚拟机监控器中,从而运行在VMX
根模式。正是这样的限制,让虚拟机监控器保持了对处理器资源的控制。
一个虚拟机监控器软件的最基础的运行生命周期及其与客户机的交互如图2-1所示。
图2-1 VMM与Guest之间的交互
软件通过执行VMXON指令进入VMX操作模式下;在VMX模式下通过VMLAUNCH
和VMRESUME指令进入客户机执行模式,即VMX非根模式;当在非根模式下触发VM
Exit时,处理器执行控制权再次回到宿主机的虚拟机监控器上;最后虚拟机监控可以执行
VMXOFF指令退出VMX执行模式。
逻辑处理器在根模式和非根模式之间的切换通过一个叫作VMCS(virtual-machinecontrol data structure)的数据结构来控制;而VMCS的访问是通过VMCS指针来操作的。
VMCS指针是一个指向VMCS结构的64位的地址,使用VMPTRST和VMPTRLD指令对
VMCS指针进行读写,使用MREAD、VMWRITE和VMCLEAR等指令对VMCS实现配置。
对于一个逻辑处理器,它可以维护多个VMCS数据结构,但是在任何时刻只有一个
VMCS在当前真正生效。多个VMCS之间也是可以相互切换的,VMPTRLD指令就让某个
VMCS在当前生效,而其他VMCS就自然成为不是当前生效的。一个虚拟机监控器会为一
个虚拟客户机上的每一个逻辑处理器维护一个VMCS数据结构。
根据Intel的官方文档,我们这里列举部分在非根模式下会导致“VM Exit”的敏感指令
和一些异常供读者朋友参考,这对于理解KVM的执行机制是必要的,因为KVM也必须按
照CPU的硬件规范来实现虚拟化软件逻辑。
1)一定会导致VM Exit的指令:CPUID、GETSEC、INVD、XSETBV等,以及VMX
模式引入的INVEPT、INVVPID、VMCALL、VMCLEAR、VMLAUNCH、VMPTRLD、VMPTRST、VMRESUME、VMXOFF、VMXON等。
2)在一定的设置条件下会导致VM Exit的指令[1]
:CLTS、HLT、IN、OUT、INVLPG、INVPCID、LGDT、LMSW、MONITOR、MOV from CR3、MOV to CR3、MWAIT、MWAIT、RDMSR、RWMSR、VMREAD、VMWRITE、RDRAND、RDTSC、XSAVES、XRSTORS等。如在处理器的虚拟机执行控制寄存器中的“HLT exiting”比特位
被置为1时,HLT的执行就会导致VM Exit。
3)可能会导致VM Exit的事件:一些异常、三次故障(Triple fault)、外部中断、不
可屏蔽中断(NMI)、INIT信号、系统管理中断(SMI)等。如在虚拟机执行控制寄存器
中的“NMI exiting”比特位被置为1时,不可屏蔽中断就会导致VM Exit。
最后提一下,由于发生一次VM Exit的代价是比较高的(可能会消耗成百上千个CPU
执行周期,而平时很多指令是几个CPU执行周期就能完成),所以对于VM Exit的分析是
虚拟化中性能分析和调优的一个关键点。
[1] 并没有完全列举导致VM Exit的所有指令,感兴趣的读者可以进一步阅读Intel软件开发
者手册中“VMX NON-ROOT OPERATION”章节中的详细描述。2.1.2 内存虚拟化
内存虚拟化的目的是给虚拟客户机操作系统提供一个从0地址开始的连续物理内存空
间,同时在多个客户机之间实现隔离和调度。在虚拟化环境中,内存地址的访问会主要涉
及以下4个基础概念,图2-2形象地展示了虚拟化环境中内存地址。
图2-2 虚拟化环境下的内存地址
1)客户机虚拟地址,GVA(Guest Virtual Address)
2)客户机物理地址,GPA(Guest Physical Address)
3)宿主机虚拟地址,HVA(Host Virtual Address)
4)宿主机物理地址,HPA(Host Physical Address)
内存虚拟化就是要将客户机虚拟地址(GVA)转化为最终能够访问的宿主机上的物
理地址(HPA)。对于客户机操作系统而言,它不感知内存虚拟化的存在,在程序访问客户机中虚拟地址时,通过CR3寄存器可以将其转化为物理地址,但是在虚拟化环境中这个
物理地址只是客户机的物理地址,还不是真实内存硬件上的物理地址。所以,虚拟机监控
器就需要维护从客户机虚拟地址到宿主机物理地址之间的一个映射关系,在没有硬件提供
的内存虚拟化之前,这个维护映射关系的页表叫作影子页表(Shadow Page Table)。内存
的访问和更新通常是非常频繁的,要维护影子页表中对应关系会非常复杂,开销也较大。
同时需要为每一个客户机都维护一份影子页表,当客户机数量较多时,其影子页表占用的
内存较大也会是一个问题。
Intel CPU在硬件设计上就引入了EPT(Extended Page Tables,扩展页表),从而将客
户机虚拟地址到宿主机物理地址的转换通过硬件来实现。当然,这个转换是通过两个步骤
来实现的,如图2-3所示。首先,通过客户机CR3寄存器将客户机虚拟地址转化为客户机
物理地址,然后通过查询EPT来实现客户机物理地址到宿主机物理地址的转化。EPT的控
制权在虚拟机监控器中,只有当CPU工作在非根模式时才参与内存地址的转换。使用EPT
后,客户机在读写CR3和执行INVLPG指令时不会导致VM Exit,而且客户页表结构自身
导致的页故障也不会导致VM Exit。所以通过引入硬件上EPT的支持,简化了内存虚拟化
的实现复杂度,同时也提高了内存地址转换的效率。
图2-3 基于EPT的内存地址转换
除了EPT,Intel在内存虚拟化效率方面还引入了VPID(Virtual-processor identifier)特
性,在硬件级对TLB资源管理进行了优化。在没有VPID之前,不同客户机的逻辑CPU在
切换执行时需要刷新TLB,而TLB的刷新会让内存访问的效率下降。VPID技术通过在硬
件上为TLB增加一个标志,可以识别不同的虚拟处理器的地址空间,所以系统可以区分虚
拟机监控器和不同虚拟机上不同处理器的TLB,在逻辑CPU切换执行时就不会刷新TLB,而只需要使用对应的TLB即可。VPID的示意图如图2-4所示。当CPU运行在非根模式下,且虚拟机执行控制寄存器的“enable VPID”比特位被置为1时,当前的VPID的值是VMCS中
的VPID执行控制域的值,其值是非0的。VPID的值在3种情况下为0,第1种是在非虚拟化
环境中执行时,第2种是在根模式下执行时,第3种情况是在非根模式下执行但“enable
VPID”控制位被置0时。图2-4 VPID示意图2.1.3 IO虚拟化
在虚拟化的架构下,虚拟机监控器必须支持来自客户机的IO请求。通常情况下有以
下4种IO虚拟化方式。
1)设备模拟:在虚拟机监控器中模拟一个传统的IO设备的特性,比如在QEMU中模
拟一个Intel的千兆网卡或者一个IDE硬盘驱动器,在客户机中就暴露为对应的硬件设备。
客户机中的IO请求都由虚拟机监控器捕获并模拟执行后返回给客户机。
2)前后端驱动接口:在虚拟机监控器与客户机之间定义一种全新的适合于虚拟化环
境的交互接口,比如常见的virtio协议就是在客户机中暴露为virtio-net、virtio-blk等网络和
磁盘设备,在QEMU中实现相应的virtio后端驱动。
3)设备直接分配:将一个物理设备,如一个网卡或硬盘驱动器直接分配给客户机使
用,这种情况下IO请求的链路中很少需要或基本不需要虚拟机监控器的参与,所以性能
很好。
4)设备共享分配:其实是设备直接分配方式的一个扩展。在这种模式下,一个(具
有特定特性的)物理设备可以支持多个虚拟机功能接口,可以将虚拟功能接口独立地分配
给不同的客户机使用。如SR-IOV就是这种方式的一个标准协议。
表2-1展示了这4种IO虚拟化方式的优缺点,给读者一个概括性的认识。在这4种方式
中,前两种都是纯软件的实现,后两种都需要特定硬件特性的支持。
表2-1 常见IO虚拟化方式的优缺点
设备直接分配在Intel平台上就是VT-d(Virtualization Technology For Directed IO)特
性,一般在系统BIOS中可以看到相关的参数设置。Intel VT-d为虚拟机监控器提供了几个
重要的能力:IO设备分配、DMA重定向、中断重定向、中断投递等。图2-5描述了在VT-
d硬件特性的帮助下实现的设备直接分配的架构,并与最传统的、通过软件模拟设备的IO
设备虚拟化进行了对比。图2-5 使用VT-d与传统设备完全模拟的虚拟化架构对比[1]
尽管VT-d特性支持的设备直接分配方式性能可以接近物理设备在非虚拟化环境中的
性能极限,但是它有一个缺点:单个设备只能分配给一个客户机,而在虚拟化环境下一个
宿主机上往往运行着多个客户机,很难保证每个客户机都能得到一个直接分配的设备。为
了克服这个缺点,设备共享分配硬件技术就应运而生,其中SR-IOV(Single Root IO
Virtualization and Sharing)就是这样的一个标准。实现了SR-IOV规范的设备,有一个功能
完整的PCI-e设备成为物理功能(Physical Function,PF)。在使能了SR-IOV之后,PF就
会派生出若干个虚拟功能(Virtual Function,VF)。VF看起来依然是一个PCI-e设备,它
拥有最小化的资源配置,有用独立的资源,可以作为独立的设备直接分配给客户机使用。
Intel的很多高级网卡如82599系列网卡就支持SR-IOV特性,一个85299网卡PF就即可配置
出多达63个VF,基本可满足单个宿主机上的客户机分配使用。当然,SR-IOV这种特性可
以看作VT-d的一个特殊例子,所以SR-IOV除了设备本身要支持该特性,同时也需要硬件
平台打开VT-d特性支持。图2-6展示了一个Intel以太网卡支持SR-IOV的硬件基础架构。图2-6 支持SR-IOV的Intel网卡架构图
[1] 该图摘自文档Intel Virtualization Technology for Directed IO Architecture Specification。2.1.4 Intel虚拟化技术发展
虚拟化技术从最初的纯软件的虚拟化技术,逐步发展到硬件虚拟化技术的支持,时至
今日硬件虚拟化技术已比较成熟。前面3小节已经分别就各种硬件虚拟化技术进行了介
绍,这里以Intel平台为例,再对其做一个小结。
Intel硬件虚拟化技术大致分为如下3个类别(这个顺序也基本上是相应技术出现的时
间先后顺序)。
1)VT-x技术:是指Intel处理器中进行的一些虚拟化技术支持,包括CPU中引入的最
基础的VMX技术,使得KVM等硬件虚拟化基础的出现成为可能。同时也包括内存虚拟化
的硬件支持EPT、VPID等技术。
2)VT-d技术:是指Intel的芯片组的虚拟化技术支持,通过Intel IOMMU可以实现对
设备直接分配的支持。
3)VT-c技术:是指Intel的IO设备相关的虚拟化技术支持,主要包含两个技术:一个
是借助虚拟机设备队列(VMDq)最大限度提高IO吞吐率,VMDq由Intel网卡中的专用硬
件来完成;另一个是借助虚拟机直接互连(VMDc)大幅提升虚拟化性能,VMDc主要就
是基于SR-IOV标准将单个Intel网卡产生多个VF设备,用来直接分配给客户机。
图2-7展示了Intel的硬件虚拟化技术的发展线路图,从中我们可以看到从2005年开始
支持VT-x硬件虚拟化,到现在较多的SR-IOV等VT-d的虚拟化技术,硬件虚拟化技术家族
有了越来越多的成员,技术特性也逐步完善。如何在具体业务的生产环境中充分利用硬件
虚拟化技术带来的技术红利,构建高性能、可扩展、易维护的虚拟化环境,可能是大家学
习虚拟化的一个主要目标。通过本书,希望大家也能够了解一些实践经验和受到一些启
发。图2-7 Intel硬件虚拟化技术发展线路图2.2 KVM架构概述
上一节介绍了CPU、内存、IO等硬件虚拟化技术。KVM就是在硬件辅助虚拟化技术
之上构建起来的虚拟机监控器。当然,并非要所有这些硬件虚拟化都支持才能运行KVM
虚拟化,KVM对硬件最低的依赖是CPU的硬件虚拟化支持,比如:Intel的VT技术和AMD
的AMD-V技术,而其他的内存和IO的硬件虚拟化支持,会让整个KVM虚拟化下的性能
得到更多的提升。
KVM虚拟化的核心主要由以下两个模块组成:
1)KVM内核模块,它属于标准Linux内核的一部分,是一个专门提供虚拟化功能的
模块,主要负责CPU和内存的虚拟化,包括:客户机的创建、虚拟内存的分配、CPU执行
模式的切换、vCPU寄存器的访问、vCPU的执行。
2)QEMU用户态工具,它是一个普通的Linux进程,为客户机提供设备模拟的功能,包括模拟BIOS、PCIPCIE总线、磁盘、网卡、显卡、声卡、键盘、鼠标等。同时它通过
ioctl系统调用与内核态的KVM模块进行交互。
KVM是在硬件虚拟化支持下的完全虚拟化技术,所以它能支持在相应硬件上能运行
的几乎所有的操作系统,如:Linux、Windows、FreeBSD、MacOS等。KVM的基础架构
如图2-8所示。在KVM虚拟化架构下,每个客户机就是一个QEMU进程,在一个宿主机上
有多少个虚拟机就会有多少个QEMU进程;客户机中的每一个虚拟CPU对应QEMU进程中
的一个执行线程;一个宿主机中只有一个KVM内核模块,所有客户机都与这个内核模块
进行交互。图2-8 KVM虚拟化基础架构2.3 KVM内核模块
KVM内核模块是标准Linux内核的一部分,由于KVM的存在让Linux本身就变成了一
个Hypervisor,可以原生地支持虚拟化功能。目前,KVM支持多种处理器平台,它支持最
常见的以Intel和AMD为代表的x86和x86_64平台,也支持PowerPC、S390、ARM等非x86
架构的平台。
KVM模块是KVM虚拟化的核心模块,它在内核中由两部分组成:一个是处理器架构
无关的部分,用lsmod命令中可以看到,叫作kvm模块;另一个是处理器架构相关的部
分,在Intel平台上就是kvm_intel这个内核模块。KVM的主要功能是初始化CPU硬件,打
开虚拟化模式,然后将虚拟客户机运行在虚拟机模式下,并对虚拟客户机的运行提供一定
的支持。
KVM仅支持硬件辅助的虚拟化,所以打开并初始化系统硬件以支持虚拟机的运行,是KVM模块的职责所在。以KVM在Intel公司的CPU上运行为例,在被内核加载的时候,KVM模块会先初始化内部的数据结构;做好准备之后,KVM模块检测系统当前的CPU,然后打开CPU控制寄存器CR4中的虚拟化模式开关,并通过执行VMXON指令将宿主操作
系统(包括KVM模块本身)置于CPU执行模式的虚拟化模式中的根模式;最后,KVM模
块创建特殊设备文件devkvm并等待来自用户空间的命令。接下来,虚拟机的创建和运行
将是一个用户空间的应用程序(QEMU)和KVM模块相互配合的过程。
devkvm这个设备可以被当作一个标准的字符设备,KVM模块与用户空间QEMU的
通信接口主要是一系列针对这个特殊设备文件的loctl调用。当然,每个虚拟客户机针
对devkvm文件的最重要的loctl调用就是“创建虚拟机”。在这里,“创建虚拟机”可以理解
成KVM为了某个特定的虚拟客户机(用户空间程序创建并初始化)创建对应的内核数据
结构。同时,KVM还会返回一个文件句柄来代表所创建的虚拟机。针对该文件句柄的
loctl调用可以对虚拟机做相应的管理,比如创建用户空间虚拟地址和客户机物理地址及真
实内存物理地址的映射关系,再比如创建多个可供运行的虚拟处理器(vCPU)。同样,KVM模块会为每一个创建出来的虚拟处理器生成对应的文件句柄,对虚拟处理器相应的
文件句柄进行相应的loctl调用,就可以对虚拟处理器进行管理。
针对虚拟处理器的最重要的loctl调用就是“执行虚拟处理器”。通过它,用户空间准备
好的虚拟机在KVM模块的支持下,被置于虚拟化模式中的非根模式下,开始执行二进制
指令。在非根模式下,所有敏感的二进制指令都会被处理器捕捉到,处理器在保存现场之
后自动切换到根模式,由KVM决定如何进一步处理(要么由KVM模块直接处理,要么返
回用户空间交由用户空间程序处理)。
除了处理器的虚拟化,内存虚拟化也是由KVM模块实现的,包括前面提到的使用硬
件提供的EPT特性,通过两级转换实现客户机虚拟地址到宿主机物理地址之间的转换。
处理器对设备的访问主要是通过IO指令和MMIO,其中IO指令会被处理器直接截
获,MMIO会通过配置内存虚拟化来捕捉。但是,外设的模拟一般不由KVM模块负责。
一般来说,只有对性能要求比较高的虚拟设备才会由KVM内核模块来直接负责,比如虚
拟中断控制器和虚拟时钟,这样可以大量减少处理器模式切换的开销。而大部分的输入输
出设备交给下一节将要介绍的用户态程序QEMU来负责。2.4 QEMU用户态设备模拟
QEMU原本就是一个著名的开源虚拟机软件项目,而不是KVM虚拟化软件的一部
分。与KVM不同,QEMU最初实现的虚拟机是一个纯软件的实现,通过二进制翻译来实
现虚拟化客户机中的CPU指令模拟,所以性能比较低。但是,其优点是跨平台,QEMU支
持在Linux、Windows、FreeBSD、Solaris、MacOS等多种操作系统上运行,能支持在
QEMU本身编译运行的平台上就实现虚拟机的功能,甚至可以支持客户机与宿主机并不是
同一个架构(比如在x86平台上运行ARM客户机)。作为一个存在已久的虚拟机监控器软
件,QEMU的代码中有完整的虚拟机实现,包括处理器虚拟化、内存虚拟化,以及KVM
也会用到的虚拟设备模拟(比如网卡、显卡、存储控制器和硬盘等)。
除了二进制翻译的方式,QEMU也能与基于硬件虚拟化的Xen、KVM结合,为它们提
供客户机的设备模拟。通过与KVM的密切结合,让虚拟化的性能提升得非常高,在真实
的企业级虚拟化场景中发挥重要作用,所以我们通常提及KVM虚拟化时就会
说“QEMUKVM”这样的软件栈。
最早期的KVM开发者们为了简化软件架构和代码重用,根据KVM特性在QEMU的基
础上进行了修改(当然这部分修改已经合并回QEMU的主干代码,故现在的QEMU已原生
支持KVM虚拟化特性)。从图2-8可以看出,每一个虚拟客户机在宿主机中就体现为一个
QEMU进程,而客户机的每一个虚拟CPU就是一个QEMU线程。虚拟机运行期间,QEMU
会通过KVM模块提供的系统调用进入内核,由KVM模块负责将虚拟机置于处理器的特殊
模式下运行。遇到虚拟机进行IO操作时,KVM模块会从上次的系统调用出口处返回
QEMU,由QEMU来负责解析和模拟这些设备。
从QEMU角度来看,也可以说QEMU使用了KVM模块的虚拟化功能,为自己的虚拟
机提供硬件虚拟化的加速,从而极大地提高了虚拟机的性能。除此之外,虚拟机的配置和
创建,虚拟机运行依赖的虚拟设备,虚拟机运行时的用户操作环境和交互,以及一些针对
虚拟机的特殊技术(如:动态迁移),都是由QEMU自己实现的。
QEMU除了提供完全模拟的设备(如:e1000网卡、IDE磁盘等)以外,还支持virtio
协议的设备模拟。virtio是一个沟通客户机前端设备与宿主机上设备后端模拟的比较高性
能的协议,在前端客户机中需要安装相应的virtio-blk、virtio-scsi、virtio-net等驱动,而
QEMU就实现了virtio的虚拟化后端。QEMU还提供了叫作virtio-blk-data-plane的一种高性
能的块设备IO方式,它最初在QEMU 1.4版本中被引入。virtio-blk-data-plane与传统virtio-
blk相比,它为每个块设备单独分配一个线程用于IO处理,data-plane线程不需要与原
QEMU执行线程同步和竞争锁,而且它使用ioeventfdirqfd机制,同时利用宿主机Linux上
的AIO(异步IO)来处理客户机的IO请求,使得块设备IO效率进一步提高。
总之,QEMU既是一个功能完整的虚拟机监控器,也在QEMUKVM的软件栈中承担
设备模拟的工作。2.5 与QEMUKVM结合的组件
在KVM虚拟化的软件栈中,毋庸置疑的是KVM内核模块与QEMU用户态程序是处于
最核心的位置,有了它们就可通过qemu命令行操作实现完整的虚拟机功能,本书中多数
的实践范例正是通过qemu命令行来演示的。然而,在实际的云计算的虚拟化场景中,为
了更高的性能或者管理的方便性,还有很多的软件可以作为KVM虚拟化实施中的组件,这里简单介绍其中的几个。
1.vhost-net
vhost-net是Linux内核中的一个模块,它用于替代QEMU中的virtio-net用户态的virtio网
络的后端实现。使用vhost-net时,还支持网卡的多队列,整体来说会让网络性能得到较大
提高。在6.1.6节中对vhost-net有更多的介绍。
2.Open vSwitch
Open vSwitch是一个高质量的、多层虚拟交换机,使用开源Apache2.0许可协议,主要
用可移植性强的C语言编写的。它的目的是让大规模网络自动化可以通过编程扩展,同时
仍然支持标准的管理接口和协议(例如NetFlow、sFlow、SPAN、RSPAN、CLI、LACP、802.1ag)。同时也提供了对OpenFlow协议的支持,用户可以使用任何支持OpenFlow协议
的控制器对OVS进行远程管理控制。Open vSwitch被设计为支持跨越多个物理服务器的分
布式环境,类似于VMware的vNetwork分布式vswitch或Cisco Nexus 1000 V。Open vSwitch
支持多种虚拟化技术,包括XenXenServer、KVM和VirtualBox。在KVM虚拟化中,要实
现软件定义网络(SDN),那么Open vSwitch是一个非常好的开源选择。
3.DPDK
DPDK全称是Data Plane Development Kit,最初是由Intel公司维护的数据平面开发工
具集,为Intel x86处理器架构下用户空间高效的数据包处理提供库函数和驱动的支持,现
在也是一个完全独立的开源项目,它还支持POWER和ARM处理器架构。不同于Linux系
统以通用性设计为目的,它专注于网络应用中数据包的高性能处理。具体体现在DPDK应
用程序是运行在用户空间上,利用自身提供的数据平面库来收发数据包,绕过了Linux内
核协议栈对数据包处理过程。其优点是:性能高、用户态开发、出故障后易恢复。在
KVM架构中,为了达到非常高的网络处理能力(特别是小包处理能力),可以选择
DPDK与QEMU中的vhost-user结合起来使用。
4.SPDK
SPDK全称是Storage Performance Development Kit,它可为编写高性能、可扩展的、用户模式的存储程序提供一系列工具及开发库。它与DPDK非常类似,其主要特点是:将
驱动放到用户态从而实现零拷贝、用轮询模式替代传统的中断模式、在所有的IO链路上
实现无锁设计,这些设计会使其性能比较高。在KVM中需要非常高的存储IO性能时,可
以将QEMU与SPDK结合使用。
5.CephCeph是Linux上一个著名的分布式存储系统,能够在维护POSIX兼容性的同时加入复
制和容错功能。Ceph由储存管理器(Object storage cluster对象存储集群,即OSD守护进
程)、集群监视器(Ceph Monitor)和元数据服务器(Metadata server cluster,MDS)构
成。其中,元数据服务器MDS仅仅在客户端通过文件系统方式使用Ceph时才需要。当客
户端通过块设备或对象存储使用Ceph时,可以没有MDS。Ceph支持3种调用接口:对象存
储,块存储,文件系统挂载。在libvirt和QEMU中都有Ceph的接口,所以Ceph与KVM虚拟
化集成是非常容易的。在OpenStack的云平台解决方案中,Ceph是一个非常常用的存储后
端。
6.libguestfs
libguestfs是用于访问和修改虚拟机的磁盘镜像的一组工具集合。libguestfs提供了访问
和编辑客户机中的文件、脚本化修改客户机中的信息、监控磁盘使用和空闲的统计信息、P2V、V2V、创建客户机、克隆客户机、备份磁盘内容、格式化磁盘、调整磁盘大小等非
常丰富的功能。libguestfs还提供了共享库,可以在CC++、Python等编程语言中对其进行
调用。libguestfs不需要启动KVM客户机就可以对磁盘镜像进行管理,功能强大且非常灵
活,是管理KVM磁盘镜像的首选工具。2.6 KVM上层管理工具
一个成熟的虚拟化解决方案离不开良好的管理和运维工具,部署、运维、管理的复杂
度与灵活性是企业实施虚拟化时重点考虑的问题。KVM目前已经有从libvirt API、virsh命
令行工具到OpenStack云管理平台等一整套管理工具,尽管与老牌虚拟化巨头VMware提供
的商业化虚拟化管理工具相比在功能和易用性上有所差距,但KVM这一整套管理工具都
是API化的、开源的,在使用的灵活性以及对其做二次开发的定制化方面仍有一定优势。
根据笔者的实践经验,本节给大家概括性地介绍KVM软件栈中常见的几个管理运维工
具,在第4章将会详细介绍相关内容。
1.libvirt
libvirt是使用最广泛的对KVM虚拟化进行管理的工具和应用程序接口,已经是事实上
的虚拟化接口标准,本节后部分介绍的其他工具都是基于libvirt的API来实现的。作为通
用的虚拟化API,libvirt不但能管理KVM,还能管理VMware、Hyper-V、Xen、VirtualBox
等其他虚拟化方案。
2.virsh
virsh是一个常用的管理KVM虚拟化的命令行工具,对于系统管理员在单个宿主机上
进行运维操作,virsh命令行可能是最佳选择。virsh是用C语言编写的一个使用libvirt API的
虚拟化管理工具,其源代码也是在libvirt这个开源项目中的。
3.virt-manager
virt-manager是专门针对虚拟机的图形化管理软件,底层与虚拟化交互的部分仍然是
调用libvirt API来操作的。virt-manager除了提供虚拟机生命周期(包括:创建、启动、停
止、打快照、动态迁移等)管理的基本功能,还提供性能和资源使用率的监控,同时内置
了VNC和SPICE客户端,方便图形化连接到虚拟客户机中。virt-manager在RHEL、CentOS、Fedora等操作系统上是非常流行的虚拟化管理软件,在管理的机器数量规模较小
时,virt-manager是很好的选择。因其图形化操作的易用性,成为新手入门学习虚拟化操
作的首选管理软件。
4.OpenStack
OpenStack是一个开源的基础架构即服务(IaaS)云计算管理平台,可用于构建共有
云和私有云服务的基础设施。OpenStack是目前业界使用最广泛的功能最强大的云管理平
台,它不仅提供了管理虚拟机的丰富功能,还有非常多其他重要管理功能,如:对象存
储、块存储、网络、镜像、身份验证、编排服务、控制面板等。OpenStack仍然使用libvirt
API来完成对底层虚拟化的管理。2.7 本章小结
本节主要介绍了KVM虚拟化的基本原理,从硬件到软件、从底层到上层都做了一些
介绍,包括:硬件虚拟化技术简介、KVM软件架构概况、KVM内核模块、QEMU用户态
设备模拟、与KVM结合的vhost-net等组件、KVM的管理工具等。由于KVM是基于硬件辅
助的虚拟化软件,故在2.1节又分别介绍了CPU虚拟化、内存虚拟化、IO虚拟化以及Intel
的虚拟化技术发展情况,以帮助读者理解虚拟化原理。同时,通过对QEMUKVM相结合
的组件和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的S390架构、ARM架构(2012年开始[1])等。其中,在x86-64上面的
功能支持是最完善的(主要原因是IntelAMD的x86-64架构在桌面和服务器市场上的主导
地位及其架构的开放性,以及它的开发者众多),本书也采用基于Intel x86-64架构的处理
器作为基本的硬件环境[2]。
在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 IO),建议在BIOS中将其打开,因为后面一些相对高级的设备的
直接分配功能会需要硬件VT-d技术的支持。VT-d是对设备IO的虚拟化硬件支持,在BIOS
中的位置可能为“Advanced→Processor Configuration”或“Advanced→System
Agent(SA)Configuration”,它在BIOS中的标志一般为“Intel(R)VT for Directed IO”或“Intel
VT-d”。
下面以一台Intel Haswell-UP平台的服务器为例,来说明在BIOS中的设置。
1)BIOS中的Advanced选项,如图3-1所示。图3-1 BIOS中的Advanced选项
2)BIOS中Enabled的VT和VT-d选项,如图3-2所示。图3-2 BIOS中Enabled的VT和VT-d选项
对于不同平台或不同厂商的BIOS,VT和VT-d等设置的位置可能是不一样的,需要根
据实际的硬件情况和BIOS中的选项来灵活设置。
设置好了VT和VT-d的相关选项,保存BIOS的设置并退出,系统重启后生效。在
Linux系统中,可以通过检查proccpuinfo文件中的CPU特性标志(flags)来查看CPU目前
是否支持硬件虚拟化。在x86和x86-64平台中,Intel系列CPU支持虚拟化的标志为“vmx”,AMD系列CPU的标志为“svm”。所以可以用以下命令行查看“vmx”或者“svm”标志:
[root@kvm-host ~] grep -E svm|vmx proccpuinfo
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
[1] KVM在ARM处理器上的第一次正式实现,可以参考链接
http:comments.gmane.orggmane.comp.emulators.kvm.devel87136中主题为[PATCH v6
0012]KVMARM Implementation的邮件。
[2] 在本书中,若无特别注明,所有理论和实验都是基于Intel x86-64处理器的。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版的系统来简单介绍[1]
,普
通Linux安装的基本过程不再详细描述,这里主要说明安装过程中一些值得注意的地方。
在选择哪些安装包(SOFTWARE SELECTION)时(图3-3),点进去选择“Server
with GUI”[2]
,而不是默认的“Minimal Install”,如图3-4所示。图3-3 在RHEL 7.3安装过程中的安装包的选择
在选择了“Server with GUI”之后,右侧还有可以额外增加的组件供选择(见图3-4),我们需要选上“Development Tools”,因为在本书的KVM编译过程中以及其他实验中可能
会用到,其中包括一些比较重要的软件包,比如:gcc、git、make等(一般被默认选
中)。可以看到还有“Virtualization Hypervisor”“Virtualization Tools”,这里可以暂时不选
它们(选上也没有关系),因为在本章中会自己编译KVM和QEMU,而在附录A介绍发行
版中的KVM时,我们会安装Virtualization Host环境,并使用发行版中自带的KVM
Virtualization功能。图3-4 Base Environment选择Server with GUI
然后,单击“Done”按钮并继续进行后面的安装流程。可以安装相应的软件包,安装
过程的一个快照如图3-5所示。
在安装完所有软件包后,系统会提示安装完成需要重启系统,重启后即可进入RHEL
7.3系统中。至此,Linux系统就安装完毕了,这就是在本书中作为宿主机(Host)的操作
系统,后面的编译和实验都是在这个宿主机上进行的(当然,我们会使用本章讲述的自己
编译的kernel和QEMU来进行实验)。图3-5 RHEL 7.3安装过程快照
[1] 一些安装步骤可参考Redhat的英文文档:https:access.redhat.comdocumentationen-
USRed_Hat_Enterprise_Linux7htmlInstallation_Guideindex.html。
[2] 这里不选择“Virtualization Host”是因为后面会自己编译安装QEMU。当然选
择“Virtualization Host”并在后面加装GUI软件包也没有关系。自己编译安装的QEMU等工
具会覆盖系统自带的。但无论选择哪种,都要再选上“Development Tools”额外环境包,这
是我们后面编译所需要的。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]
格式)。
1.下载kvm.git
KVM项目的代码是托管在Linux内核官方源码网站http:git.kernel.org上的,可以到上
面查看和下载。该网页上virtkvmkvm.git即KVM项目的代码,它是最新的、功能最丰富
的KVM源代码库(尽管并非最稳定的)。目前,kvm.git的最主要维护者(maintainer)是
来自Redhat公司的Paolo Bonzini和Radim Krcmár。从http:git.kernel.org?p=virtkvmkvm.git
网页可以看到,kvm.git的下载链接有以下3个URL,可用于下载最新的KVM的开发代码仓
库。
git:git.kernel.orgpubscmvirtkvmkvm.git
http:git.kernel.orgpubscmvirtkvmkvm.git
https:git.kernel.orgpubscmvirtkvmkvm.git
这3个URL下载的内容完全一致,根据自己实际情况选择其中一个下载即可。Linux内
核相关的项目一般都使用Git
[2]
作为源代码管理工具,KVM当然也是用Git管理源码的。可
以使用git clone命令来下载KVM的源代码,也可以使用Git工具的其他命令对源码进行各
种管理。这里不详述Git的各种命令,有兴趣的读者可以参考其他文稿。
kvm.git的下载方式和过程为以下命令行所示:
[root@kvm-host ~] git clone
git:git.kernel.orgpubscmvirtkvmkvm.git
Cloning into 'kvm'...
remote: Counting objects: 5017872, done.
remote: Compressing objects: 100% (938249938249), done.
Receiving objects: 100% (50178725017872), 1006.69 MiB | 60.72 MiBs, done.
remote: Total 5017872 (delta 4229078), reused 4826094 (delta 4038351)Resolving deltas: 100% (42290784229078), done.
Checking out files: 100% (5591455914), done.
[root@kvm-host ~] cd kvm
[root@kvm-host kvm] pwd
rootkvm
2.下载linux.git
Linux内核的官方网站为http:kernel.org,其中源代码管理网站为http:git.kernel.org,可以在那里找到最新的linux.git代码。在源码管理网站上,我们看到有多个linux.git,我们
选择Linus Torvalds[3]
的源码库(也即是Linux内核的主干)。在内核源码的网
页http:git.kernel.org?p=linuxkernelgittorvaldslinux.git中可以看到,其源码仓库也有以下
3个链接可用:
git:git.kernel.orgpubscmlinuxkernelgittorvaldslinux.git
http:git.kernel.orgpubscmlinuxkernelgittorvaldslinux.git
https:git.kernel.orgpubscmlinuxkernelgittorvaldslinux.git
这3个URL中源码内容是完全相同的,可以使用git clone命令复制到本地,其具体操作
方式与前一种(kvm.git)的下载方式完全一样。
3.下载Linux的Tarball
在Linux官方网站(http:kernel.org)上,也提供Linux内核的Tarball文件下载。除了
在其首页上单击一些Tarball之外,也可以到以下网址下载Linux内核的各个版本的
Tarball:
·ftp:ftp.kernel.orgpublinuxkernel。
·http:www.kernel.orgpublinuxkernel。
kernel.org还提供一种rsync的方式下载,此处不详细叙述,请参见其官网首页的提
示。
以用wget下载linux-4.8.1.tar.xz为例,命令行代码如下:
[root@kvm-host ~] wget
https:cdn.kernel.orgpublinuxkernelv4.xlinux-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.cnkernel与http:www.kernel.orgpublinuxkernel是同步
的,用起来比较方便。
·北京交通大学的一个开源镜像站:http:mirror.bjtu.edu.cnkernellinuxkernel。
还有以下两个镜像站推荐给大家:
·网易开源镜像站,http:mirrors.163.com。
·搜狐开源镜像站,http:mirrors.sohu.com。
[1] Tarball是UNIXLinux世界中的一个术语,用于指代tar档案(通过tar命令打包归档后的
文件,如常见的.tar、.tar.gz、.tar.bz2结尾的档案文件)。
[2] Git是一个高效、快速的分布式的版本控制工具和源代码管理工具,最初是Linus
Torvalds为Linux内核开发而设计和开发的工具,是Linux中最广泛使用的SCM工具。另
外,一个基于Git的非常著名的源码托管网站https:github.com也值得推荐一下。
[3] Linus Torvalds,就是那个著名的Linux创始人,从芬兰移民到美国,是著名的软件工程
师和黑客。1991年,在芬兰赫尔辛基大学读书的Linus发布了后来最流行的开源操作系统
内核Linux的第一个版本。3.3.2 配置KVM
上面3种方式下载的源代码都可以同样地进行配置和编译,本章以开发中的最新源代
码仓库kvm.git来讲解KVM的配置和编译等。KVM是作为Linux内核中的一个module而存
在的,而kvm.git是一个包含了最新的KVM模块开发中代码的完整的Linux内核源码仓库。
它的配置方式与普通的Linux内核配置完全一样,只是需要注意将KVM相关的配置选择为
编译进内核或者编译为模块。
在kvm.git(Linux kernel)代码目录下,运行“make help”命令可以得到一些关于如何
配置和编译kernel的帮助手册。命令行如下:
[root@kvm-host kvm] make help
Cleaning targets:
clean - Remove most generated files but keep the config and enough
build support to build external modules
mrproper - Remove all generated files + config + various backup files
distclean - mrproper + remove editor backup and patch files
Configuration targets:
config - Update current config utilising a line-oriented program
nconfig - Update current config utilising a ncurses menu based program
menuconfig - Update current config utilising a menu based program
xconfig - Update current config utilising a Qt based front-end
gconfig - Update current config utilising a GTK+ based front-end
oldconfig - Update current config utilising a provided .config as base
localmodconfig - Update current config disabling modules not loaded
localyesconfig - Update current config converting local mods to core
silentoldconfig - Same as oldconfig, but quietly, additionally update deps
defconfig - New config with default from ARCH supplied defconfig
savedefconfig - Save current config as .defconfig (minimal config)
allnoconfig - New config where all options are answered with no
allyesconfig - New config where all options are accepted with yes
allmodconfig - New config selecting modules when possible
alldefconfig - New config with all symbols set to default
randconfig - New config with random answer to all options
listnewconfig - List new options
olddefconfig - Same as silentoldconfig but sets new symbols to their default
value
kvmconfig - Enable additional options for kvm guest kernel support
xenconfig - Enable additional options for xen dom0 and guest kernel support
tinyconfig - Configure the tiniest possible kernel
对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平台上,默认配置为archx86configsx86_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所示。图3-6 make menuconfig命令的选择界面
图3-7 Virtualization中的配置选项
提示:为了确保生成的.config文件生成的kernel是实际可以工作的(直接make
defconfig生成的.config文件编译出来的kernel常常是不能工作的),最佳实践是以你当前
使用的config(比如,我们安装好RHEL 7.3的OS以后,bootconfig-3.10.0-xxx.x86_64)为
基础,将它复制到你的linux目录下,重命名为.config,然后通过make olddefconfig更新补
充一下这个.config。
在配置完成之后,就会在kvm.git目录下面生成一个.config文件。最好检查一下KVM
相关的配置是否正确。在本次配置中,与KVM直接相关的几个配置项主要情况如下:CONFIG_HAVE_KVM=y
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_HAVE_KVM_EVENTFD=y
CONFIG_KVM_APIC_ARCHITECTURE=y
CONFIG_KVM_MMIO=y
CONFIG_KVM_ASYNC_PF=y
CONFIG_HAVE_KVM_MSI=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
CONFIG_KVM_INTEL=m
CONFIG_KVM_AMD is not set
CONFIG_KVM_MMU_AUDIT=y3.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 includegeneratedcompile.h
UPD includegeneratedcompile.h
CC initversion.o
LD initbuilt-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 includeconfigkernel.release
CHK includegenerateduapilinuxversion.h
CHK includegeneratedutsrelease.h
LD archx86bootsetup.elf
OBJCOPY archx86bootsetup.bin
OBJCOPY archx86bootvmlinux.bin
HOSTCC archx86boottoolsbuild
BUILD archx86bootbzImage 这里生成了我们需要的bzImage文件
Setup is 17276 bytes (padded to 17408 bytes).
System is 5662 kB
CRC 3efff614
Kernel: archx86bootbzImage is ready (2)
3)编译kernel和bzImage之后编译内核的模块,命令为“make modules”,其命令行输出如下:
[root@kvm-host kvm] make modules -j 20
IHEX2FW firmwareemi26loader.fw
IHEX2FW firmwareemi26firmware.fw
IHEX2FW firmwareemi26bitstream.fw
IHEX2FW firmwareemi62loader.fw
IHEX2FW firmwareemi62bitstream.fw
IHEX2FW firmwareemi62spdif.fw
IHEX2FW firmwareemi62midi.fw
H16TOFW firmwareedgeportboot2.fw
H16TOFW firmwareedgeportboot.fw
H16TOFW firmwareedgeportdown.fw
H16TOFW firmwareedgeportdown2.fw
IHEX2FW firmwarewhiteheat_loader.fw
IHEX2FW firmwarewhiteheat.fw
IHEX2FW firmwarekeyspan_pdakeyspan_pda.fw
IHEX2FW firmwarekeyspan_pdaxircom_pgs.fw 3.3.4 安装KVM
编译完KVM之后,下面介绍如何安装KVM。
KVM的安装包括两个步骤:安装module,安装kernel与initramfs。
1.安装module
通过“make modules_install”命令可以将编译好的module安装到相应的目录中,默认情
况下module被安装到libmoduleskernel_versionkernel目录中。
[root@kvm-host kvm] make modules_install
INSTALL libfirmwarewhiteheat.fw
INSTALL libfirmwarekeyspan_pdakeyspan_pda.fw
INSTALL libfirmwarekeyspan_pdaxircom_pgs.fw
DEPMOD 4.8.0+
安装好module之后,可以查看一下相应的安装路径,可看到kvm模块也已经安装。如
下所示:
[root@kvm-host kvm] ll libmodules4.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 libmodules4.8.0+kernelarchx86kvm
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 .archx86bootinstall.sh 4.8.0+ archx86bootbzImage 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 -> bootSystem.map-4.8.0+
lrwxrwxrwx 1 root root 20 Oct 15 15:10 vmlinuz -> bootvmlinuz-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配置文件(如:bootgrub2grub.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 [ xfeature_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=devmapperrhel-root ro rd.lvm.lv=rhelroot crashkernel=auto rd.lvm.lv=rhelswap vconsole.font=latarcyrheb-sun16 vconsole.keymap=us rhgb devdiskby-uuid19d79b0d-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相关的模块加载成功后,检查devkvm这个文件,它是kvm内核模块提供给
用户空间的QEMU程序使用的一个控制接口,它提供了客户机(Guest)操作系统运行所
需要的模拟和实际的硬件设备环境。
[root@kvm-host kvm] ls -l devkvm
crw-rw-rw-+ 1 root kvm 10, 232 Oct 9 15:22 devkvm 3.4 编译和安装QEMU
除了在内核空间的KVM模块之外,在用户空间需要QEMU[1]
来模拟所需要的CPU和
设备模型,以及启动客户机进程,这样才有了一个完整的KVM运行环境。
在编译和安装了KVM并且启动到编译的内核之后,下面来看一下QEMU的编译和安
装。
[1] 关于QEMU项目,可以参考其官方网站:http:wiki.qemu.orgMain_Page。3.4.1 曾经的qemu-kvm
在上一版中,我们是以qemu-kvm为例来讲解QEMUKVM的。qemu-kvm原本是kernel
社区维护的专门用于KVM的QEMU的分支。
在2012年年末的时候,这个分支并入了主流的QEMU(git:git.qemu-
project.orgqemu.git)。从此,不再需要特殊的qemu-kvm,而只是通用的QEMU加上--
enable-kvm选项就可以创建KVM guest了。3.4.2 下载QEMU源代码
在并入主流QEMU以后,目前的QEMU项目针对KVMx86的部分依然是由Redhat公司
的Paolo Bonzini作为维护者(Maintainer),代码的git url托管在qemu-project.org上。
QEMU开发代码仓库的网页连接为:http:git.qemu.orgqemu.git。
其中,可以看到有如下2个URL链接可供下载开发中的最新qemu-kvm的代码仓库。
git:git.qemu.orgqemu.git
http:git.qemu.orggitqemu.git
可以根据自己实际需要选择当中任一个,用git clone命令下载即可,它们是完全一样
的。
另外,也可以到以下下载链接中根据需要下载最近几个发布版本的代码压缩包。
http:wiki.qemu.orgDownload
在本节后面讲解编译时,是以下载开发中的最新的qemu.git为例的。获取其代码仓库
过程如下:
[root@kvm-host ~] git clone git:git.qemu.orgqemu.git
Cloning into 'qemu'...
remote: Counting objects: 294725, done.
remote: Compressing objects: 100% (5942559425), done.
remote: Total 294725 (delta 238595), reused 289874 (delta 234513)
Receiving objects: 100% (294725294725), 94.23 MiB | 37.66 MiBs, done.
Resolving deltas: 100% (238595238595), 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 [usrlocal]--interp-prefix=PREFIX where to find shared libraries, etc.
use %M for cpu name [usrgnemulqemu-%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 usrlocal
BIOS directory usrlocalshareqemu...ELF interp prefix usrgnemulqemu-%M
Source path rootqemu
C compiler cc
Host C compiler cc...
QEMU_CFLAGS -Iusrincludepixman-1 -Werror -pthread -Iusrincludeglib-2.0 -Iusrlib64glib-2.0include -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-softmmuqemu-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被安装之后的系统状态。
[root@kvm-host qemu] ls usrlocalshareqemu
acpi-dsdt.aml efi-eepro100.rom keymaps openbios-sparc32 pxe-e1000.rom
QEMU,cgthree.bin slof.bin vgabios-qxl.bin
bamboo.dtb efi-ne2k_pci.rom kvmvapic.bin openbios-sparc64
pxe-eepro100.rom qemu-icon.bmp spapr-rtas.bin
vgabios-stdvga.bin
bios-256k.bin efi-pcnet.rom linuxboot.bin palcode-clipper
pxe-ne2k_pci.rom qemu_logo_no_text.svg trace-events-all
vgabios-virtio.bin
bios.bin efi-rtl8139.rom linuxboot_dma.bin petalogix-ml605.dtb
pxe-pcnet.rom QEMU,tcx.bin u-boot.e500
vgabios-VMware.bin
efi-e1000e.rom efi-virtio.rom multiboot.bin petalogix-s3adsp1800.dtb
pxe-rtl8139.rom ......
KVM实战:原理、进阶与性能调优
任永杰 程舟 著
ISBN:978-7-111-61981-9
本书纸版由机械工业出版社于2019年出版,电子版由华章分社(北京华章图文信息有限公
司,北京奥维博世图书发行有限公司)全球范围内制作与发行。
版权所有,侵权必究
客服热线:+ 86-10-68995265
客服信箱:service@bbbvip.com
官方网址:www.hzmedia.com.cn
新浪微博 @华章数媒
微信公众号 华章电子书(微信号:hzebook)目录 前言
第一篇 KVM虚拟化基础
第1章 虚拟化简介
1.1 云计算概述
1.1.1 什么是云计算
1.1.2 云计算的历史
1.1.3 云计算的几种服务模型
1.2 虚拟化技术
1.2.1 什么是虚拟化
1.2.2 软件虚拟化和硬件虚拟化
1.2.3 半虚拟化和全虚拟化
1.2.4 Type1和Type2虚拟化
1.3 KVM简介
1.3.1 KVM的历史
1.3.2 KVM的功能概览
1.3.3 KVM的现状
1.3.4 KVM的展望
1.4 其他的虚拟化解决方案简介
1.4.1 Xen
1.4.2 VMware
1.4.3 HyperV
1.4.4 Container
1.5 本章小结
第2章 KVM原理简介
2.1 硬件虚拟化技术
2.1.1 CPU虚拟化
2.1.2 内存虚拟化
2.1.3 IO虚拟化
2.1.4 Intel虚拟化技术发展
2.2 KVM架构概述
2.3 KVM内核模块
2.4 QEMU用户态设备模拟
2.5 与QEMUKVM结合的组件
2.6 KVM上层管理工具
2.7 本章小结
第3章 构建KVM环境
3.1 硬件系统的配置
3.2 安装宿主机Linux系统
3.3 编译和安装KVM
3.3.1 下载KVM源代码
3.3.2 配置KVM
3.3.3 编译KVM
3.3.4 安装KVM
3.4 编译和安装QEMU3.4.1 曾经的qemu-kvm
3.4.2 下载QEMU源代码
3.4.3 配置和编译QEMU
3.4.4 安装QEMU
3.5 安装客户机
3.6 启动第一个KVM客户机
3.7 本章小结
第4章 KVM管理工具
4.1 libvirt
4.1.1 libvirt简介
4.1.2 libvirt的安装与配置
4.1.3 libvirt域的XML配置文件
4.1.4 libvirt API简介
4.1.5 建立到Hypervisor的连接
4.1.6 libvirt API使用示例
4.2 virsh
4.2.1 virsh简介
4.2.2 virsh常用命令
4.3 virt-manager
4.3.1 virt-manager简介
4.3.2 virt-manager编译和安装
4.3.3 virt-manager使用
4.4 virt-viewer、virt-install、virt-top和libguestfs
4.4.1 virt-viewer
4.4.2 virt-install
4.4.3 virt-top
4.4.4 libguestfs
4.5 云计算管理平台
4.5.1 OpenStack简介
4.5.2 ZStack简介
4.6 本章小结
第5章 KVM核心基础功能
5.1 硬件平台和软件版本说明
5.2 CPU配置
5.2.1 vCPU的概念
5.2.2 SMP的支持
5.2.3 CPU过载使用
5.2.4 CPU模型
5.2.5 进程的处理器亲和性和vCPU的绑定
5.3 内存配置
5.3.1 内存设置基本参数
5.3.2 EPT和VPID简介
5.3.3 内存过载使用
5.4 存储配置
5.4.1 存储配置和启动顺序
5.4.2 qemu-img命令5.4.3 QEMU支持的镜像文件格式
5.4.4 客户机存储方式
5.5 网络配置
5.5.1 用QEMU实现的网络模式
5.5.2 使用直接的网桥模式
5.5.3 用网桥实现NAT模式
5.5.4 QEMU内部的用户模式网络
5.5.5 其他网络选项
5.6 图形显示
5.6.1 SDL的使用
5.6.2 VNC的使用
5.6.3 VNC显示中的鼠标偏移
5.6.4 非图形模式
5.6.5 显示相关的其他选项
5.7 本章小结
第二篇 KVM虚拟化进阶
第6章 KVM设备高级管理
6.1 半虚拟化驱动
6.1.1 virtio概述
6.1.2 安装virtio驱动
6.1.3 使用virtio_balloon
6.1.4 使用virtio_net
6.1.5 使用virtio_blk
6.1.6 内核态的vhost-net后端以及网卡多队列
6.1.7 使用用户态的vhost-user作为后端驱动
6.1.8 kvm_clock配置
6.1.9 对Windows客户机的优化
6.2 设备直接分配(VT-d)
6.2.1 VT-d概述
6.2.2 VFIO简介
6.2.3 VT-d环境配置
6.2.4 VT-d操作示例
6.2.5 SR-IOV技术
6.3 热插拔
6.3.1 PCI设备热插拔
6.3.2 PCI设备热插拔示例
6.3.3 CPU的热插拔
6.3.4 内存的热插拔
6.3.5 磁盘的热插拔
6.3.6 网卡接口的热插拔
6.4 本章小结
第7章 KVM内存管理高级技巧
7.1 大页
7.1.1 大页的介绍
7.1.2 KVM虚拟化对大页的利用
7.2 透明大页7.3 KSM
7.3.1 KSM基本原理
7.3.2 KSM操作实践
7.3.3 QEMU对KSM的控制
7.4 与NUMA相关的工具
7.4.1 numastat
7.4.2 numad
7.4.3 numactl
7.5 本章小结
第8章 KVM迁移
8.1 动态迁移
8.1.1 动态迁移的概念
8.1.2 动态迁移的效率和应用场景
8.1.3 KVM动态迁移原理
8.1.4 KVM动态迁移实践
8.1.5 VT-dSR-IOV的动态迁移
8.2 迁移到KVM虚拟化环境
8.2.1 virt-v2v工具介绍
8.2.2 从Xen迁移到KVM
8.2.3 从VMware迁移到KVM
8.2.4 从VirtualBox迁移到KVM
8.2.5 从物理机迁移到KVM虚拟化环境(P2V)
8.3 本章小结
第9章 其他高级功能
9.1 嵌套虚拟化
9.1.1 嵌套虚拟化的基本概念
9.1.2 KVM嵌套KVM
9.2 KVM安全
9.2.1 SMEPSMAPMPX
9.2.2 控制客户机的资源使用——cgroups
9.2.3 SELinux和sVirt
9.2.4 其他安全策略
9.3 CPU指令相关的性能优化
9.3.1 AVXAVX2AVX512
9.3.2 XSAVE指令集
9.3.3 AES新指令
9.3.4 完全暴露宿主机CPU特性
9.4 QEMU监控器
9.4.1 QEMU monitor的切换和配置
9.4.2 常用命令介绍
9.5 qemu命令行参数
9.5.1 回顾已用过的参数
9.5.2 其他常用参数
9.6 本章小结
第三篇 性能测试与调优
第10章 KVM性能测试及参考数据10.1 虚拟化性能测试简介
10.2 CPU性能测试
10.2.1 CPU性能测试工具
10.2.2 测试环境配置
10.2.3 性能测试方法
10.2.4 性能测试数据
10.3 内存性能测试
10.3.1 内存性能测试工具
10.3.2 测试环境配置
10.3.3 性能测试方法
10.3.4 性能测试数据
10.4 网络性能测试
10.4.1 网络性能测试工具
10.4.2 测试环境配置
10.4.3 性能测试方法
10.4.4 性能测试数据
10.5 磁盘IO性能测试
10.5.1 磁盘IO性能测试工具
10.5.2 测试环境配置
10.5.3 性能测试方法
10.5.4 性能测试数据
10.6 CPU指令集对性能的提升
10.7 其他影响客户机性能的因素
10.8 本章小结
附录A Linux发行版中的KVM
附录B 参与KVM开源社区前言
为什么要写这本书
自《KVM虚拟化技术:实战与原理解析》(以下简称“上一本书”)出版以来,受到
了读者的热烈欢迎,几度脱销重印。这给了笔者强烈的鼓舞和责任感,觉得有必要与时俱
进给读者介绍最新的KVM虚拟化技术的相关知识。
从上一本书出版后到现在近5年时间里,国内虚拟化技术迅速普及,云计算应用风起
云涌,阿里云、腾讯云、华为云等国内云服务提供商迅速崛起,使得云计算、虚拟化不再
是原来象牙塔里虚无缥缈的技术概念,而是与普通大众日常生活息息相关的新名词,KVM被这几大云服务提供商广泛采用[1]
,使得它成为云计算世界里事实上的虚拟化标
准。在这样的市场背景下,以Intel为代表的x86硬件厂商,这些年也愈加重视虚拟化技术
的硬件支持与创新[2]
,ARM平台的硬件虚拟化支持也愈加完善。硬件层面的创新也促使
QEMU、KVM在软件层面日新月异。比如,从2013年第1版发行至今,KVM(内核)版
本从3.5发展到了4.8;QEMU版本从1.3发展到了2.7;专门针对KVM的qemu-kvm代码树已
经废弃(被合并到了主流QEMU中)……因此,上一本书中的很多用例、方法和结论等,在新的代码环境下已经有些不合时宜,甚至会出错。我们有必要给读者提供最新且正确的
信息。
相对于上一本书的修改
总体来说,我们对上一本书里所有的用例、图例都做了大量修改更新,实验环境采用
笔者写作时的最新技术:硬件平台采用Intel Broadwell Xeon Server,KVM(内核)为4.8
版本,QEMU为2.7版本,操作系统环境是RHEL 7.3。文中注释改成脚注的形式,而不是
像上一本书那样出现在每章末尾。我们认为这样更方便读者阅读。当然,文字表述上也进
行了许多修改。
另外,我们对章节的结构也进行了重新组织,全书共分3篇,10章:第一篇“KVM虚
拟化基础”(第1章~第5章),第二篇“KVM虚拟化进阶”(第6章~第9章),第三篇“性
能测试与调优”(第10章)。
除了上述的总体修改外,各章主要修改内容如下。
第1章,我们重新组织了结构,精简了一些文字介绍,加入了一些数据图表以便于读
者的理解。加入了云计算几种服务模型的描述和图示。加入了一节关于容器(Container)
的简介,以便读者对比学习。
第2章,对上一本书相关章节进行了更为系统的梳理,介绍了硬件虚拟化技术、KVM、QEMU、与KVM配合的组件以及相关工具链。
第5章,着重对其中的网络配置一节进行了更新。将上一本书中的第5章拆分成了第6
章、第7章、第8章和第9章,并分别进行了内容扩充。第6章,对应上一本书中的第5章的半虚拟化、设备直接分配、热插拔这3节,并分别
进行了补充。在半虚拟化驱动一节中,我们新增了“内核态的vhost-net后端以及网卡多队
列”“使用用户态的vhost-user作为后端驱动”“对Windows客户机的优化”这3小节。在设备直
接分配一节中,我们使用VFIO替换掉了已经被废弃的Legacy passthrough。在热插拔一
节,我们将内存热插拔独立出来,并着重更新,因为在上一本书出版时它还未被完全支
持。除此之外,我们还新增了磁盘热插拔和网络接口的热插拔两节。
第7章,我们将上一本书中的第4章中内存大页部分和上一本书中的第5章中的KSM、透明大页等内容凑在一起,组成了KVM内存管理高级技巧,同时新增了NUMA(非统一
内存访问架构)一节。
第8章,由上一本书中的第5章的“动态迁移”和“迁移到KVM虚拟化环境”两节组成。
第9章,在上一本书中的第5章的“嵌套虚拟化”“KVM安全”等内容的基础上,新增
了“CPU指令相关的性能优化”一节,着重介绍了最近几年Intel的一些性能优化新指令在虚
拟化环境中的应用。
第10章,对应上一本书中的第8章,专门讲KVM性能测试与优化。我们在最新的软硬
件环境中重做了CPU、内存、网络、磁盘的性能测试,获取了最新的数据,尤其对一些测
试工具(benchmark)进行了重新选取,比如磁盘性能测试,我们放弃了IOzone和
Bonnie++,而选用业界更认可的fio。另外,我们还加入了“CPU指令集对性能的提
升”和“其他的影响客户机性能的因素”两节进行分析,希望对读者进行虚拟化系能调优有
所启示。
上一本书中的第7章“Linux发行版中的KVM”和第9章“参与KVM开源社区”分别作为本
书的附录A和附录B,并进行了相应的内容更新。
其他章节的内容保持不变,即第3章为上一本书的第3章且内容不变;第4章为上一本
书的第6章,内容不变。
读者对象
本书适合对Linux下虚拟化或云计算基础技术感兴趣的读者阅读,包括Linux运维工程
师、KVM开发者、云平台开发者、虚拟化方案决策者、KVM的用户以及其他对KVM虚拟
机感兴趣的计算机爱好者。希望本书对这些读者了解KVM提供以下帮助。
·Linux运维工程师:了解KVM的使用方法、功能和基本的性能数据,能够搭建高性
能的KVM虚拟化系统,并应用于生产环境中。
·KVM开发者:了解KVM的基本原理和功能,也了解其基本用法和一些调试方法,以
及如何参与到KVM开源社区中去贡献代码。
·云平台开发者:了解底层KVM虚拟化的基本原理和用法,以促进云平台上层应用的
开发和调试的效率。
·虚拟化方案决策者:了解KVM的硬件环境需求和它的功能、性能概况,以便在虚拟化技术选型时做出最优化的决策。
·普通用户:了解KVM的功能和如何使用KVM,用掌握的KVM虚拟化技术来促进其
他相关的学习、开发和测试。
如何阅读本书
前面已经提到,本书相比上一本书内容更加集中,分类更加合理。如果读者朋友对
KVM没有什么了解,笔者建议按本书章节顺序阅读,通读一遍之后再对感兴趣的章节进
行仔细阅读。对于已有一定KVM知识基础的读者,可以根据自己的兴趣和已经掌握的知
识情况来有选择地阅读各个章节。当然,笔者建议今后可能会经常使用KVM的读者,在
阅读本书时,可以根据书中示例或者其他示例来进行实际操作。如果是开发者,也可以查
看相应的源代码。
勘误和支持
KVM、QEMU等开源社区非常活跃,QEMUKVM发展迅速,每天都有新的功能加进
去,或者原有功能被改进。特别是qemu命令行参数很可能会有改动,故本书中qemu命令
行参数只能完全适用于本书中提及的QEMU版本,读者若使用不同的版本,命令行参数可
能并不完全相同。例如,本书写作时,“-enable-kvm”已经被社区标为“将要废弃”,很可能
在读者拿到本书的时候,需要用“-accel kvm”来代替它。
由于KVM和QEMU的发展变化比较快,加之笔者的技术水平有限,编写时间仓促,书中难免会出现一些错误或者不准确的地方,恳请读者朋友批评指正。读者朋友对本书相
关内容有任何的疑问、批评和建议,都可以通过笔者之一(任永杰)的博客网站
http:smilejay.com进行讨论。也可以发邮件给我们(smile665@gmail.com、Robert.Ho@outlook.com),笔者会尽力回复并给读者以满意的答案。全书中涉及的示例
代码程序(不包含单行的命令)和重要的配置文件,都可以从网站
https:github.comsmilejaykvm-book查看和下载。
如果读者朋友们有更多的宝贵意见或者任何关于KVM虚拟化技术的讨论,也都欢迎
发送电子邮件至邮箱smile665@gmail.com、Robert.Ho@outlook.com,我们非常期待能够得
到朋友们的真挚反馈。
[1] 全球最大的云服务提供商Amazon,在2017年11月也宣布开始采用KVM作为它的虚拟
化技术,大有启用KVM而放弃Xen之势。
[2] 硬件虚拟化支持是每一代Intel CPU的最核心功能之一,也是每一代新平台新功能和性
能提升的领域。第一篇 KVM虚拟化基础
·第1章 虚拟化简介
·第2章 KVM原理简介
·第3章 构建KVM环境
·第4章 KVM管理工具
·第5章 KVM核心基础功能第1章 虚拟化简介
在写作上一本书的时候(2013年),云计算虽然已经在国际上提出多年,但在国内还
是刚刚兴起。到写作本书时这短短4年内,国内云计算已经翘首追赶,紧跟国际的步伐。
例如阿里云,截至笔者写作时,阿里云已经连续7个季度3位数的同比增长率。老牌公司微
软也在这几年加速追赶,在这个新的领域跻身一线。1.1 云计算概述
1.1.1 什么是云计算
一直以来,云计算(Cloud Computing)的定义也如同它的名字一样,云里雾里,说
不清楚。维基百科里是这样定义的:是一种基于互联网的计算方式,通过这种方式,共享
的软硬件资源和信息可以按需求提供给计算机各种终端和其他设备[1]。以前,我们的信息
处理(计算)是由一个实实在在的计算机来完成的,它看得见,摸得着。后来,随着计算
硬件、网络技术、存储技术的飞速发展,人们发现,每个人独自拥有一台计算机似乎有些
浪费,因为它大多数时候是空闲的。那么,如果将计算资源集中起来,大家共享,类似现
代操作系统那样分时复用,将是对资源的极大节省和效率的极大提升,经济学上的解释也
就是边际效应(成本)递减。科技行业的发展,根源也是经济利益的推动。在这样的背景
下,云计算应运而生了。它就是把庞大的计算资源集中在某个地方或是某些地方,而不再
是放在身边的那台计算机了;用户的每一次计算,都发生在那个被称为云的他看不见摸不
着的某个地方。
以CPU为例,图1-1和图1-2摘选了从2000年到2017年上市的Intel桌面CPU的参数(主
频、核数、LLC[2]
、制造工艺),从中可以大概看到CPU处理能力的飞速提升。它的另一
面也就意味着,个人单独拥有一台计算机,从资源利用效率角度来看,被大大闲置了的。
图1-1 Intel CPU处理能力的主要参数图1-2 Intel CPU LLC的发展及制造工艺的演进
[1] https:zh.wikipedia.orgwiki%E9%9B%B2%E7%AB%AF%E9%81%8B%E7%AE%97。
[2] Last Level Cache指介于CPU core和RAM之间的最后一层缓存。Pentium时代通常最多到
L2 Cache。现在的Core i3i5i7都有L3 Cache,并且越来越大。1.1.2 云计算的历史
正式的云计算的产品始发于2006年,那年8月,亚马逊(Amazon)发布了“弹性计算
云”(Elastic Compute Cloud)。2008年10月,微软宣布了名为Azure的云计算产品,并在
2010年2月正式发布Windows Azure[1]。Google也从2008年开始进入云计算时代,那年4
月,其发布了Google App Engine Beta,但直到2013年12月,其Google Compute Engine对
标AWS EC2才正式可用。
2010年7月,NASA和Rackspace共同发布了著名的开源项目Openstack。
从国内来看,2009年,阿里巴巴率先成立了阿里云部门,一开始只对内服务于其自身
的电商业务,如淘宝、天猫。2011年7月,阿里云开始正式对外销售云服务。
无论是国内还是国外,云计算的市场都快速发展。“Amazon把云计算做成一个大生意
没有花太长的时间:不到两年时间,Amazon上的注册开发人员达44万人,还有为数众多
的企业级用户。有第三方统计机构提供的数据显示,Amazon与云计算相关的业务收入已
达1亿美元。云计算是Amazon增长最快的业务之一。”[2]
国内的阿里云也在2013年以后快
速蓬勃发展。无论是国际巨头AWS(亚马逊)还是国内的阿里云,这些年都是快速增
长,尤其阿里云,虽然体量暂时还远不及AWS,但一直都是超过100%的增长,让人侧
目,如图1-3所示。
图1-3 云计算营收对比:2013—2017年度亚马逊AWS和阿里云[3]
[1] 2014年3月,Windows Azure更名为Microsoft Azure。
[2] 刘鹏:云计算发展现状。http:www.chinacloud.cnshow.aspx?id=754cid=11。[3] 数据整理自网络。阿里财年始于前一年4月,这里以大约自然年表示,比如2015年数据
来自于阿里2016财报。另外阿里云2013、2014年度数据包括其internet infrastructure收入,2015年开始才将阿里云单独出来。换算时,美元兑人民币汇率假设为6.8。微软的Azure营
收没有单独披露。Google cloud营收也未能单独获得。1.1.3 云计算的几种服务模型
“云计算是推动IT转向以业务为中心模式的一次重大变革。它着眼于运营效率、竞争
力和快速响应等实际成果。这意味着IT的作用正在从提供IT服务逐步过渡到根据业务需求
优化服务的交付和使用。这种全新的模式将以前的信息孤岛转化为灵活高效的资源池和具
备自我管理能力的虚拟基础架构,从而以更低的成本和以服务的形式提供给用户。IT即服
务将提供业务所需要的一切,并在不丧失对系统的控制力的同时,保持系统的灵活性和敏
捷性。”[1]
云计算的模型是以服务为导向的,根据提供的服务层次不同,可分为:
IaaS(Infrastructure as a Service,基础架构即服务)、PaaS(Platform as a Service,平台即
服务)、SaaS(Software as a Service,软件即服务)。它们提供的服务越来越抽象,用户
实际控制的范围也越来越小,如图1-4所示。
图1-4 云计算服务层次模型[2]
1.SaaS,软件即服务
云服务提供商提供给客户直接使用软件服务,如Google Docs、Microsoft CRM、Salesforce.com等。用户不必自己维护软件本身,只管使用软件提供的服务。用户为该软
件提供的服务付费。
2.PaaS,平台即服务
云服务提供商提供给客户开发、运维应用程序的运行环境,用户负责维护自己的应用
程序,但并不掌控操作系统、硬件以及运作的网络基础架构。如Google App Engine等。平台是指应用程序运行环境(图1-4中的Runtime)。通常,这类用户在云环境中运维的应用
程序会再提供软件服务给他的下级客户。用户为自己的程序的运行环境付费。
3.IaaS,基础设施即服务
用户有更大的自主权,能控制自己的操作系统、网络连接(虚拟的)、硬件(虚拟
的)环境等,云服务提供商提供的是一个虚拟的主机环境。如Google Compute Engine、AWS EC2等。用户为一个主机环境付费。
从图1-4中可以看到,无论是哪种云计算服务模型,虚拟化(Virtualization)都是其基
础。那么什么是虚拟化呢?
[1] 虚拟化和云计算技术回顾与展望。
http:www.ctosay.cncontent40797008418208146787.html。
[2] 图片来源http:inspira.co.inblogbenefits-iaas-vs-paas-vs-saas。1.2 虚拟化技术
1.2.1 什么是虚拟化
维基百科关于虚拟化的定义是:“In computing,virtualization refers to the act of
creating a virtual(rather than actual)version of something,including virtual computer hardware
platforms,storage devices,and computer network resources。”(在计算机领域,虚拟化指
创建某事物的虚拟(而非实际)版本,包括虚拟的计算机硬件平台、存储设备,以及计算
机网络资源)可见,虚拟化是一种资源管理技术,它将计算机的各种实体资源(CPU、内
存、存储、网络等)予以抽象和转化出来,并提供分割、重新组合,以达到最大化利用物
理资源的目的。
广义来说,我们一直以来对物理硬盘所做的逻辑分区,以及后来的LVM(Logical
Volume Manager),都可以纳入虚拟化的范畴。
结合图1-4来看,在没有虚拟化以前(我们抽掉Virtualization层),一个物理的主机
(Sever、Storage、Network层)上面只能支持一个操作系统及其之上的一系列运行环境和
应用程序;有了虚拟化技术,一个物理主机可以被抽象、分割成多个虚拟的逻辑意义上的
主机,向上支撑多个操作系统及其之上的运行环境和应用程序,则其资源可以被最大化地
利用。
图1-5 物理资源虚拟化示意
如图1-5所示的Virtual Machine Monitor(VMM,虚拟机监控器,也称为Hypervisor)
层,就是为了达到虚拟化而引入的一个软件层。它向下掌控实际的物理资源(相当于原本
的操作系统);向上呈现给虚拟机N份逻辑的资源。为了做到这一点,就需要将虚拟机对
物理资源的访问“偷梁换柱”——截取并重定向,让虚拟机误以为自己是在独享物理资源。虚拟机监控器运行的实际物理环境,称为宿主机;其上虚拟出来的逻辑主机,称为客户
机。
虚拟化技术有很多种实现方式,比如软件虚拟化和硬件虚拟化,再比如准虚拟化和全
虚拟化。下面将针对每种实现方式做一个简单的介绍。1.2.2 软件虚拟化和硬件虚拟化
1.软件虚拟化技术
软件虚拟化,顾名思义,就是通过软件模拟来实现VMM层,通过纯软件的环境来模
拟执行客户机里的指令。
最纯粹的软件虚拟化实现当属QEMU。在没有启用硬件虚拟化辅助的时候,它通过软
件的二进制翻译[1]
仿真出目标平台呈现给客户机,客户机的每一条目标平台指令都会被
QEMU截取,并翻译成宿主机平台的指令,然后交给实际的物理平台执行。由于每一条都
需要这么操作一下,其虚拟化性能是比较差的,同时其软件复杂度也大大增加。但好处是
可以呈现各种平台给客户机,只要其二进制翻译支持。
2.硬件虚拟化技术
硬件虚拟化技术就是指计算机硬件本身提供能力让客户机指令独立执行,而不需要
(严格来说是不完全需要)VMM截获重定向。
以x86架构为例,它提供一个略微受限制的硬件运行环境供客户机运行(non-root
mode[2]),在绝大多数情况下,客户机在此受限环境中运行与原生系统在非虚拟化环境
中运行没有什么两样,不需要像软件虚拟化那样每条指令都先翻译再执行,而VMM运行
在root mode,拥有完整的硬件访问控制权限。仅仅在少数必要的时候,某些客户机指令
的运行才需要被VMM截获并做相应处理,之后客户机返回并继续在non-root mode中运
行。可以想见,硬件虚拟化技术的性能接近于原生系统[3]
,并且,极大地简化了VMM的
软件设计架构。
Intel从2005年就开始在其x86 CPU中加入硬件虚拟化的支持——Intel Virtualization
Technology,简称Intel VT。到目前为止,在所有的Intel CPU中,都可以看到Intel VT的身
影。并且,每一代新的CPU中,都会有新的关于硬件虚拟化支持、改进的feature加入。也
因如此,Intel x86平台是对虚拟化支持最为成熟的平台,本书将以Intel x86平台为例介绍
KVM的虚拟化。
[1] 二进制翻译(binary translation)是指将使用某套指令集的二进制代码转换成基于另一
套指令集的。它既可以通过硬件来完成,也可以通过软件来完成。
[2] root与non-root mode是Intel为了硬件虚拟化而引入的与原来的Ring0~Ring3正交的权限
控制机制。详见Intel Sefnare Development Manual第15章。
[3] 本书中,原生系统(Native)是指不使用虚拟化技术的主机系统,即原本的一个物理
主机安装一个操作系统的方式。1.2.3 半虚拟化和全虚拟化
1.半虚拟化[1]
通过上一节的描述,大家可以理解,最理想的虚拟化的两个目标如下:
1)客户机完全不知道自己运行在虚拟化环境中,还以为自己运行在原生环境里。
2)完全不需要VMM介入客户机的运行过程。
纯软件的虚拟化可以做到第一个目标,但性能不是很好,而且软件设计的复杂度大大
增加。
那么如果放弃第一个目标呢?让客户机意识到自己是运行在虚拟化环境里,并做相应
修改以配合VMM,这就是半虚拟化(Para-Virtualization)。一方面,可以提升性能和简
化VMM软件复杂度;另一方面,也不需要太依赖硬件虚拟化的支持,从而使得其软件设
计(至少是VMM这一侧)可以跨平台且是优雅的。“本质上,准虚拟化弱化了对虚拟机特
殊指令的被动截获要求,将其转化成客户机操作系统的主动通知。但是,准虚拟化需要修
改客户机操作系统的源代码来实现主动通知。”典型的半虚拟化技术就是virtio,使用virtio
需要在宿主机VMM和客户机里都相应地装上驱动。
2.全虚拟化
与半虚拟化相反的,全虚拟化(Full Virtualization)坚持第一个理想化目标:客户机
的操作系统完全不需要改动。敏感指令在操作系统和硬件之间被VMM捕捉处理,客户操
作系统无须修改,所有软件都能在虚拟机中运行。因此,全虚拟化需要模拟出完整的、和
物理平台一模一样的平台给客户机,这在达到了第一个目标的同时也增加了虚拟化层
(VMM)的复杂度。
性能上,2005年硬件虚拟化兴起之前,软件实现的全虚拟化完败于VMM和客户机操
作系统协同运作的半虚拟化,这种情况一直延续到2006年。之后以Intel VT-x、VT-d[2]
为
代表的硬件虚拟化技术的兴起,让由硬件虚拟化辅助的全虚拟化全面超过了半虚拟化。但
是,以virtio为代表的半虚拟化技术也一直在演进发展,性能上只是略逊于全虚拟化,加
之其较少的平台依赖性,依然受到广泛的欢迎。
[1] 在《KVM虚拟化技术:实战与原理解析》中称为“准虚拟化”
[2] https:www.intel.comcontentwwwusenvirtualizationvirtualization-technologyintel-
virtualizationtechnology.html。1.2.4 Type1和Type2虚拟化
从软件框架的角度上,根据虚拟化层是直接位于硬件之上还是在一个宿主操作系统之
上,将虚拟化划分为Typel和Type2,如图1-6所示。
Type1(类型1)Hypervisor也叫native或bare-metal Hypervisor。这类虚拟化层直接运
行在硬件之上,没有所谓的宿主机操作系统。它们直接控制硬件资源以及客户机。典型地
如Xen(见1.4.1节)和VMware ESX。
Type2(类型2)Hypervisor运行在一个宿主机操作系统之上,如VMware
Workstation;或系统里,如KVM。这类Hypervisor通常就是宿主机操作系统的一个应用程
序,像其他应用程序一样受宿主机操作系统的管理。比如VMware Workstation就是运行在
Windows或者Linux操作系统上的一个程序而已[1]。客户机是在宿主机操作系统上的一个
抽象,通常抽象为进程。
[1] 将KVM归为Type1或Type2是有争议的,一方面,它是以kernel module的形式加载于
kernel,与kernel融为一体,可以认为它将Linux kernel转变为一个Type1的Hypervisor。另
一方面,在逻辑上,它受制于kernel,所有对硬件资源的管理都是通过kernel去做的,所以
归为Type2。1.3 KVM简介
1.3.1 KVM的历史
KVM全称是Kernel-based Virtual Machine,即基于内核的虚拟机,是采用硬件虚拟化
技术的全虚拟化解决方案[1]。
图1-6 类型1和类型2的Hypervisor
KVM最初是由Qumranet
[2]
公司的Avi Kivity开发的,作为他们的VDI产品的后台虚拟
化解决方案。为了简化开发,Avi Kivity并没有选择从底层开始新写一个Hypervisor,而是
选择了基于Linux kernel,通过加载模块使Linux kernel本身变成一个Hypervisor。2006年10
月,在先后完成了基本功能、动态迁移以及主要的性能优化之后,Qumranet正式对外宣布
了KVM的诞生。同月,KVM模块的源代码被正式纳入Linux kernel,成为内核源代码的一
部分。作为一个功能和成熟度都逊于Xen的项目[3]
,在这么快的时间内被内核社区接纳,主要原因在于:
1)在虚拟化方兴未艾的当时,内核社区急于将虚拟化的支持包含在内,但是Xen取
代内核由自身管理系统资源的架构引起了内核开发人员的不满和抵触。
2)Xen诞生于硬件虚拟化技术出现之前,所以它在设计上采用了半虚拟化的方式,这让Xen采用硬件虚拟化技术有了更多的历史包袱,不如KVM新兵上阵一身轻。
2008年9月4日,Redhat公司以1.07亿美元收购了Qumranet公司,包括它的KVM开源项
目和开发人员。自此,Redhat开始在其RHEL发行版中集成KVM,逐步取代Xen,并从
RHEL7开始,正式不支持Xen。[1] 对于某些设备,如硬盘、网卡,KVM也支持virtio的半虚拟化方式。
[2] 这是一家以色列的创业公司,提供桌面虚拟化产品(VDI),KVM就是其后台虚拟化
的VMM。
[3] Xen先于KVM出现,并且在KVM出现时已经是一个成熟的开源VMM。1.3.2 KVM的功能概览
KVM从诞生开始就定位于基于硬件虚拟化支持的全虚拟化实现。它以内核模块的形
式加载之后,就将Linux内核变成了一个Hypervisor,但硬件管理等还是通过Linux kernel
来完成的,所以它是一个典型的Type 2 Hypervisor,如图1-7所示。
图1-7 KVM功能框架[1]一个KVM客户机对应于一个Linux进程,每个vCPU则是这个进程下的一个线程,还
有单独的处理IO的线程,也在一个线程组内。所以,宿主机上各个客户机是由宿主机内
核像调度普通进程一样调度的,即可以通过Linux的各种进程调度的手段来实现不同客户
机的权限限定、优先级等功能。
客户机所看到的硬件设备是QEMU模拟出来的(不包括VT-d透传的设备,详见6.2
节),当客户机对模拟设备进行操作时,由QEMU截获并转换为对实际的物理设备(可能
设置都不实际物理地存在)的驱动操作来完成。
下面介绍一些KVM的功能特性。
1.内存管理
KVM依赖Linux内核进行内存管理。上面提到,一个KVM客户机就是一个普通的
Linux进程,所以,客户机的“物理内存”就是宿主机内核管理的普通进程的虚拟内存。进
而,Linux内存管理的机制,如大页、KSM(Kernel Same Page Merge,内核的同页合
并)、NUMA(Non-Uniform Memory Arch,非一致性内存架构)[2]
、通过mmap的进程间
共享内存,统统可以应用到客户机内存管理上。
早期时候,客户机自身内存访问落实到真实的宿主机的物理内存的机制叫影子页表
(Shadow Page Table)。KVM Hypervisor为每个客户机准备一份影子页表,与客户机自
身页表建立一一对应的关系。客户机自身页表描述的是GVA→GPA[3]
的映射关系;影子
页表描述的是GPA→HPA的映射关系。当客户机操作自身页表的时候,KVM就相应地更
新影子页表。比如,当客户机第一次访问某个物理页的时候,由于Linux给进程的内存通
常都是拖延到最后要访问的一刻才实际分配的,所以,此时影子页表中这个页表项是空
的,KVM Hypervisor会像处理通常的缺页异常那样,把这个物理页补上,再返回客户机
执行的上下文中,由客户机继续完成它的缺页异常。
影子页表的机制是比较拗口,执行的代价也是比较大的。所以,后来,这种靠软件的
GVA→GPA→HVA→HPA的转换被硬件逻辑取代了,大大提高了执行效率。这就是Intel
的EPT或者AMD的NPT技术,两家的方法类似,都是通过一组可以被硬件识别的数据结
构,不用KVM建立并维护额外的影子页表,由硬件自动算出GPA→HPA。现在的KVM默
认都打开了EPTNPT功能。
2.存储和客户机镜像的格式
严格来说,这是QEMU的功能特性。
KVM能够使用Linux支持的任何存储来存储虚拟机镜像,包括具有IDE、SCSI和
SATA的本地磁盘,网络附加存储(NAS)(包括NFS和SAMBACIFS),或者支持iSCSI
和光线通道的SAN。多路径IO可用于改进存储吞吐量和提供冗余。
由于KVM是Linux内核的一部分,它可以利用所有领先存储供应商都支持的一种成熟
且可靠的存储基础架构,它的存储堆栈在生产部署方面具有良好的记录。
KVM还支持全局文件系统(GFS2)等共享文件系统上的虚拟机镜像,以允许客户机
镜像在多个宿主机之间共享或使用逻辑卷共享。磁盘镜像支持稀疏文件形式,支持通过仅
在虚拟机需要时分配存储空间,而不是提前分配整个存储空间,这就提高了存储利用率。KVM的原生磁盘格式为QCOW2,它支持快照,允许多级快照、压缩和加密。
3.实时迁移
KVM支持实时迁移,这提供了在宿主机之间转移正在运行的客户机而不中断服务的
能力。实时迁移对用户是透明的,客户机保持打开,网络连接保持活动,用户应用程序也
持续运行,但客户机转移到了一个新的宿主机上。
除了实时迁移,KVM支持将客户机的当前状态(快照,snapshot)保存到磁盘,以允
许存储并在以后恢复它。
4.设备驱动程序
KVM支持混合虚拟化,其中半虚拟化的驱动程序安装在客户机操作系统中,允许虚
拟机使用优化的IO接口而不使用模拟的设备,从而为网络和块设备提供高性能的IO。
KVM使用的半虚拟化的驱动程序是IBM和Redhat联合Linux社区开发的VirtIO标准;
它是一个与Hypervisor独立的、构建设备驱动程序的接口,允许多种Hypervisor使用一组相
同的设备驱动程序,能够实现更好的对客户机的互操作性。
同时,KVM也支持Intel的VT-d技术,通过将宿主机的PCI总线上的设备透传(pass-
through)给客户机,让客户机可以直接使用原生的驱动程序高效地使用这些设备。这种
使用是几乎不需要Hypervisor的介入的。
5.性能和可伸缩性
KVM也继承了Linux的性能和可伸缩性。KVM在CPU、内存、网络、磁盘等虚拟化性
能上表现出色,大多都在原生系统的95%以上[4]。KVM的伸缩性也非常好,支持拥有多
达288个vCPU和4TB RAM的客户机,对于宿主机上可以同时运行的客户机数量,软件上
无上限[5]。
这意味着,任何要求非常苛刻的应用程序工作负载都可以运行在KVM虚拟机上。
[1] 图片来源:https:en.wikipedia.orgwikiFile:Kernel-based_Virtual_Machine.svg。
[2] 见本书第7章。
[3] GVA:Guest Virtual Address,客户机虚拟地址。GPA:Guest Physical Address,客户
机物理地址。HVA:Host Virtual Address,宿主机虚拟地址。HPA:Host Physical
Address,宿主机物理地址。
[4] 本书第10章有详细测试。
[5] https:access.redhat.comarticles906543。1.3.3 KVM的现状
至本书写作时,KVM已经10周岁了。10年之间,得益于与Linux天然一体以及Redhat
的倾力打造,KVM已经成为Openstack用户选择的最主流的Hypervisor(因为KVM是
Openstack的默认Hypervisor)。来自Openstack的调查显示,KVM占到87%以上的部署份
额[1]
,并且(笔者认为)还会继续增大。可以说,KVM已经主宰了公有云部署的
Hypervisor市场;而在私有云部署方面,尤其大公司内部私有云部署,还是VMware的地
盘,目前受到HyperV的竞争。
功能上,虚拟化发展到今天,各个Hypervisor的主要功能都趋同。KVM作为后起之
秀,并且在公有云上广泛部署,其功能的完备性是毋庸置疑的。并且由于其开源性,反而
较少一些出于商业目的的限制,比如一篇文章
(ftppublic.dhe.ibm.comlinuxpdfsClabby_Analytics_-_VMware_v_KVM.pdf)中比较
VMware EXS与KVM,就是一个例子[2]。
性能上,作为同样开源的Hypervisor,KVM和Xen都很优秀,都能达到原生系统95%
以上的效率(CPU、内存、网络、磁盘等benchmark衡量),KVM甚至还略微好过Xen一
点点[3]。与微软的Hyper-V相比,KVM似乎略逊于最新的Windows 2016上的HyperV,而
好于Windows 2012 R2上的HyperV[4]
,但这是微软的一家之言,笔者没有重新测试验证。
其他与诸如VMware EXS等的性能比较,网上也可以找到很多,读者可以自行搜索。总的
来说,即使各有优劣,虚拟化技术发展到今天已经成熟,KVM也是如此。
[1] http:superuser.openstack.orgarticlesopenstack-user-survey-insights-november-2014。
[2] 事实上,作为商业软件,RHEL、RHEV对KVM的功能也有一些限制,比如客户机数
目,RHEL7限制最多只能启动4个客户机而RHEV则没有。而原生的开源KVM是没有这些
限制的。
[3] https:major.io20140622performance-benchmarks-kvm-vs-xen。
[4] https:blogs.msdn.microsoft.comvirtual_pc_guy20170203hyper-v-vs-kvm-for-openstack-
performance。1.3.4 KVM的展望
经过10年的发展,KVM已经成熟。那么,接下来KVM会怎样进一步发展呢?
1)大规模部署尚有挑战。KVM是Openstack和oVirt
[1]
选择的默认Hypervisor,因而实
际的广泛部署常常是大规模的(large scale,scalability)。这种大规模,一方面指高并
发、高密度,即一台宿主机上支持尽可能多的客户机;另一方面,也指大规模的单个客户
机,即单个客户机配备尽可能多的vCPU和内存等资源,典型的,这类需求来自高性能计
算(HPC)领域。随着硬件尤其是CPU硬件技术的不停发展(物理的processor越来越
多),这种虚拟化的大规模方面的需求也在不停地增大[2]
,并且这不是简单数量的增加,这种增加会伴随着新的挑战等着KVM开发者去解决,比如热迁移的宕机时间
(downtime)就是其中一例。
2)实时性(Realtime)。近几年一个新的趋势就是NFV(Network Functions
Virtualization,网络功能的虚拟化),它指将原先物理的网络设备搬到一个个虚拟的客户
机上,以便更好地实现软件定义网络的愿景。网络设备对实时性的要求是非常高的;而不
巧,NFV的开源平台OPNFV[3]
选择了Openstack,尽管Openstack向下支持各种
Hypervisor,但如前文所说,KVM是其默认以及主要部署的选择,所以NFV实时性的要求
责无旁贷地落到了KVM头上,NFV-KVM[4]
项目应运而生,它作为OPNFV的子项目主要
解决KVM在实时性方面受到的挑战。
3)安全是永恒的主题话题。就像网络病毒永远不停地演变推陈出新一样,新时代的
IT架构的主体,云虚拟化,也会一直受到各类恶意攻击的骚扰,从而陷入道高一尺魔高
一丈的循环。Hypervisor的开发者、应用者会一直从如何更好地隔离客户机、更少的
Hypervisor干预等方面入手,增加虚拟化的安全性。KVM作为Type 2的Hypervisor,天然
地与Host OS有关联,安全性方面的话题更引人注目。同时,硬件厂商如Intel,也会从硬
件层面不停地推出新的安全方面的功能(feature),KVM从软件方面也要跟上脚步,使
能(enable)之。
4)性能调优。如同一句广告词说的:“进无止境”。一方面,新的功能代码的不停引
入总会给性能调优开辟新的空间;另一方面,老的功能的实现也许还有更好的方法。还
有,新的硬件功能的出现,也是性能调优永恒的动力源泉。
[1] https:www.ovirt.org。
[2] 比如,就在本书完稿前不久,KVM对客户机CPU数量的支持就从240个增加到了288
个,以顺应Intel新的Xeon-Phi产品线的功能和性能。
[3] https:www.opnfv.org。
[4] https:wiki.opnfv.orgdisplaykvmNfv-kvm。1.4 其他的虚拟化解决方案简介
1.4.1 Xen
Xen的出现要早于KVM,可以追溯到20世纪90年代。剑桥大学的Ian Pratt和Keir Fraser
在一个叫作Xenoserver的研究项目中开发了Xen虚拟机。在那个年代,硬件虚拟化还没有
出现,所以Xen最开始采用的是半虚拟化的解决方案。
Xen在2002年开源,并在2003年发布了1.0版本、2004年发布了2.0版本,随即被
Redhat、Novell和Sun的Linux发行版集成,作为其虚拟化组件。2005年的3.0版本开始加入
Intel和AMD的硬件虚拟化的支持,以及Intel的IA64架构,从此,Xen也提供全虚拟化解决
方案(HVM),可以运行完全没有修改的客户机操作系统。2007年10月,思杰公司出资5
亿美元收购了XenSource,变成了Xen项目的东家。2013年,Xen成为Linux基金会赞助的
合作项目。
Xen在架构上是一个典型的Type 1 Hypervisor,与KVM形成鲜明对比,如图1-8所示。
严格来说,它没有宿主机的概念,而是由Xen Hypervisor(VMM)完全管控硬件,但用户
却看不见、摸不着它,只能通过特殊的0号虚拟机(Dom0),通过其中xl工具栈(tool
stack)与Xen Hypervisor交互来管理其他普通虚拟机(DomU)。0号虚拟机是一个运行修
改过的半虚拟化的内核的Linux虚拟机。从架构上,Xen的虚拟化方案既利用了Linux内核
的IO部分(Dom0的内核),将Linux内核的CPU、内存管理等核心部分排除在外由自己接
手(Xen Hypervisor),所以,一开始就受到了Linux内核开发人员的抵制,致使Linux内
核作为Dom0对Xen的支持部分一直不能合入Linux内核社区。一直到2010年,在采用基于
内核的PVOPs方式大量重写了Xen代码以后,才勉强合入Linux内核社区。2011年,从
Linux内核2.6.37版本开始,正式支持Xen Dom0。1.4.2 VMware
VMware成立于1998年,是最早专注于虚拟化商业软件(并成功)的公司,从它的名
字也可以看出它对自己的定位和目标。从十几年前虚拟化软件兴起开始,它就是这个市场
的霸主。笔者早年的认知也是虚拟化=VMware。直到最近,在公有云兴起的背景之下,VMware开始受到KVM和Xen等开源项目以及微软AzureHyperV的挑战。VMware最初是
由一对夫妇等几人创立的,2004年被EMC收购。2016年,EMC又被Dell收购,所以现在
VMware是Dell旗下的子公司。
图1-8 Xen的架构
VMware从诞生起就一直专注于虚拟化,其产品线非常全,既有PaaS产品,也有IaaS
产品;既有Hypervisor,也有应用管理、存储管理等配套软件;既有面向个人用户的桌面
级虚拟化产品,也有面向企业的服务器级产品;既有运行于Linux平台上的产品,也有
Windows和Mac平台上的产品。本书只选择最著名的两款产品给大家简单介绍下,更多更
详细的信息大家可以到它的官网查看。
1.VMware Workstation
VMware Workstation是VMware最早的产品,也是最广为人知的产品,1999年发布。
在刚开始的时候,还没有硬件虚拟化技术,所以它是采用二进制翻译的方式实现虚拟化
的。但是由于它的二进制翻译技术独步当时,性能还很出色,尤其跟当时同类产品相比。
可以说,是VMware Workstation奠定了VMware在虚拟化软件行业的地位。VMwareWorkstation是桌面级虚拟化产品,运行在Windows、Linux和Mac操作系统上,是Type 2
Hypervisor。使用它需要购买License,但VMware同时提供了与Workstation功能类似,只
是有所删减的Workstation Player,供大家非商业化地免费使用。
2.VMware ESXi
VMware ESXi是服务器级的虚拟化软件。与Workstation不同,它直接运行在硬件平台
上,是Type1 Hypervisor。在架构上与Xen有些相像,是现在VMware的拳头产品,大多数
大公司的私有云都是用它搭建的。除了vMotion(即Live Migration功能)、HA(High
Availability,指软硬件运行的不间断地冗余备份)等业界常见功能外,ESXi还支持Cisco
Nexus 1000v[1]
,作为分布式虚拟交换机运行在ESXi集群中。
[1] Nexus 1000v是Cisco和VMWare合作的产物。
https:www.vmware.comcompanynewsreleases2008cisco_vmworld08.html。1.4.3 HyperV
与VMware一样,HyperV也是闭源(Close Source,与Opensource相对)的商业软件。
微软从Windows 8Windows Server 2008开始,用它取代原来的Virtual PC,成为Server OS
版本自带的平台虚拟化软件。
HyperV在架构上与Xen类似,也是Type 1 Hypervisor。它有Partition的概念,有一个
Parent Partition,类似于Xen Dom0,有管理硬件资源的权限;HyperV的Child Partion就类
似于普通的客户机DomU。对Hypervisor的请求以及对客户机的管理都要通过Parent
Partition,硬件的驱动也由Parent Partition来完成。客户机看到的都是虚拟出来的硬件资
源,它们对其虚拟硬件资源的访问都会被重定向到Parent Partition,由它来完成实际的操
作,这种重定向是通过VMBus连接Parent Partition的VSP(Virtualization Service Provider)
和child partition的VSC(Virtualization Service Consumer)来完成的,而这个过程对客户机
OS都是透明的。图1-9中,HyperV Hypervisor运行在Ring-1,也就是Intel VMX技术的root
mode(特权模式),而parent partition和child partition的内核都运行在non-root mode的Ring
0和Ring 3,也就是非特权模式的内核态和用户态。这样的架构安全性是比较好的。性能
上如1.3.3节提到的那样,据微软自己说是略好于KVM的。
图1-9 HyperV架构[1]
[1] 图片来源:https:en.wikipedia.orgwikiFile:Hyper-V.png。1.4.4 Container
Container严格来说与前面提到的虚拟化软件不是一个大类,首先,它不是某个虚拟化
软件,而是某类软件的统称,包括Docker和LXC等;其次,它不是硬件平台级的虚拟化技
术,而是软件运行环境的虚拟化,是一种操作系统级的虚拟化技术,与前面提到的不是一
个层次的。
Container技术利用了Linux kernel提供的cgroup、namespace等机制,将应用之间隔离
起来,好像自己是操作系统上的唯一一个应用似的。而Linux kernel除了封装出这些应用
单独的运行环境以外,还可以控制分配给各个应用的资源配额,比如CPU利用率、内存、网络带宽等。
与平台虚拟化技术相比,Container技术省去了启动和维护整个虚拟客户机的开销(硬
件初始化、Kernel boot、init等),因而它非常轻量级,非常适用于PaaS服务模型。但另
一方面,由于各个Contained instance其实还是共用一个OS、一个Kernel,所以安全性比不
上平台虚拟化技术。总而言之,Container和KVM等平台虚拟化技术,目前还是各有所
长,还处在相互取长补短的过程中。1.5 本章小结
本章从云计算的基本概念入手,给读者讲解了SaaS、PaaS、IaaS这3种云服务类型,还讲到了作为云计算底层的虚拟化技术。对于虚拟化技术,着重对KVM的基础架构进行
了介绍,同时对Xen、VMware、HyperV等虚拟化技术以及容器技术也进行了简介。本章
目的在于让读者在开始学习KVM虚拟化技术之前,对虚拟化技术有一个整体的简明扼要
的认识。第2章 KVM原理简介
2.1 硬件虚拟化技术
通过第1章的介绍,大家已经知道KVM虚拟化必须依赖于硬件辅助的虚拟化技术,本
节就来介绍一下硬件虚拟化技术。
最早的硬件虚拟化技术出现在1972年的大型机IBM System370系统上,而真正让硬件
虚拟化技术“走入寻常百姓家”的是2005年年末Intel发布的VT-x硬件虚拟化技术,以及
AMD于2006年发布的AMD-V。本书中除了特别说明,默认以Intel的硬件虚拟化技术作为
代表来介绍。2.1.1 CPU虚拟化
CPU是计算机系统最核心的模块,我们的程序执行到最后都是翻译为机器语言在CPU
上执行的。在没有CPU硬件虚拟化技术之前,通常使用指令的二进制翻译(binary
translation)来实现虚拟客户机中CPU指令的执行,很早期的VMware就使用这样的方案,其指令执行的翻译比较复杂,效率比较低。所以Intel最早发布的虚拟化技术就是CPU虚拟
化方面的,这才为本书的主角——KVM的出现创造了必要的硬件条件。
Intel在处理器级别提供了对虚拟化技术的支持,被称为VMX(virtual-machine
extensions)。有两种VMX操作模式:VMX根操作(root operation)与VMX非根操作
(non-root operation)。作为虚拟机监控器中的KVM就是运行在根操作模式下,而虚拟机
客户机的整个软件栈(包括操作系统和应用程序)则运行在非根操作模式下。进入VMX
非根操作模式被称为“VM Entry”;从非根操作模式退出,被称为“VM Exit”。
VMX的根操作模式与非VMX模式下最初的处理器执行模式基本一样,只是它现在支
持了新的VMX相关的指令集以及一些对相关控制寄存器的操作。VMX的非根操作模式是
一个相对受限的执行环境,为了适应虚拟化而专门做了一定的修改;在客户机中执行的一
些特殊的敏感指令或者一些异常会触发“VM Exit”退到虚拟机监控器中,从而运行在VMX
根模式。正是这样的限制,让虚拟机监控器保持了对处理器资源的控制。
一个虚拟机监控器软件的最基础的运行生命周期及其与客户机的交互如图2-1所示。
图2-1 VMM与Guest之间的交互
软件通过执行VMXON指令进入VMX操作模式下;在VMX模式下通过VMLAUNCH
和VMRESUME指令进入客户机执行模式,即VMX非根模式;当在非根模式下触发VM
Exit时,处理器执行控制权再次回到宿主机的虚拟机监控器上;最后虚拟机监控可以执行
VMXOFF指令退出VMX执行模式。
逻辑处理器在根模式和非根模式之间的切换通过一个叫作VMCS(virtual-machinecontrol data structure)的数据结构来控制;而VMCS的访问是通过VMCS指针来操作的。
VMCS指针是一个指向VMCS结构的64位的地址,使用VMPTRST和VMPTRLD指令对
VMCS指针进行读写,使用MREAD、VMWRITE和VMCLEAR等指令对VMCS实现配置。
对于一个逻辑处理器,它可以维护多个VMCS数据结构,但是在任何时刻只有一个
VMCS在当前真正生效。多个VMCS之间也是可以相互切换的,VMPTRLD指令就让某个
VMCS在当前生效,而其他VMCS就自然成为不是当前生效的。一个虚拟机监控器会为一
个虚拟客户机上的每一个逻辑处理器维护一个VMCS数据结构。
根据Intel的官方文档,我们这里列举部分在非根模式下会导致“VM Exit”的敏感指令
和一些异常供读者朋友参考,这对于理解KVM的执行机制是必要的,因为KVM也必须按
照CPU的硬件规范来实现虚拟化软件逻辑。
1)一定会导致VM Exit的指令:CPUID、GETSEC、INVD、XSETBV等,以及VMX
模式引入的INVEPT、INVVPID、VMCALL、VMCLEAR、VMLAUNCH、VMPTRLD、VMPTRST、VMRESUME、VMXOFF、VMXON等。
2)在一定的设置条件下会导致VM Exit的指令[1]
:CLTS、HLT、IN、OUT、INVLPG、INVPCID、LGDT、LMSW、MONITOR、MOV from CR3、MOV to CR3、MWAIT、MWAIT、RDMSR、RWMSR、VMREAD、VMWRITE、RDRAND、RDTSC、XSAVES、XRSTORS等。如在处理器的虚拟机执行控制寄存器中的“HLT exiting”比特位
被置为1时,HLT的执行就会导致VM Exit。
3)可能会导致VM Exit的事件:一些异常、三次故障(Triple fault)、外部中断、不
可屏蔽中断(NMI)、INIT信号、系统管理中断(SMI)等。如在虚拟机执行控制寄存器
中的“NMI exiting”比特位被置为1时,不可屏蔽中断就会导致VM Exit。
最后提一下,由于发生一次VM Exit的代价是比较高的(可能会消耗成百上千个CPU
执行周期,而平时很多指令是几个CPU执行周期就能完成),所以对于VM Exit的分析是
虚拟化中性能分析和调优的一个关键点。
[1] 并没有完全列举导致VM Exit的所有指令,感兴趣的读者可以进一步阅读Intel软件开发
者手册中“VMX NON-ROOT OPERATION”章节中的详细描述。2.1.2 内存虚拟化
内存虚拟化的目的是给虚拟客户机操作系统提供一个从0地址开始的连续物理内存空
间,同时在多个客户机之间实现隔离和调度。在虚拟化环境中,内存地址的访问会主要涉
及以下4个基础概念,图2-2形象地展示了虚拟化环境中内存地址。
图2-2 虚拟化环境下的内存地址
1)客户机虚拟地址,GVA(Guest Virtual Address)
2)客户机物理地址,GPA(Guest Physical Address)
3)宿主机虚拟地址,HVA(Host Virtual Address)
4)宿主机物理地址,HPA(Host Physical Address)
内存虚拟化就是要将客户机虚拟地址(GVA)转化为最终能够访问的宿主机上的物
理地址(HPA)。对于客户机操作系统而言,它不感知内存虚拟化的存在,在程序访问客户机中虚拟地址时,通过CR3寄存器可以将其转化为物理地址,但是在虚拟化环境中这个
物理地址只是客户机的物理地址,还不是真实内存硬件上的物理地址。所以,虚拟机监控
器就需要维护从客户机虚拟地址到宿主机物理地址之间的一个映射关系,在没有硬件提供
的内存虚拟化之前,这个维护映射关系的页表叫作影子页表(Shadow Page Table)。内存
的访问和更新通常是非常频繁的,要维护影子页表中对应关系会非常复杂,开销也较大。
同时需要为每一个客户机都维护一份影子页表,当客户机数量较多时,其影子页表占用的
内存较大也会是一个问题。
Intel CPU在硬件设计上就引入了EPT(Extended Page Tables,扩展页表),从而将客
户机虚拟地址到宿主机物理地址的转换通过硬件来实现。当然,这个转换是通过两个步骤
来实现的,如图2-3所示。首先,通过客户机CR3寄存器将客户机虚拟地址转化为客户机
物理地址,然后通过查询EPT来实现客户机物理地址到宿主机物理地址的转化。EPT的控
制权在虚拟机监控器中,只有当CPU工作在非根模式时才参与内存地址的转换。使用EPT
后,客户机在读写CR3和执行INVLPG指令时不会导致VM Exit,而且客户页表结构自身
导致的页故障也不会导致VM Exit。所以通过引入硬件上EPT的支持,简化了内存虚拟化
的实现复杂度,同时也提高了内存地址转换的效率。
图2-3 基于EPT的内存地址转换
除了EPT,Intel在内存虚拟化效率方面还引入了VPID(Virtual-processor identifier)特
性,在硬件级对TLB资源管理进行了优化。在没有VPID之前,不同客户机的逻辑CPU在
切换执行时需要刷新TLB,而TLB的刷新会让内存访问的效率下降。VPID技术通过在硬
件上为TLB增加一个标志,可以识别不同的虚拟处理器的地址空间,所以系统可以区分虚
拟机监控器和不同虚拟机上不同处理器的TLB,在逻辑CPU切换执行时就不会刷新TLB,而只需要使用对应的TLB即可。VPID的示意图如图2-4所示。当CPU运行在非根模式下,且虚拟机执行控制寄存器的“enable VPID”比特位被置为1时,当前的VPID的值是VMCS中
的VPID执行控制域的值,其值是非0的。VPID的值在3种情况下为0,第1种是在非虚拟化
环境中执行时,第2种是在根模式下执行时,第3种情况是在非根模式下执行但“enable
VPID”控制位被置0时。图2-4 VPID示意图2.1.3 IO虚拟化
在虚拟化的架构下,虚拟机监控器必须支持来自客户机的IO请求。通常情况下有以
下4种IO虚拟化方式。
1)设备模拟:在虚拟机监控器中模拟一个传统的IO设备的特性,比如在QEMU中模
拟一个Intel的千兆网卡或者一个IDE硬盘驱动器,在客户机中就暴露为对应的硬件设备。
客户机中的IO请求都由虚拟机监控器捕获并模拟执行后返回给客户机。
2)前后端驱动接口:在虚拟机监控器与客户机之间定义一种全新的适合于虚拟化环
境的交互接口,比如常见的virtio协议就是在客户机中暴露为virtio-net、virtio-blk等网络和
磁盘设备,在QEMU中实现相应的virtio后端驱动。
3)设备直接分配:将一个物理设备,如一个网卡或硬盘驱动器直接分配给客户机使
用,这种情况下IO请求的链路中很少需要或基本不需要虚拟机监控器的参与,所以性能
很好。
4)设备共享分配:其实是设备直接分配方式的一个扩展。在这种模式下,一个(具
有特定特性的)物理设备可以支持多个虚拟机功能接口,可以将虚拟功能接口独立地分配
给不同的客户机使用。如SR-IOV就是这种方式的一个标准协议。
表2-1展示了这4种IO虚拟化方式的优缺点,给读者一个概括性的认识。在这4种方式
中,前两种都是纯软件的实现,后两种都需要特定硬件特性的支持。
表2-1 常见IO虚拟化方式的优缺点
设备直接分配在Intel平台上就是VT-d(Virtualization Technology For Directed IO)特
性,一般在系统BIOS中可以看到相关的参数设置。Intel VT-d为虚拟机监控器提供了几个
重要的能力:IO设备分配、DMA重定向、中断重定向、中断投递等。图2-5描述了在VT-
d硬件特性的帮助下实现的设备直接分配的架构,并与最传统的、通过软件模拟设备的IO
设备虚拟化进行了对比。图2-5 使用VT-d与传统设备完全模拟的虚拟化架构对比[1]
尽管VT-d特性支持的设备直接分配方式性能可以接近物理设备在非虚拟化环境中的
性能极限,但是它有一个缺点:单个设备只能分配给一个客户机,而在虚拟化环境下一个
宿主机上往往运行着多个客户机,很难保证每个客户机都能得到一个直接分配的设备。为
了克服这个缺点,设备共享分配硬件技术就应运而生,其中SR-IOV(Single Root IO
Virtualization and Sharing)就是这样的一个标准。实现了SR-IOV规范的设备,有一个功能
完整的PCI-e设备成为物理功能(Physical Function,PF)。在使能了SR-IOV之后,PF就
会派生出若干个虚拟功能(Virtual Function,VF)。VF看起来依然是一个PCI-e设备,它
拥有最小化的资源配置,有用独立的资源,可以作为独立的设备直接分配给客户机使用。
Intel的很多高级网卡如82599系列网卡就支持SR-IOV特性,一个85299网卡PF就即可配置
出多达63个VF,基本可满足单个宿主机上的客户机分配使用。当然,SR-IOV这种特性可
以看作VT-d的一个特殊例子,所以SR-IOV除了设备本身要支持该特性,同时也需要硬件
平台打开VT-d特性支持。图2-6展示了一个Intel以太网卡支持SR-IOV的硬件基础架构。图2-6 支持SR-IOV的Intel网卡架构图
[1] 该图摘自文档Intel Virtualization Technology for Directed IO Architecture Specification。2.1.4 Intel虚拟化技术发展
虚拟化技术从最初的纯软件的虚拟化技术,逐步发展到硬件虚拟化技术的支持,时至
今日硬件虚拟化技术已比较成熟。前面3小节已经分别就各种硬件虚拟化技术进行了介
绍,这里以Intel平台为例,再对其做一个小结。
Intel硬件虚拟化技术大致分为如下3个类别(这个顺序也基本上是相应技术出现的时
间先后顺序)。
1)VT-x技术:是指Intel处理器中进行的一些虚拟化技术支持,包括CPU中引入的最
基础的VMX技术,使得KVM等硬件虚拟化基础的出现成为可能。同时也包括内存虚拟化
的硬件支持EPT、VPID等技术。
2)VT-d技术:是指Intel的芯片组的虚拟化技术支持,通过Intel IOMMU可以实现对
设备直接分配的支持。
3)VT-c技术:是指Intel的IO设备相关的虚拟化技术支持,主要包含两个技术:一个
是借助虚拟机设备队列(VMDq)最大限度提高IO吞吐率,VMDq由Intel网卡中的专用硬
件来完成;另一个是借助虚拟机直接互连(VMDc)大幅提升虚拟化性能,VMDc主要就
是基于SR-IOV标准将单个Intel网卡产生多个VF设备,用来直接分配给客户机。
图2-7展示了Intel的硬件虚拟化技术的发展线路图,从中我们可以看到从2005年开始
支持VT-x硬件虚拟化,到现在较多的SR-IOV等VT-d的虚拟化技术,硬件虚拟化技术家族
有了越来越多的成员,技术特性也逐步完善。如何在具体业务的生产环境中充分利用硬件
虚拟化技术带来的技术红利,构建高性能、可扩展、易维护的虚拟化环境,可能是大家学
习虚拟化的一个主要目标。通过本书,希望大家也能够了解一些实践经验和受到一些启
发。图2-7 Intel硬件虚拟化技术发展线路图2.2 KVM架构概述
上一节介绍了CPU、内存、IO等硬件虚拟化技术。KVM就是在硬件辅助虚拟化技术
之上构建起来的虚拟机监控器。当然,并非要所有这些硬件虚拟化都支持才能运行KVM
虚拟化,KVM对硬件最低的依赖是CPU的硬件虚拟化支持,比如:Intel的VT技术和AMD
的AMD-V技术,而其他的内存和IO的硬件虚拟化支持,会让整个KVM虚拟化下的性能
得到更多的提升。
KVM虚拟化的核心主要由以下两个模块组成:
1)KVM内核模块,它属于标准Linux内核的一部分,是一个专门提供虚拟化功能的
模块,主要负责CPU和内存的虚拟化,包括:客户机的创建、虚拟内存的分配、CPU执行
模式的切换、vCPU寄存器的访问、vCPU的执行。
2)QEMU用户态工具,它是一个普通的Linux进程,为客户机提供设备模拟的功能,包括模拟BIOS、PCIPCIE总线、磁盘、网卡、显卡、声卡、键盘、鼠标等。同时它通过
ioctl系统调用与内核态的KVM模块进行交互。
KVM是在硬件虚拟化支持下的完全虚拟化技术,所以它能支持在相应硬件上能运行
的几乎所有的操作系统,如:Linux、Windows、FreeBSD、MacOS等。KVM的基础架构
如图2-8所示。在KVM虚拟化架构下,每个客户机就是一个QEMU进程,在一个宿主机上
有多少个虚拟机就会有多少个QEMU进程;客户机中的每一个虚拟CPU对应QEMU进程中
的一个执行线程;一个宿主机中只有一个KVM内核模块,所有客户机都与这个内核模块
进行交互。图2-8 KVM虚拟化基础架构2.3 KVM内核模块
KVM内核模块是标准Linux内核的一部分,由于KVM的存在让Linux本身就变成了一
个Hypervisor,可以原生地支持虚拟化功能。目前,KVM支持多种处理器平台,它支持最
常见的以Intel和AMD为代表的x86和x86_64平台,也支持PowerPC、S390、ARM等非x86
架构的平台。
KVM模块是KVM虚拟化的核心模块,它在内核中由两部分组成:一个是处理器架构
无关的部分,用lsmod命令中可以看到,叫作kvm模块;另一个是处理器架构相关的部
分,在Intel平台上就是kvm_intel这个内核模块。KVM的主要功能是初始化CPU硬件,打
开虚拟化模式,然后将虚拟客户机运行在虚拟机模式下,并对虚拟客户机的运行提供一定
的支持。
KVM仅支持硬件辅助的虚拟化,所以打开并初始化系统硬件以支持虚拟机的运行,是KVM模块的职责所在。以KVM在Intel公司的CPU上运行为例,在被内核加载的时候,KVM模块会先初始化内部的数据结构;做好准备之后,KVM模块检测系统当前的CPU,然后打开CPU控制寄存器CR4中的虚拟化模式开关,并通过执行VMXON指令将宿主操作
系统(包括KVM模块本身)置于CPU执行模式的虚拟化模式中的根模式;最后,KVM模
块创建特殊设备文件devkvm并等待来自用户空间的命令。接下来,虚拟机的创建和运行
将是一个用户空间的应用程序(QEMU)和KVM模块相互配合的过程。
devkvm这个设备可以被当作一个标准的字符设备,KVM模块与用户空间QEMU的
通信接口主要是一系列针对这个特殊设备文件的loctl调用。当然,每个虚拟客户机针
对devkvm文件的最重要的loctl调用就是“创建虚拟机”。在这里,“创建虚拟机”可以理解
成KVM为了某个特定的虚拟客户机(用户空间程序创建并初始化)创建对应的内核数据
结构。同时,KVM还会返回一个文件句柄来代表所创建的虚拟机。针对该文件句柄的
loctl调用可以对虚拟机做相应的管理,比如创建用户空间虚拟地址和客户机物理地址及真
实内存物理地址的映射关系,再比如创建多个可供运行的虚拟处理器(vCPU)。同样,KVM模块会为每一个创建出来的虚拟处理器生成对应的文件句柄,对虚拟处理器相应的
文件句柄进行相应的loctl调用,就可以对虚拟处理器进行管理。
针对虚拟处理器的最重要的loctl调用就是“执行虚拟处理器”。通过它,用户空间准备
好的虚拟机在KVM模块的支持下,被置于虚拟化模式中的非根模式下,开始执行二进制
指令。在非根模式下,所有敏感的二进制指令都会被处理器捕捉到,处理器在保存现场之
后自动切换到根模式,由KVM决定如何进一步处理(要么由KVM模块直接处理,要么返
回用户空间交由用户空间程序处理)。
除了处理器的虚拟化,内存虚拟化也是由KVM模块实现的,包括前面提到的使用硬
件提供的EPT特性,通过两级转换实现客户机虚拟地址到宿主机物理地址之间的转换。
处理器对设备的访问主要是通过IO指令和MMIO,其中IO指令会被处理器直接截
获,MMIO会通过配置内存虚拟化来捕捉。但是,外设的模拟一般不由KVM模块负责。
一般来说,只有对性能要求比较高的虚拟设备才会由KVM内核模块来直接负责,比如虚
拟中断控制器和虚拟时钟,这样可以大量减少处理器模式切换的开销。而大部分的输入输
出设备交给下一节将要介绍的用户态程序QEMU来负责。2.4 QEMU用户态设备模拟
QEMU原本就是一个著名的开源虚拟机软件项目,而不是KVM虚拟化软件的一部
分。与KVM不同,QEMU最初实现的虚拟机是一个纯软件的实现,通过二进制翻译来实
现虚拟化客户机中的CPU指令模拟,所以性能比较低。但是,其优点是跨平台,QEMU支
持在Linux、Windows、FreeBSD、Solaris、MacOS等多种操作系统上运行,能支持在
QEMU本身编译运行的平台上就实现虚拟机的功能,甚至可以支持客户机与宿主机并不是
同一个架构(比如在x86平台上运行ARM客户机)。作为一个存在已久的虚拟机监控器软
件,QEMU的代码中有完整的虚拟机实现,包括处理器虚拟化、内存虚拟化,以及KVM
也会用到的虚拟设备模拟(比如网卡、显卡、存储控制器和硬盘等)。
除了二进制翻译的方式,QEMU也能与基于硬件虚拟化的Xen、KVM结合,为它们提
供客户机的设备模拟。通过与KVM的密切结合,让虚拟化的性能提升得非常高,在真实
的企业级虚拟化场景中发挥重要作用,所以我们通常提及KVM虚拟化时就会
说“QEMUKVM”这样的软件栈。
最早期的KVM开发者们为了简化软件架构和代码重用,根据KVM特性在QEMU的基
础上进行了修改(当然这部分修改已经合并回QEMU的主干代码,故现在的QEMU已原生
支持KVM虚拟化特性)。从图2-8可以看出,每一个虚拟客户机在宿主机中就体现为一个
QEMU进程,而客户机的每一个虚拟CPU就是一个QEMU线程。虚拟机运行期间,QEMU
会通过KVM模块提供的系统调用进入内核,由KVM模块负责将虚拟机置于处理器的特殊
模式下运行。遇到虚拟机进行IO操作时,KVM模块会从上次的系统调用出口处返回
QEMU,由QEMU来负责解析和模拟这些设备。
从QEMU角度来看,也可以说QEMU使用了KVM模块的虚拟化功能,为自己的虚拟
机提供硬件虚拟化的加速,从而极大地提高了虚拟机的性能。除此之外,虚拟机的配置和
创建,虚拟机运行依赖的虚拟设备,虚拟机运行时的用户操作环境和交互,以及一些针对
虚拟机的特殊技术(如:动态迁移),都是由QEMU自己实现的。
QEMU除了提供完全模拟的设备(如:e1000网卡、IDE磁盘等)以外,还支持virtio
协议的设备模拟。virtio是一个沟通客户机前端设备与宿主机上设备后端模拟的比较高性
能的协议,在前端客户机中需要安装相应的virtio-blk、virtio-scsi、virtio-net等驱动,而
QEMU就实现了virtio的虚拟化后端。QEMU还提供了叫作virtio-blk-data-plane的一种高性
能的块设备IO方式,它最初在QEMU 1.4版本中被引入。virtio-blk-data-plane与传统virtio-
blk相比,它为每个块设备单独分配一个线程用于IO处理,data-plane线程不需要与原
QEMU执行线程同步和竞争锁,而且它使用ioeventfdirqfd机制,同时利用宿主机Linux上
的AIO(异步IO)来处理客户机的IO请求,使得块设备IO效率进一步提高。
总之,QEMU既是一个功能完整的虚拟机监控器,也在QEMUKVM的软件栈中承担
设备模拟的工作。2.5 与QEMUKVM结合的组件
在KVM虚拟化的软件栈中,毋庸置疑的是KVM内核模块与QEMU用户态程序是处于
最核心的位置,有了它们就可通过qemu命令行操作实现完整的虚拟机功能,本书中多数
的实践范例正是通过qemu命令行来演示的。然而,在实际的云计算的虚拟化场景中,为
了更高的性能或者管理的方便性,还有很多的软件可以作为KVM虚拟化实施中的组件,这里简单介绍其中的几个。
1.vhost-net
vhost-net是Linux内核中的一个模块,它用于替代QEMU中的virtio-net用户态的virtio网
络的后端实现。使用vhost-net时,还支持网卡的多队列,整体来说会让网络性能得到较大
提高。在6.1.6节中对vhost-net有更多的介绍。
2.Open vSwitch
Open vSwitch是一个高质量的、多层虚拟交换机,使用开源Apache2.0许可协议,主要
用可移植性强的C语言编写的。它的目的是让大规模网络自动化可以通过编程扩展,同时
仍然支持标准的管理接口和协议(例如NetFlow、sFlow、SPAN、RSPAN、CLI、LACP、802.1ag)。同时也提供了对OpenFlow协议的支持,用户可以使用任何支持OpenFlow协议
的控制器对OVS进行远程管理控制。Open vSwitch被设计为支持跨越多个物理服务器的分
布式环境,类似于VMware的vNetwork分布式vswitch或Cisco Nexus 1000 V。Open vSwitch
支持多种虚拟化技术,包括XenXenServer、KVM和VirtualBox。在KVM虚拟化中,要实
现软件定义网络(SDN),那么Open vSwitch是一个非常好的开源选择。
3.DPDK
DPDK全称是Data Plane Development Kit,最初是由Intel公司维护的数据平面开发工
具集,为Intel x86处理器架构下用户空间高效的数据包处理提供库函数和驱动的支持,现
在也是一个完全独立的开源项目,它还支持POWER和ARM处理器架构。不同于Linux系
统以通用性设计为目的,它专注于网络应用中数据包的高性能处理。具体体现在DPDK应
用程序是运行在用户空间上,利用自身提供的数据平面库来收发数据包,绕过了Linux内
核协议栈对数据包处理过程。其优点是:性能高、用户态开发、出故障后易恢复。在
KVM架构中,为了达到非常高的网络处理能力(特别是小包处理能力),可以选择
DPDK与QEMU中的vhost-user结合起来使用。
4.SPDK
SPDK全称是Storage Performance Development Kit,它可为编写高性能、可扩展的、用户模式的存储程序提供一系列工具及开发库。它与DPDK非常类似,其主要特点是:将
驱动放到用户态从而实现零拷贝、用轮询模式替代传统的中断模式、在所有的IO链路上
实现无锁设计,这些设计会使其性能比较高。在KVM中需要非常高的存储IO性能时,可
以将QEMU与SPDK结合使用。
5.CephCeph是Linux上一个著名的分布式存储系统,能够在维护POSIX兼容性的同时加入复
制和容错功能。Ceph由储存管理器(Object storage cluster对象存储集群,即OSD守护进
程)、集群监视器(Ceph Monitor)和元数据服务器(Metadata server cluster,MDS)构
成。其中,元数据服务器MDS仅仅在客户端通过文件系统方式使用Ceph时才需要。当客
户端通过块设备或对象存储使用Ceph时,可以没有MDS。Ceph支持3种调用接口:对象存
储,块存储,文件系统挂载。在libvirt和QEMU中都有Ceph的接口,所以Ceph与KVM虚拟
化集成是非常容易的。在OpenStack的云平台解决方案中,Ceph是一个非常常用的存储后
端。
6.libguestfs
libguestfs是用于访问和修改虚拟机的磁盘镜像的一组工具集合。libguestfs提供了访问
和编辑客户机中的文件、脚本化修改客户机中的信息、监控磁盘使用和空闲的统计信息、P2V、V2V、创建客户机、克隆客户机、备份磁盘内容、格式化磁盘、调整磁盘大小等非
常丰富的功能。libguestfs还提供了共享库,可以在CC++、Python等编程语言中对其进行
调用。libguestfs不需要启动KVM客户机就可以对磁盘镜像进行管理,功能强大且非常灵
活,是管理KVM磁盘镜像的首选工具。2.6 KVM上层管理工具
一个成熟的虚拟化解决方案离不开良好的管理和运维工具,部署、运维、管理的复杂
度与灵活性是企业实施虚拟化时重点考虑的问题。KVM目前已经有从libvirt API、virsh命
令行工具到OpenStack云管理平台等一整套管理工具,尽管与老牌虚拟化巨头VMware提供
的商业化虚拟化管理工具相比在功能和易用性上有所差距,但KVM这一整套管理工具都
是API化的、开源的,在使用的灵活性以及对其做二次开发的定制化方面仍有一定优势。
根据笔者的实践经验,本节给大家概括性地介绍KVM软件栈中常见的几个管理运维工
具,在第4章将会详细介绍相关内容。
1.libvirt
libvirt是使用最广泛的对KVM虚拟化进行管理的工具和应用程序接口,已经是事实上
的虚拟化接口标准,本节后部分介绍的其他工具都是基于libvirt的API来实现的。作为通
用的虚拟化API,libvirt不但能管理KVM,还能管理VMware、Hyper-V、Xen、VirtualBox
等其他虚拟化方案。
2.virsh
virsh是一个常用的管理KVM虚拟化的命令行工具,对于系统管理员在单个宿主机上
进行运维操作,virsh命令行可能是最佳选择。virsh是用C语言编写的一个使用libvirt API的
虚拟化管理工具,其源代码也是在libvirt这个开源项目中的。
3.virt-manager
virt-manager是专门针对虚拟机的图形化管理软件,底层与虚拟化交互的部分仍然是
调用libvirt API来操作的。virt-manager除了提供虚拟机生命周期(包括:创建、启动、停
止、打快照、动态迁移等)管理的基本功能,还提供性能和资源使用率的监控,同时内置
了VNC和SPICE客户端,方便图形化连接到虚拟客户机中。virt-manager在RHEL、CentOS、Fedora等操作系统上是非常流行的虚拟化管理软件,在管理的机器数量规模较小
时,virt-manager是很好的选择。因其图形化操作的易用性,成为新手入门学习虚拟化操
作的首选管理软件。
4.OpenStack
OpenStack是一个开源的基础架构即服务(IaaS)云计算管理平台,可用于构建共有
云和私有云服务的基础设施。OpenStack是目前业界使用最广泛的功能最强大的云管理平
台,它不仅提供了管理虚拟机的丰富功能,还有非常多其他重要管理功能,如:对象存
储、块存储、网络、镜像、身份验证、编排服务、控制面板等。OpenStack仍然使用libvirt
API来完成对底层虚拟化的管理。2.7 本章小结
本节主要介绍了KVM虚拟化的基本原理,从硬件到软件、从底层到上层都做了一些
介绍,包括:硬件虚拟化技术简介、KVM软件架构概况、KVM内核模块、QEMU用户态
设备模拟、与KVM结合的vhost-net等组件、KVM的管理工具等。由于KVM是基于硬件辅
助的虚拟化软件,故在2.1节又分别介绍了CPU虚拟化、内存虚拟化、IO虚拟化以及Intel
的虚拟化技术发展情况,以帮助读者理解虚拟化原理。同时,通过对QEMUKVM相结合
的组件和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的S390架构、ARM架构(2012年开始[1])等。其中,在x86-64上面的
功能支持是最完善的(主要原因是IntelAMD的x86-64架构在桌面和服务器市场上的主导
地位及其架构的开放性,以及它的开发者众多),本书也采用基于Intel x86-64架构的处理
器作为基本的硬件环境[2]。
在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 IO),建议在BIOS中将其打开,因为后面一些相对高级的设备的
直接分配功能会需要硬件VT-d技术的支持。VT-d是对设备IO的虚拟化硬件支持,在BIOS
中的位置可能为“Advanced→Processor Configuration”或“Advanced→System
Agent(SA)Configuration”,它在BIOS中的标志一般为“Intel(R)VT for Directed IO”或“Intel
VT-d”。
下面以一台Intel Haswell-UP平台的服务器为例,来说明在BIOS中的设置。
1)BIOS中的Advanced选项,如图3-1所示。图3-1 BIOS中的Advanced选项
2)BIOS中Enabled的VT和VT-d选项,如图3-2所示。图3-2 BIOS中Enabled的VT和VT-d选项
对于不同平台或不同厂商的BIOS,VT和VT-d等设置的位置可能是不一样的,需要根
据实际的硬件情况和BIOS中的选项来灵活设置。
设置好了VT和VT-d的相关选项,保存BIOS的设置并退出,系统重启后生效。在
Linux系统中,可以通过检查proccpuinfo文件中的CPU特性标志(flags)来查看CPU目前
是否支持硬件虚拟化。在x86和x86-64平台中,Intel系列CPU支持虚拟化的标志为“vmx”,AMD系列CPU的标志为“svm”。所以可以用以下命令行查看“vmx”或者“svm”标志:
[root@kvm-host ~] grep -E svm|vmx proccpuinfo
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
[1] KVM在ARM处理器上的第一次正式实现,可以参考链接
http:comments.gmane.orggmane.comp.emulators.kvm.devel87136中主题为[PATCH v6
0012]KVMARM Implementation的邮件。
[2] 在本书中,若无特别注明,所有理论和实验都是基于Intel x86-64处理器的。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版的系统来简单介绍[1]
,普
通Linux安装的基本过程不再详细描述,这里主要说明安装过程中一些值得注意的地方。
在选择哪些安装包(SOFTWARE SELECTION)时(图3-3),点进去选择“Server
with GUI”[2]
,而不是默认的“Minimal Install”,如图3-4所示。图3-3 在RHEL 7.3安装过程中的安装包的选择
在选择了“Server with GUI”之后,右侧还有可以额外增加的组件供选择(见图3-4),我们需要选上“Development Tools”,因为在本书的KVM编译过程中以及其他实验中可能
会用到,其中包括一些比较重要的软件包,比如:gcc、git、make等(一般被默认选
中)。可以看到还有“Virtualization Hypervisor”“Virtualization Tools”,这里可以暂时不选
它们(选上也没有关系),因为在本章中会自己编译KVM和QEMU,而在附录A介绍发行
版中的KVM时,我们会安装Virtualization Host环境,并使用发行版中自带的KVM
Virtualization功能。图3-4 Base Environment选择Server with GUI
然后,单击“Done”按钮并继续进行后面的安装流程。可以安装相应的软件包,安装
过程的一个快照如图3-5所示。
在安装完所有软件包后,系统会提示安装完成需要重启系统,重启后即可进入RHEL
7.3系统中。至此,Linux系统就安装完毕了,这就是在本书中作为宿主机(Host)的操作
系统,后面的编译和实验都是在这个宿主机上进行的(当然,我们会使用本章讲述的自己
编译的kernel和QEMU来进行实验)。图3-5 RHEL 7.3安装过程快照
[1] 一些安装步骤可参考Redhat的英文文档:https:access.redhat.comdocumentationen-
USRed_Hat_Enterprise_Linux7htmlInstallation_Guideindex.html。
[2] 这里不选择“Virtualization Host”是因为后面会自己编译安装QEMU。当然选
择“Virtualization Host”并在后面加装GUI软件包也没有关系。自己编译安装的QEMU等工
具会覆盖系统自带的。但无论选择哪种,都要再选上“Development Tools”额外环境包,这
是我们后面编译所需要的。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]
格式)。
1.下载kvm.git
KVM项目的代码是托管在Linux内核官方源码网站http:git.kernel.org上的,可以到上
面查看和下载。该网页上virtkvmkvm.git即KVM项目的代码,它是最新的、功能最丰富
的KVM源代码库(尽管并非最稳定的)。目前,kvm.git的最主要维护者(maintainer)是
来自Redhat公司的Paolo Bonzini和Radim Krcmár。从http:git.kernel.org?p=virtkvmkvm.git
网页可以看到,kvm.git的下载链接有以下3个URL,可用于下载最新的KVM的开发代码仓
库。
git:git.kernel.orgpubscmvirtkvmkvm.git
http:git.kernel.orgpubscmvirtkvmkvm.git
https:git.kernel.orgpubscmvirtkvmkvm.git
这3个URL下载的内容完全一致,根据自己实际情况选择其中一个下载即可。Linux内
核相关的项目一般都使用Git
[2]
作为源代码管理工具,KVM当然也是用Git管理源码的。可
以使用git clone命令来下载KVM的源代码,也可以使用Git工具的其他命令对源码进行各
种管理。这里不详述Git的各种命令,有兴趣的读者可以参考其他文稿。
kvm.git的下载方式和过程为以下命令行所示:
[root@kvm-host ~] git clone
git:git.kernel.orgpubscmvirtkvmkvm.git
Cloning into 'kvm'...
remote: Counting objects: 5017872, done.
remote: Compressing objects: 100% (938249938249), done.
Receiving objects: 100% (50178725017872), 1006.69 MiB | 60.72 MiBs, done.
remote: Total 5017872 (delta 4229078), reused 4826094 (delta 4038351)Resolving deltas: 100% (42290784229078), done.
Checking out files: 100% (5591455914), done.
[root@kvm-host ~] cd kvm
[root@kvm-host kvm] pwd
rootkvm
2.下载linux.git
Linux内核的官方网站为http:kernel.org,其中源代码管理网站为http:git.kernel.org,可以在那里找到最新的linux.git代码。在源码管理网站上,我们看到有多个linux.git,我们
选择Linus Torvalds[3]
的源码库(也即是Linux内核的主干)。在内核源码的网
页http:git.kernel.org?p=linuxkernelgittorvaldslinux.git中可以看到,其源码仓库也有以下
3个链接可用:
git:git.kernel.orgpubscmlinuxkernelgittorvaldslinux.git
http:git.kernel.orgpubscmlinuxkernelgittorvaldslinux.git
https:git.kernel.orgpubscmlinuxkernelgittorvaldslinux.git
这3个URL中源码内容是完全相同的,可以使用git clone命令复制到本地,其具体操作
方式与前一种(kvm.git)的下载方式完全一样。
3.下载Linux的Tarball
在Linux官方网站(http:kernel.org)上,也提供Linux内核的Tarball文件下载。除了
在其首页上单击一些Tarball之外,也可以到以下网址下载Linux内核的各个版本的
Tarball:
·ftp:ftp.kernel.orgpublinuxkernel。
·http:www.kernel.orgpublinuxkernel。
kernel.org还提供一种rsync的方式下载,此处不详细叙述,请参见其官网首页的提
示。
以用wget下载linux-4.8.1.tar.xz为例,命令行代码如下:
[root@kvm-host ~] wget
https:cdn.kernel.orgpublinuxkernelv4.xlinux-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.cnkernel与http:www.kernel.orgpublinuxkernel是同步
的,用起来比较方便。
·北京交通大学的一个开源镜像站:http:mirror.bjtu.edu.cnkernellinuxkernel。
还有以下两个镜像站推荐给大家:
·网易开源镜像站,http:mirrors.163.com。
·搜狐开源镜像站,http:mirrors.sohu.com。
[1] Tarball是UNIXLinux世界中的一个术语,用于指代tar档案(通过tar命令打包归档后的
文件,如常见的.tar、.tar.gz、.tar.bz2结尾的档案文件)。
[2] Git是一个高效、快速的分布式的版本控制工具和源代码管理工具,最初是Linus
Torvalds为Linux内核开发而设计和开发的工具,是Linux中最广泛使用的SCM工具。另
外,一个基于Git的非常著名的源码托管网站https:github.com也值得推荐一下。
[3] Linus Torvalds,就是那个著名的Linux创始人,从芬兰移民到美国,是著名的软件工程
师和黑客。1991年,在芬兰赫尔辛基大学读书的Linus发布了后来最流行的开源操作系统
内核Linux的第一个版本。3.3.2 配置KVM
上面3种方式下载的源代码都可以同样地进行配置和编译,本章以开发中的最新源代
码仓库kvm.git来讲解KVM的配置和编译等。KVM是作为Linux内核中的一个module而存
在的,而kvm.git是一个包含了最新的KVM模块开发中代码的完整的Linux内核源码仓库。
它的配置方式与普通的Linux内核配置完全一样,只是需要注意将KVM相关的配置选择为
编译进内核或者编译为模块。
在kvm.git(Linux kernel)代码目录下,运行“make help”命令可以得到一些关于如何
配置和编译kernel的帮助手册。命令行如下:
[root@kvm-host kvm] make help
Cleaning targets:
clean - Remove most generated files but keep the config and enough
build support to build external modules
mrproper - Remove all generated files + config + various backup files
distclean - mrproper + remove editor backup and patch files
Configuration targets:
config - Update current config utilising a line-oriented program
nconfig - Update current config utilising a ncurses menu based program
menuconfig - Update current config utilising a menu based program
xconfig - Update current config utilising a Qt based front-end
gconfig - Update current config utilising a GTK+ based front-end
oldconfig - Update current config utilising a provided .config as base
localmodconfig - Update current config disabling modules not loaded
localyesconfig - Update current config converting local mods to core
silentoldconfig - Same as oldconfig, but quietly, additionally update deps
defconfig - New config with default from ARCH supplied defconfig
savedefconfig - Save current config as .defconfig (minimal config)
allnoconfig - New config where all options are answered with no
allyesconfig - New config where all options are accepted with yes
allmodconfig - New config selecting modules when possible
alldefconfig - New config with all symbols set to default
randconfig - New config with random answer to all options
listnewconfig - List new options
olddefconfig - Same as silentoldconfig but sets new symbols to their default
value
kvmconfig - Enable additional options for kvm guest kernel support
xenconfig - Enable additional options for xen dom0 and guest kernel support
tinyconfig - Configure the tiniest possible kernel
对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平台上,默认配置为archx86configsx86_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所示。图3-6 make menuconfig命令的选择界面
图3-7 Virtualization中的配置选项
提示:为了确保生成的.config文件生成的kernel是实际可以工作的(直接make
defconfig生成的.config文件编译出来的kernel常常是不能工作的),最佳实践是以你当前
使用的config(比如,我们安装好RHEL 7.3的OS以后,bootconfig-3.10.0-xxx.x86_64)为
基础,将它复制到你的linux目录下,重命名为.config,然后通过make olddefconfig更新补
充一下这个.config。
在配置完成之后,就会在kvm.git目录下面生成一个.config文件。最好检查一下KVM
相关的配置是否正确。在本次配置中,与KVM直接相关的几个配置项主要情况如下:CONFIG_HAVE_KVM=y
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_HAVE_KVM_EVENTFD=y
CONFIG_KVM_APIC_ARCHITECTURE=y
CONFIG_KVM_MMIO=y
CONFIG_KVM_ASYNC_PF=y
CONFIG_HAVE_KVM_MSI=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
CONFIG_KVM_INTEL=m
CONFIG_KVM_AMD is not set
CONFIG_KVM_MMU_AUDIT=y3.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 includegeneratedcompile.h
UPD includegeneratedcompile.h
CC initversion.o
LD initbuilt-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 includeconfigkernel.release
CHK includegenerateduapilinuxversion.h
CHK includegeneratedutsrelease.h
LD archx86bootsetup.elf
OBJCOPY archx86bootsetup.bin
OBJCOPY archx86bootvmlinux.bin
HOSTCC archx86boottoolsbuild
BUILD archx86bootbzImage 这里生成了我们需要的bzImage文件
Setup is 17276 bytes (padded to 17408 bytes).
System is 5662 kB
CRC 3efff614
Kernel: archx86bootbzImage is ready (2)
3)编译kernel和bzImage之后编译内核的模块,命令为“make modules”,其命令行输出如下:
[root@kvm-host kvm] make modules -j 20
IHEX2FW firmwareemi26loader.fw
IHEX2FW firmwareemi26firmware.fw
IHEX2FW firmwareemi26bitstream.fw
IHEX2FW firmwareemi62loader.fw
IHEX2FW firmwareemi62bitstream.fw
IHEX2FW firmwareemi62spdif.fw
IHEX2FW firmwareemi62midi.fw
H16TOFW firmwareedgeportboot2.fw
H16TOFW firmwareedgeportboot.fw
H16TOFW firmwareedgeportdown.fw
H16TOFW firmwareedgeportdown2.fw
IHEX2FW firmwarewhiteheat_loader.fw
IHEX2FW firmwarewhiteheat.fw
IHEX2FW firmwarekeyspan_pdakeyspan_pda.fw
IHEX2FW firmwarekeyspan_pdaxircom_pgs.fw 3.3.4 安装KVM
编译完KVM之后,下面介绍如何安装KVM。
KVM的安装包括两个步骤:安装module,安装kernel与initramfs。
1.安装module
通过“make modules_install”命令可以将编译好的module安装到相应的目录中,默认情
况下module被安装到libmoduleskernel_versionkernel目录中。
[root@kvm-host kvm] make modules_install
INSTALL libfirmwarewhiteheat.fw
INSTALL libfirmwarekeyspan_pdakeyspan_pda.fw
INSTALL libfirmwarekeyspan_pdaxircom_pgs.fw
DEPMOD 4.8.0+
安装好module之后,可以查看一下相应的安装路径,可看到kvm模块也已经安装。如
下所示:
[root@kvm-host kvm] ll libmodules4.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 libmodules4.8.0+kernelarchx86kvm
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 .archx86bootinstall.sh 4.8.0+ archx86bootbzImage 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 -> bootSystem.map-4.8.0+
lrwxrwxrwx 1 root root 20 Oct 15 15:10 vmlinuz -> bootvmlinuz-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配置文件(如:bootgrub2grub.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 [ xfeature_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=devmapperrhel-root ro rd.lvm.lv=rhelroot crashkernel=auto rd.lvm.lv=rhelswap vconsole.font=latarcyrheb-sun16 vconsole.keymap=us rhgb devdiskby-uuid19d79b0d-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相关的模块加载成功后,检查devkvm这个文件,它是kvm内核模块提供给
用户空间的QEMU程序使用的一个控制接口,它提供了客户机(Guest)操作系统运行所
需要的模拟和实际的硬件设备环境。
[root@kvm-host kvm] ls -l devkvm
crw-rw-rw-+ 1 root kvm 10, 232 Oct 9 15:22 devkvm 3.4 编译和安装QEMU
除了在内核空间的KVM模块之外,在用户空间需要QEMU[1]
来模拟所需要的CPU和
设备模型,以及启动客户机进程,这样才有了一个完整的KVM运行环境。
在编译和安装了KVM并且启动到编译的内核之后,下面来看一下QEMU的编译和安
装。
[1] 关于QEMU项目,可以参考其官方网站:http:wiki.qemu.orgMain_Page。3.4.1 曾经的qemu-kvm
在上一版中,我们是以qemu-kvm为例来讲解QEMUKVM的。qemu-kvm原本是kernel
社区维护的专门用于KVM的QEMU的分支。
在2012年年末的时候,这个分支并入了主流的QEMU(git:git.qemu-
project.orgqemu.git)。从此,不再需要特殊的qemu-kvm,而只是通用的QEMU加上--
enable-kvm选项就可以创建KVM guest了。3.4.2 下载QEMU源代码
在并入主流QEMU以后,目前的QEMU项目针对KVMx86的部分依然是由Redhat公司
的Paolo Bonzini作为维护者(Maintainer),代码的git url托管在qemu-project.org上。
QEMU开发代码仓库的网页连接为:http:git.qemu.orgqemu.git。
其中,可以看到有如下2个URL链接可供下载开发中的最新qemu-kvm的代码仓库。
git:git.qemu.orgqemu.git
http:git.qemu.orggitqemu.git
可以根据自己实际需要选择当中任一个,用git clone命令下载即可,它们是完全一样
的。
另外,也可以到以下下载链接中根据需要下载最近几个发布版本的代码压缩包。
http:wiki.qemu.orgDownload
在本节后面讲解编译时,是以下载开发中的最新的qemu.git为例的。获取其代码仓库
过程如下:
[root@kvm-host ~] git clone git:git.qemu.orgqemu.git
Cloning into 'qemu'...
remote: Counting objects: 294725, done.
remote: Compressing objects: 100% (5942559425), done.
remote: Total 294725 (delta 238595), reused 289874 (delta 234513)
Receiving objects: 100% (294725294725), 94.23 MiB | 37.66 MiBs, done.
Resolving deltas: 100% (238595238595), 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 [usrlocal]--interp-prefix=PREFIX where to find shared libraries, etc.
use %M for cpu name [usrgnemulqemu-%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 usrlocal
BIOS directory usrlocalshareqemu...ELF interp prefix usrgnemulqemu-%M
Source path rootqemu
C compiler cc
Host C compiler cc...
QEMU_CFLAGS -Iusrincludepixman-1 -Werror -pthread -Iusrincludeglib-2.0 -Iusrlib64glib-2.0include -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-softmmuqemu-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被安装之后的系统状态。
[root@kvm-host qemu] ls usrlocalshareqemu
acpi-dsdt.aml efi-eepro100.rom keymaps openbios-sparc32 pxe-e1000.rom
QEMU,cgthree.bin slof.bin vgabios-qxl.bin
bamboo.dtb efi-ne2k_pci.rom kvmvapic.bin openbios-sparc64
pxe-eepro100.rom qemu-icon.bmp spapr-rtas.bin
vgabios-stdvga.bin
bios-256k.bin efi-pcnet.rom linuxboot.bin palcode-clipper
pxe-ne2k_pci.rom qemu_logo_no_text.svg trace-events-all
vgabios-virtio.bin
bios.bin efi-rtl8139.rom linuxboot_dma.bin petalogix-ml605.dtb
pxe-pcnet.rom QEMU,tcx.bin u-boot.e500
vgabios-VMware.bin
efi-e1000e.rom efi-virtio.rom multiboot.bin petalogix-s3adsp1800.dtb
pxe-rtl8139.rom ......
您现在查看是摘要介绍页, 详见PDF附件(16220KB,542页)。





