0%

KVM原理简介

简介

本文总结了《KVM实战:原理、进阶与性能调优》一书中的KVM原理简介部分,这一部分主要介绍了KVM虚拟化的基本原理,从硬件到软件、从底层到上层都做了一些介绍,包括:硬件虚拟化技术简介、KVM软件架构概况、KVM内核模块、QEMU用户态设备模拟、与KVM结合的vhost-net等组件、KVM的管理工具等。由于KVM是基于硬件辅助的虚拟化软件,故在第一节又分别介绍了CPU虚拟化、内存虚拟化、I/O虚拟化以及Intel 的虚拟化技术发展情况,以帮助读者理解虚拟化原理。

如果你想:

  1. 大概了解KVM虚拟化的基本原理;
  2. 大致了解KVM和QEMU是如何配合工作的;
  3. 在当今的云计算场景下,有哪些和KVM配合使用的工具;

那么相信此文会对您有所帮助!:)

为了更好地明白此文,您需要对以下知识需要有了解:

  1. 虚拟内存;

硬件虚拟化

CPU虚拟化

CPU虚拟化最关键的技术是CPU中为了支持CPU虚拟化而产生的VMX技术,在VMX技术中,有两种VMX操作模式:

  1. VMX root operation(根模式):hypervisor就运行在这个模式
  2. VMX non-root operation(非根模式):guest就运行在这个模式(包括guest上的操作系统和运行在操作系统上的软件

具体的运行周期可以参考下图:guest运行到一些特殊的敏感指令时,会触发VM Exit,从而从非根模式退回到根模式中。

image-20211216103504588
image-20211216103504588
  1. 一个逻辑CPU怎么在VMX的根模式和VMX的非根模式中进行切换呢?——通过VMCS的数据结构;

  2. hypervisor会为guest中的每一个逻辑CPU维护一个VMCS数据结构;

由于发生一次VM Exit的代价是比较高的(可能会消耗成百上千个CPU 执行周期,而平时很多指令是几个CPU执行周期就能完成),所以对于VM Exit的分析是虚拟化中性能分析和调优的一个关键点。

内存虚拟化

  1. 对于内存虚拟化,内存虚拟化的目的是什么?

    内存虚拟化的目的是给虚拟客户机操作系统提供一个从0地址开始的连续物理内存空间,同时在多个客户机之间实现隔离和调度。

  2. 内存虚拟化中的四个地址

    image-20211216104812345
    image-20211216104812345
    1. 客户机虚拟地址,GVA(Guest Virtual Address)
    2. 客户机物理地址,GPA(Guest Physical Address)
    3. 宿主机虚拟地址,HVA(Host Virtual Address)
    4. 宿主机物理地址,HPA(Host Physical Address)
  3. 所以,内存虚拟化的最终目的就是要把GVA转化为HPA

  4. 关于影子页表,影子页表的机制很简单,就是一个GVA到HPA的页表,但是可以想象的是维护影子页表的开销和复杂度是非常高的,而且需要为每一个guest都维护一份影子页表,占用的空间也是问题

  5. Intel CPU在硬件设计上就引入了EPT(Extended Page Tables,扩展页表),从而将客 户机虚拟地址到宿主机物理地址的转换通过硬件来实现。分为两步:

    1. 首先,通过客户机CR3寄存器将客户机虚拟地址转化为客户机物理地址
    2. 然后通过查询EPT来实现客户机物理地址到宿主机物理地址的转化
    image-20211216105340822
    image-20211216105340822
  6. Intel CPU在内存虚拟化方面,为了提高效率还引入了VPID(Virtual-Processor Identifer)以区分不同的guest中的不同逻辑CPU,带来了什么好处?以前在切换逻辑CPU的时候,每次都要刷新TLB,这样子会对内存访问的效率造成很大的影响,而现在可以通过VPID识别不同的逻辑CPU,hypervisor再为每一个逻辑CPU保存一份TLB的副本,然后进行逻辑CPU切换时直接通过VPID拿出对应的TLB来使用即可。image-20211216111107826

I/O虚拟化

除了CPU虚拟化和内存虚拟化以外,为了支持guest的正常运行,还需要I/O虚拟化,一般来说有下面四种I/O虚拟化方式:

  1. 设备模拟:纯软件模拟,比如使用QEMU模拟一个Intel网卡,guest完全和这个模拟出来的网卡进行交互
  2. 前后端驱动:在hypervisor与guest之间定义一种全新的适合于虚拟化环境的交互接口,比如常见的virtio协议就是在客户机中暴露为virtio-net、virtio-blk等网络和磁盘设备,在QEMU中实现相应的virtio后端驱动。
  3. 设备直通:设备直接分配在Intel平台上就是VT-d(Virtualization Technology For Directed I/O)特 性,一般在系统BIOS中可以看到相关的参数设置。Intel VT-d为虚拟机监控器提供了几个重要的能力:I/O设备分配、DMA重定向、中断重定向、中断投递等。
  4. 设备共享分配:如SR-IOV,SR-IOV这种特性可 以看作VT-d的一个特殊例子,所以SR-IOV除了设备本身要支持该特性,同时也需要硬件 平台打开VT-d特性支持。

以上四种方式的优缺点参考下图:

image-20211216111957779
image-20211216111957779

设备直接分配在Intel平台上就是VT-d(Virtualization Technology For Directed I/O)特 性,一般在系统BIOS中可以看到相关的参数设置。Intel VT-d为虚拟机监控器提供了几个重要的能力:I/O设备分配、DMA重定向、中断重定向、中断投递等。

Intel虚拟化技术小结

Intel硬件虚拟化技术大致分为如下3个类别(这个顺序也基本上是相应技术出现的时间先后顺序)。

  1. VT-x技术:是指Intel处理器中进行的一些虚拟化技术支持,包括CPU中引入的最 基础的VMX技术,使得KVM等硬件虚拟化基础的出现成为可能。同时也包括内存虚拟化 的硬件支持EPT、VPID等技术。
  2. VT-d技术:是指Intel的芯片组的虚拟化技术支持,通过Intel IOMMU可以实现对 设备直接分配的支持。
  3. VT-c技术:是指Intel的I/O设备相关的虚拟化技术支持,主要包含两个技术:一个是借助虚拟机设备队列(VMDq)最大限度提高I/O吞吐率,VMDq由Intel网卡中的专用硬件来完成;另一个是借助虚拟机直接互连(VMDc)大幅提升虚拟化性能,VMDc主要就是基于SR-IOV标准将单个Intel网卡产生多个VF设备,用来直接分配给客户机。

KVM架构

KVM虚拟化的核心主要由以下两个模块组成:

  1. KVM内核模块,它属于标准Linux内核的一部分,是一个专门提供虚拟化功能的 模块,主要负责CPU和内存的虚拟化,包括:客户机的创建、虚拟内存的分配、CPU执行 模式的切换、vCPU寄存器的访问、vCPU的执行。
  2. QEMU用户态工具,它是一个普通的Linux进程,为客户机提供设备模拟的功能, 包括模拟BIOS、PCI/PCIE总线、磁盘、网卡、显卡、声卡、键盘、鼠标等。同时它通过 ioctl系统调用与内核态的KVM模块进行交互

在KVM虚拟化架构下,每个客户机就是一个QEMU进程,在一个宿主机上 有多少个虚拟机就会有多少个QEMU进程;客户机中的每一个虚拟CPU对应QEMU进程中 的一个执行线程;一个宿主机中只有一个KVM内核模块,所有客户机都与这个内核模块进行交互。

image-20211216115551801
image-20211216115551801

KVM内核模块

image-20211216115712394
image-20211216115712394

KVM在内核中分为两个模块,如上图所示:

  1. KVM模块:处理器架构无关;
  2. KVM_intel模块:处理器架构相关;

KVM的主要作用:初始化CPU硬件,打开虚拟化模式,然后将虚拟机运行在虚拟化模式下;

KVM被内核加载的时候做了什么事:以KVM在Intel公司的CPU上运行为例,在被内核加载的时候, KVM模块会先初始化内部的数据结构;做好准备之后,KVM模块检测系统当前的CPU, 然后打开CPU控制寄存器CR4中的虚拟化模式开关,并通过执行VMXON指令将宿主操作系统(包括KVM模块本身)置于CPU执行模式的虚拟化模式中的根模式;最后,KVM模 块创建特殊设备文件/dev/kvm并等待来自用户空间的命令。接下来,虚拟机的创建和运 将是一个用户空间的应用程序(QEMU)和KVM模块相互配合的过程。

/dev/kvm字符设备

/dev/kvm这个设备可以被当作一个标准的字符设备,KVM模块与用户空间QEMU的通信接口主要是一系列针对这个特殊设备文件的loctl调用。

  1. 创建虚拟机

    “创建虚拟机”可以理解成KVM为了某个特定的虚拟客户机(用户空间程序创建并初始化)创建对应的内核数据结构。同时,KVM还会返回一个文件句柄来代表所创建的虚拟机。

  2. 虚拟机的管理

    针对该文件句柄的ioctl调用可以对虚拟机做相应的管理,比如创建用户空间虚拟地址和客户机物理地址及真实内存物理地址的映射关系,再比如创建多个可供运行的虚拟处理器(vCPU)。

  3. 执行vCPU

    可以通过ioctl系统调用对vCPU进行管理,其中最重要的就是“执行vCPU",通过它,用户空间准备 好的虚拟机在KVM模块的支持下,被置于虚拟化模式中的非根模式下,开始执行二进制 指令。在非根模式下,所有敏感的二进制指令都会被处理器捕捉到,处理器在保存现场之 后自动切换到根模式,由KVM决定如何进一步处理(要么由KVM模块直接处理,要么返 回用户空间交由用户空间程序处理)。

KVM还负责内存虚拟化,vCPU对设备的访问主要是通过I/O指令和MMIO,其中I/O指令会被处理器直接截获,MMIO会通过配置内存虚拟化来捕捉。但是,外设的模拟一般不由KVM模块负责。 一般来说,只有对性能要求比较高的虚拟设备才会由KVM内核模块来直接负责,比如虚 拟中断控制器和虚拟时钟,这样可以大量减少处理器模式切换的开销。而大部分的输入输出设备交给用户态程序QEMU来负责。

关于QEMU

  1. QEMU是一个纯软件实现的hypervisor,通过二进制翻译的方式实现对虚拟机CPU指令的模拟;
  2. QEMU本身是完全可以单纯作为一个hypervisor的
  3. 在KVM/QEMU的方式下,QEMU承担了设备模拟的工作,此时hypervisor是Linux内核中的KVM
  4. QEMU已经merge了KVM,现在的QEMU原生支持KVM,但是同样的,需要有硬件支持

其他的一些组件

在KVM虚拟化的软件栈中,毋庸置疑的是KVM内核模块与QEMU用户态程序是处于最核心的位置,有了它们就可通过qemu命令行操作实现完整的虚拟机功能。然而,在实际的云计算的虚拟化场景中,为了更高的性能或者管理的方便性,还有很多的软件可以作为KVM虚拟化实施中的组件, 这里简单介绍其中的几个。

  1. vhost-net

    vhost-net是Linux内核中的一个模块,它用于替代QEMU中的virtio-net用户态的virtio网 络的后端实现。使用 时,还支持网卡的多队列,整体来说会让网络性能得到较大

  2. Open vSwitch

    可以在KVM中实现软件定义网络(SDK);

  3. DPDK

    在 KVM架构中,为了达到非常高的网络处理能力(特别是小包处理能力),可以选择 DPDK与QEMU中的vhost-user结合起来使用。

  4. SPDK

    在KVM中需要非常高的存储I/O性能时,可以将QEMU与SPDK结合使用。

  5. Ceph

    在OpenStack的云平台解决方案中,Ceph是一个非常常用的存储后 端。

  6. libguestfs

    libguestfs不需要启动KVM客户机就可以对磁盘镜像进行管理,功能强大且非常灵活,是管理KVM磁盘镜像的首选工具。

参考文献

KVM实战:原理、进阶与性能调优