kvm热迁移

第一部分 SR-IOV简介html

https://cloud.tencent.com/developer/article/1087112前端

1.1 SR-IOV简介node

SR-IOV(PCI-SIG Single Root I/O Virtualization and Sharing)是PCI-SIG组织发布的规范。linux

设计PCI-SIG SR-IOV 规范的目的是:经过为虚拟机提供独立的内存地址、中断和DMA流而避免VMM的介入。SR-IOV容许一个PCI设备提供多个VFs。VMM将一个或者多个 VF 分配给一个虚机。一个VF同时只能被分配一个虚机。而虚拟机感知不到这个网卡是被VF的仍是普通的物理网卡。后端

1.2 SR-IOV引入了两个PCIefunction types安全

PFs:包括管理SR-IOV功能在内的全部PCIe function。服务器

VFs:一部分轻量级的PCIe function,只能进行必要的数据操做和配置。网络

1.3 R-IOV工做流程中有三个角色架构

1.PCIe的SR-IOV机制:提供独立可配置的多个VFs,每个VFs具备独立的PCIe配置空间。app

2.VMM:则把VFs分配给虚拟机。

3.VT-x和VT-d:经过硬件辅助技术提供和虚拟机之间的直接DMA数据映射传输,跳过VMM的干预。

1.4 SR-IOV原理

下面一幅图描述了SR-IOV的原理(来自intel《PCI-SIG SR-IOV Prime》):

1.5 SR-IOV的优缺点

SR-IOV相对与软件模拟IO虚拟化的优势:

1.下降了IO延迟和对CPU的占用,得到了接近原生的IO性能,由于虚拟机直接使用VFs,没有了VMM的陷入处理。

2.数据更加安全,由于每一个VF属于一个IOMMU Group,共享IOMMU Group的设备不能分配给不一样的虚拟机,而每一个IOMMU Group又有独立的内存。

SR-IOV相对与Device assignment的优势:

没有了一个PCI设备只能给一个虚拟机的尴尬,SR-IOV下多个虚拟机可经过独占VFs的方式共享一个PCI设备。

SR-IOV的缺点:

使用了VFs的虚拟机不能在线迁移

 

第二部分 KVM热迁移原理

https://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm1/index.html 介绍原理

https://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm2/index.html 实验(操做qemu执行热迁移)

https://developers.redhat.com/blog/2015/03/24/live-migrating-qemu-kvm-virtual-machines/

KVM热迁移大致流程和内存降速问题

2.1 概述

迁移的前面阶段,服务在源主机运行,当迁移进行到必定阶段,目的主机已经具有了运行系统的必须资源,通过一个很是短暂的切换,源主机将控制权转移到目的主机,服务在目的主机上继续运行。

对于 VM 的内存状态的迁移,XEN 和 KVM 都采用了主流的的预拷贝(pre-copy)的策略。迁移开始以后,源主机 VM 仍在运行,目的主机 VM 还没有启动。迁移经过一个循环,将源主机 VM 的内存数据发送至目的主机 VM。循环第一轮发送全部内存页数据,接下来的每一轮循环发送上一轮预拷贝过程当中被 VM 写过的脏页内存 dirty pages。直到时机成熟,预拷贝循环结束,进入停机拷贝阶段,源主机被挂起,再也不有内存更新。最后一轮循环中的脏页被传输至目的主机 VM。

预拷贝机制极大的减小了停机拷贝阶段须要传输的内存数据量,从而将停机时间大大缩小。【意思是预拷贝不影响vm的在线运行,减小了停机时间】

最右边部分的图表是QEMU状态,整个状态不涉及迁移过程。可是在迁移开始以前将这个状态设置正确很重要。在源主机和目的主机上的QEMU设置必须相同,这是经过在两个主机上使用一条类似的QEMU命令行来实现的。因为QEMU命令行的多种选择很是难以搞定,咱们使用Libvirt替咱们选择正确的。Libvirt能够确保QEMU两边程序的迁移设置正确性。

在线迁移分3个阶段:

第一个阶段:将全部RAM都标记脏

第二个阶段:持续不断发送脏RAM,当达到一些低水印或者条件时中止

第三个阶段:中止运行客户机,将剩余脏RAM,设备状态转移过去,在目标主机QEMU上启动虚拟机

在第二阶段代码,咱们会在每一个迭代来检查有多少页面被客户机标记脏。会检查花费多长时间来转换一个页面,以便来设定一个预估的网络带宽。在这个预估带宽和当前迭代的脏页面数量,咱们能够计算出花费多久来转化剩余页面。若是在可接受或者设置的停机时间限制内,咱们过渡到第三阶段是没有问题的。不然咱们会继续停留在第二阶段。

QEMU中还有更多的与迁移有关的代码:有些代码是用来发送/接受迁移数据:TCP或者UNIX包,本地文件说明符,或者RDMA。也有exec功能,来自QEMU的数据,在被发送到目的地前,会被传输到其余进程。这对于传出数据压缩,加密都颇有用。在目的端,也须要进行解压缩或者解加密进程。对于UNIX包,fd或者exec-based协议,须要更高层的程序来管理两端的迁移。Libvirt就是这个程序,咱们能够依赖libvirt的能力来控制这个迁移。

2.2 如何判断”时机成熟“

对于更新速度很是快的内存部分,每次循环过程都会变脏,须要重复 pre-copy,同时也致使循环次数很是多,迁移的时间变长。针对这种状况,KVM 虚拟机创建了三个原则:集中原则,一个循环内的 dirty pages 小于等于 50;不扩散原则, 一个循环内传输的 dirty pages 少于新产生的;有限循环原则,循环次数必须少于 30。在实现上,就是采起了如下措施:

  • 有限循环:循环次数和效果受到控制,对每轮 pre-copy 的效果进行计算,若 pre-copy 对于减小不一致内存数量的效果不显著,或者循环次数超过了上限,循环将停止,进入停机拷贝阶段。
  • 在被迁移 VM 的内核设置一个内存访问的监控模块。在内存 pre-copy 过程当中,VM 的一个进程在一个被调度运行的期间,被限制最多执行 40 次内存写操做。这个措施直接限制了 pre-copy 过程当中内存变脏的速度,其代价是对 VM 上的进程运行进行了必定的限制。【这个模块是要改guest OS吗?】

2.3 迁移过程详解

(1)系统验证目标服务器的存储器和网络设置是否正确,并预保留目标服务器虚拟机的资源。

图 1. 源服务器和目标服务器简图

 

(2)当虚拟机还在源服务器上运转时,第一个循环内将所有内存镜像复制到目标服务器上。在这个过程当中,KVM 依然会监视内存的任何变化。

图 2. 内存镜像复制示意图

 

(3)之后的循环中,检查上一个循环中内存是否发生了变化。 假如发生了变化,那么 VMM 会将发生变化的内存页即 dirty pages 从新复制到目标服务器中,并覆盖掉先前的内存页。在这个阶段,VMM 依然会继续监视内存的变化状况。

图 3. 进行有变化的内存复制

 

(4)VMM 会持续这样的内存复制循环。随着循环次数的增长,所须要复制的 dirty pages 就会明显减小,而复制所耗费的时间就会逐渐变短,那么内存就有可能没有足够的时间发生变化。最后,当源服务器与目标服务器之间的差别达到必定标准时,内存复制操做才会结束,同时暂停源系统。

图 4. 所需复制的数据在减小

 

(5)在源系统和目标系统都停机的状况下,将最后一个循环的 dirty-pages 和源系统设备的工做状态复制到目标服务器。

图 5. 状态信息的复制

 

(6)而后,将存储从源系统上解锁,并锁定在目标系统上。启动目标服务器,并与存储资源和网络资源相链接。

图 6. 中止源服务器,启动目标服务器

 

 

第三部分 passthrough与SR-IOV区别、vhost和vhost-user等

https://www.cnblogs.com/sammyliu/p/4548194.html

http://virtual.51cto.com/art/201801/563894.htm

https://blog.csdn.net/qq_15437629/article/details/77899905

http://blog.vmsplice.net/2011/09/qemu-internals-vhost-architecture.html

https://spdk.io/doc/vhost_processing.html

3.1 Passthrough

设备直接分配 (Device assignment)也称为 Device Pass-Through。

先简单看看PCI 和 PCI-E 的区别(AMD CPU):

(简单点看,PCI 卡的性能没有 PCI-E 高,由于 PCI-E 是直接连在 IOMMU 上,而 PCI 卡是连在一个 IO Hub 上。)

IOMMU = Input/Output Memory Management Unit

主要的 PCI 设备类型:

  • Network cards (wired or wireless)
  • SCSI adapters
  • Bus controllers: USB, PCMCIA, I2C, FireWire, IDE
  • Graphics and video cards
  • Sound cards
这种方式,容许将宿主机中的物理 PCI 设备直接分配给客户机使用。较新的x86平台已经支持这种类型,Intel 定义的 I/O 虚拟化技术成为 VT-d,AMD 的称为 AMD-V。KVM 支持客户机以独占方式访问这个宿主机的 PCI/PCI-E 设备。经过硬件支持的 VT-d 技术将设备分给客户机后,在客户机看来,设备是物理上链接在PCI或者PCI-E总线上的,客户机对该设备的I/O交互操做和实际的物理设备操做彻底同样,不须要或者不多须要 KVM 的参与。运行在 VT-d 平台上的 QEMU/KVM,能够分配网卡、磁盘控制器、USB控制器、VGA 显卡等设备供客户机直接使用。
  • 好处:在执行 I/O 操做时大量减小甚至避免 VM-Exit 陷入到 Hypervisor 中,极大地提升了性能,能够达到几乎和原生系统同样的性能。VT-d 克服了 virtio 兼容性很差和 CPU 使用频率较高的问题。
  • 不足:(1)一台服务器主板上的空间比较有限,所以容许添加的 PCI 和 PCI-E 设备是有限的。大量使用 VT-d 独立分配设备给客户机,让硬件设备数量增长,这会增长硬件投资成本。(2)对于使用 VT-d 直接分配了设备的客户机,其动态迁移功能将受限,不过也可使用热插拔或者libvirt 工具等方式来缓解这个问题。
  • 不足的解决方案:(1)在一台物理宿主机上,仅少数 I/O 如网络性能要求较高的客户机使用 VT-d直接分配设备,其余的使用纯模拟或者 virtio 已达到多个客户机共享同一个设备的目的 (2)对于网络I/O的解决办法,能够选择 SR-IOV 是一个网卡产生多个独立的虚拟网卡,将每一个虚拟网卡分配个一个客户机使用。
几乎全部的 PCI 和 PCI-E 设备都支持直接分配,除了显卡之外(显卡的特殊性 在这里)。PCI Pass-through 须要硬件平台 Intel VT-d 或者 AMD IOMMU 的支持。这些特性必须在 BIOS 中被启用。Red Hat Enterprise Linux 6.0 及以上版本支持热插拔的 PCI 设备直接分配到虚拟机。
网卡直接分配:

硬盘直接分配:

  • 通常 SATA 或者 SAS 等类型的硬盘的控制器都是直接接入到 PCI 或者  PCI-E 总线的,因此也能够将硬盘做为普通的PCI设备直接分配个客户机。须要注意的是,当分配硬盘时,实际上将其控制器做为一个总体分配到客户机中,所以须要在硬件平台上至少有另两个或者多个SATA或者 SAS控制器。 

3.2 Passthrough分配示例:

准备工做:

(1)在 BIOS 中打开 Intel VT-d 

(2)在 Linux 内核中启用 PCI Pass-through

添加 intel_iommu=on 到 /boot/grub/grub.conf 文件中。(在个人 RedHat Linux 6上,该文件是 /boot/grub.conf)

(3)重启系统,使得配置生效

实际分配:

(1)使用 lspci -nn 命令找到待分配的 PCI 设备。这里以一个 FC 卡为例:

使用 lspci 命令获得的 PCI 数字的含义,之后使用 libvirt API 分配设备时会用到:

(2)使用 virsh nodedev-list 命令找到该设备的 PCI 编号

(3)将设备从主机上解除

(4)使用 virt-manager 将设备直接分配给一个启动了的虚拟机

3.3 各类设备虚拟化方式的比较【注意:什么是vhost???

3.4 IO设备的虚拟化方式

3.4.1 全虚拟化下vm的IO路径

(1)当虚拟机进行I/O操做时,根据《也谈Intel的cpu虚拟化》咱们知道,虚拟机经过VM exit将cpu控制权返回给VMM,从而陷入到root模式下的ring0内的VMM,进行”陷入模拟“。

(2)将本次I/O请求的信息存放到IO共享页,QEMU从IO共享页读取信息后由硬件模拟代码来模拟出本次的IO操做,并调用内核中的硬件驱动把IO请求发送到物理硬件,完成以后将结果放回到IO共享页。

(3)KVM模块中的捕获代码读取IO共享页中的结果,把结果返回到guest。

(4)经过VM entry,guest再次得到cpu控制权,根据IO返回的结果进行处理。

         说明:VMM和guest的IO信息共享不光IO共享页一种,还可使用DMA。QEMU不把IO结果放到IO共享页中,而是经过DMA将结果直接写到guest的内存中去,而后经过KVM模块告诉客户机DMA操做已经完成。

 

3.4.2 半虚拟化virtio

The purpose of virtio and [virtio] specification is that virtual environments
and guests should have a straightforward, efficient, standard and extensible
mechanism for virtual devices, rather than boutique per-environment or per-OS
mechanisms.

guest和host使用使用virtio先后端的技术减小了guest IO时的VM Exit(guest和host的上下文切换)而且使guest和host能并行处理IO来提升throughput和减小latency。可是IO的路径并无比全虚拟化技术减小。下面是virtio的IO路径:

guest在IO请求时,首先guest须要切换到host kernel,而后host kernel会切换到hyperisor来处理guest的请求,hypervisor经过系统调用将数据包发送到外部网络后切换回host kernel,而后再切换回guest。这个长IO路径和全虚拟化时相同的,只是减小了VM exit和VM entry。

IBM在2005年提出了virtio, 虚拟机中的半虚拟化前端驱动和主机上的后端服务简单的使用virtqueue共享队列交换数据,大幅的减小了e1000模拟时复杂的io操做,从而能够较大程度的提高虚拟网络性能。

guest使用virtio driver将请求发送给virtio-backend。

图中描述了virtio的io路径: guest发出中断信号退出kvm,从kvm退出到用户空间的qemu进程。而后由qemu开始对tap设备进行读写。 能够看到这里从用户态进入内核,再从内核切换到用户态,进行了2次切换。

virtio的io路径:guest设置好tx→kick host→guest陷出到kvm→kvm从内核切换到用户态的qemu进程→qemu将tx数据投递到tap设备

3.4.3 vhost和vhost-user

为了解决virio的IO路径太长的问题,vhost产生了。它是位于host kernel的一个模块,用于和guest直接通讯,因此数据交换就在guest和host kernel间进行,减小了上下文的切换。

vhost相对与virto架构,把virtio驱动后端驱动从用户态放到了内核态中(vhost的内核模块充当virtiO后端驱动),在内核中加入了vhost-net.ko模块,使得对网络数据能够在内核态获得处理。

guest发出中断信号退出kvm,kvm直接和vhost-net.ko通讯,而后由vhost-net.ko访问tap设备。 这样网络数据只须要通过从用户态到内核态的一次切换,就能够完成数据的传输。大大提升了虚拟网卡的性能。 

路径:guest设置好tx→kick host→guest陷出到kvm→vhost-net将tx数据投递到tap设备

vhost-user和vhost相似,只是使用一个用户态进程vhost-user代替了内核中的vhost模块。

[Vhost-user protocol] is aiming to complement the ioctl interface used to
control the vhost implementation in the Linux kernel. It implements the control
plane needed to establish virtqueue sharing with a user space process on the
same host. It uses communication over a Unix domain socket to share file
descriptors in the ancillary data of the message.
The protocol defines 2 sides of the communication, master and slave. Master is
the application that shares its virtqueues, in our case QEMU. Slave is the
consumer of the virtqueues.
In the current implementation QEMU is the Master, and the Slave is intended to
be a software Ethernet switch running in user space, such as Snabbswitch.
Master and slave can be either a client (i.e. connecting) or server (listening)
in the socket communication.

vhost-user进程和Guset之间时经过共享内存的方式进行数据操做。vhost-user相对与vhost架构,把virtio驱动后端驱动从内核态又放回到了用户态中(vhost-user进程充当virtiO后端驱动)。

它将网络数据放入用户态处理将能够获得更灵活的形式:

路径:guest设置好tx→kick host→guest陷出到kvm→kvm将通知vhost-backend→vhost-backend将tx数据直接发送到nic设备

vhost-backend从原来kernel中的vhost-net 变成了用户空间的snabbswitch,snabbswitch直接接管物理网卡的驱动,从而直接控制网络信息的输入输出。snabbswitch主要使用了下面的技术来提升性能:

  1. 采用了大页来做为host和vm之间通讯的内存空间
  2. 用户态操做网卡,使用相似于netmap的zero copy技术来加速对物理设备的访问
  3. 使用numa技术,加快中断响应速率

值得一提的是使用snabbswitch后,不用再使用原来的tap设备模拟的网卡。

使用vhost-user技术,从虚拟机到host上实现了数据的zero copy(经过大页共享),host到nic的zero copy(snabbswitch实现的驱动),能进一步加快数据的传输。

DPDK即是一个在用户态能够直接操做物理网卡的库函数,它和vhost-user结合即可以实现相似于snabb switch同样性能强劲的用户态交换机了

【有了vhost-user,DPDK和SPDK(storage performance xx)等加速框架就得以实现了】

相关文章
相关标签/搜索