在 QEMU/KVM 中,客户机可以使用的设备大致可分为三类:
1. 模拟设备:完全由 QEMU 纯软件模拟的设备。
2. Virtio 设备:实现 VIRTIO API 的半虚拟化设备。
3. PCI 设备直接分配 (PCI device assignment) 。
1. 全虚拟化 I/O 设备
KVM 在 IO 虚拟化方面,传统或者默认的方式是使用 QEMU 纯软件的方式来模拟 I/O 设备,包括键盘、鼠标、显示器,硬盘 和 网卡 等。模拟设备可能会使用物理的设备,或者使用纯软件来模拟。模拟设备只存在于软件中。
1.1 原理
过程:
注意:当客户机通过DMA (Direct Memory Access)访问大块I/O时,QEMU 模拟程序将不会把结果放进共享页中,而是通过内存映射的方式将结果直接写到客户机的内存中共,然后通知KVM模块告诉客户机DMA操作已经完成。
这种方式的优点是可以模拟出各种各样的硬件设备;其缺点是每次 I/O 操作的路径比较长,需要多次上下文切换,也需要多次数据复制,所以性能较差。
1.2 QEMU 模拟网卡的实现Qemu 纯软件的方式来模拟I/O设备,其中包括经常使用的网卡设备。Guest OS启动命令中没有传入的网络配置时,QEMU默认分配 rtl8139 类型的虚拟网卡类型,使用的是默认用户配置模式,这时候由于没有具体的网络模式的配置,Guest的网络功能是有限的。 全虚拟化情况下,KVM虚机可以选择的网络模式包括:
分别使用的 qemu-kvm 参数为:
网桥模式是目前比较简单,也是用的比较多的模式,下图是网桥模式下的 VM的收发包的流程。 如图中所示,红色箭头表示数据报文的入方向,步骤:
(引用自 http://luoye.me/2014/07/17/netdev-virtual-1/) 1.3 RedHat Linux 6 中提供的模拟设备
注意:RedHat Linux KVM 不支持 SCSI 模拟。
在不显式指定使用其它类型设备的情况下,KVM 虚机将使用这些默认的虚拟设备。比如上面描述的默认情况下 KVM 虚机默认使用rtl8139网卡。比如,在 RedHat Linxu 6.5 主机上启动KVM RedHat Linux 6.4 虚机后,登录虚机,查看 pci 设备,可以看到这些模拟设备:
当使用 “-net nic,model=e1000” 指定网卡model 为 e1000 时,
1.4 qemu-kvm 关于磁盘设备和网络的主要选项
对于网卡来说,你可以使用 modle 参数指定虚拟网络的类型。 RedHat Linux 6 所支持的虚拟网络类型有: [root@rh65 isoimages]# kvm -net nic,model=? qemu: Supported NIC models: ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio 2. 准虚拟化 (Para-virtualizaiton) I/O 驱动 virtio
在 KVM 中可以使用准虚拟化驱动来提供客户机的I/O 性能。目前 KVM 采用的的是 virtio 这个 Linux 上的设备驱动标准框架,它提供了一种 Host 与 Guest 交互的 IO 框架。
2.1 virtio 的架构
KVM/QEMU 的 vitio 实现采用在 Guest OS 内核中安装前端驱动 (Front-end driver)和在 QEMU 中实现后端驱动(Back-end)的方式。前后端驱动通过 vring 直接通信,这就绕过了经过 KVM 内核模块的过程,达到提高 I/O 性能的目的。
纯软件模拟的设备和 Virtio 设备的区别:virtio 省去了纯模拟模式下的异常捕获环节,Guest OS 可以和 QEMU 的 I/O 模块直接通信。
使用 Virtio 的完整虚机 I/O流程:
Host 数据发到 Guest:
1. KVM 通过中断的方式通知 QEMU 去获取数据,放到 virtio queue 中
2. KVM 再通知 Guest 去 virtio queue 中取数据。
2.2 Virtio 在 Linux 中的实现
Virtio 是在半虚拟化管理程序中的一组通用模拟设备的抽象。这种设计允许管理程序通过一个应用编程接口 (API)对外提供一组通用模拟设备。通过使用半虚拟化管理程序,客户机实现一套通用的接口,来配合后面的一套后端设备模拟。后端驱动不必是通用的,只要它们实现了前端所需的行为。因此,Virtio 是一个在 Hypervisor 之上的抽象API接口,让客户机知道自己运行在虚拟化环境中,进而根据 virtio 标准与 Hypervisor 协作,从而客户机达到更好的性能。
Linux 内核中实现的五个前端驱动程序:
Guest OS 中,在不使用 virtio 设备的时候,这些驱动不会被加载。只有在使用某个 virtio 设备的时候,对应的驱动才会被加载。每个前端驱动器具有在管理程序中的相应的后端的驱动程序。
以 virtio-net 为例,解释其原理:
(1)virtio-net 的原理:
它使得:
(2)virtio-net 的流程:
总结 Virtio 的优缺点:
2.3 使用 virtio 设备 (以 virtio-net 为例)使用 virtio 类型的设备比较简单。较新的 Linux 版本上都已经安装好了 virtio 驱动,而 Windows 的驱动需要自己下载安装。 (1)检查主机上是否支持 virtio 类型的网卡设备
[root@rh65 isoimages]# kvm -net nic,model=?
qemu: Supported NIC models: ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio
(2)指定网卡设备model 为 virtio,启动虚机
(3)通过 vncviewer 登录虚机,能看到被加载了的 virtio-net 需要的内核模块
(4)查看 pci 设备
其它 virtio 类型的设备的使用方式类似 virtio-net。 2.4 vhost-net (kernel-level virtio server)前面提到 virtio 在宿主机中的后端处理程序(backend)一般是由用户空间的QEMU提供的,然而如果对于网络 I/O 请求的后端处理能够在在内核空间来完成,则效率会更高,会提高网络吞吐量和减少网络延迟。在比较新的内核中有一个叫做 “vhost-net” 的驱动模块,它是作为一个内核级别的后端处理程序,将virtio-net的后端处理任务放到内核空间中执行,减少内核空间到用户空间的切换,从而提高效率。 根据 KVM 官网的这篇文章,vhost-net 能提供更低的延迟(latency)(比 e1000 虚拟网卡低 10%),和更高的吞吐量(throughput)(8倍于普通 virtio,大概 7~8 Gigabits/sec )。 vhost-net 与 virtio-net 的比较:
vhost-net 的要求:
qemu-kvm 命令的 -net tap 有几个选项和 vhost-net 相关的: -net tap,[,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostforce=on|off]
vhost-net 的使用实例: (1)确保主机上 vhost-net 内核模块被加载了
(2)启动一个虚拟机,在客户机中使用 -net 定义一个 virtio-net 网卡,在主机端使用 -netdev 启动 vhost
(3)在虚拟机端,看到 virtio 网卡使用的 TAP 设备为 tap0。
(4)在宿主机中看 vhost-net 被加载和使用了,以及 Linux 桥 br0,它连接物理网卡 eth1 和 客户机使用的 TAP 设备 tap0
一般来说,使用 vhost-net 作为后端处理驱动可以提高网络的性能。不过,对于一些网络负载类型使用 vhost-net 作为后端,却可能使其性能不升反降。特别是从宿主机到其中的客户机之间的UDP流量,如果客户机处理接受数据的速度比宿主机发送的速度要慢,这时就容易出现性能下降。在这种情况下,使用vhost-net将会是UDP socket的接受缓冲区更快地溢出,从而导致更多的数据包丢失。故这种情况下,不使用vhost-net,让传输速度稍微慢一点,反而会提高整体的性能。 使用 qemu-kvm 命令行,加上“vhost=off”(或没有vhost选项)就会不使用vhost-net,而在使用libvirt时,需要对客户机的配置的XML文件中的网络配置部分进行如下的配置,指定后端驱动的名称为“qemu”(而不是“vhost”)。 <interface type=”network”> … <model type=”virtio”/> <driver name=”qemu”/> … </interface> 2.6 virtio-balloon另一个比较特殊的 virtio 设备是 virtio-balloon。通常来说,要改变客户机所占用的宿主机内存,要先关闭客户机,修改启动时的内存配置,然后重启客户机才可以实现。而 内存的 ballooning (气球)技术可以在客户机运行时动态地调整它所占用的宿主机内存资源,而不需要关闭客户机。该技术能够:
目前很多的VMM,包括 KVM, Xen,VMware 等都对 ballooning 技术提供支持。其中,KVM 中的 Ballooning 是通过宿主机和客户机协同来实现的,在宿主机中应该使用 2.6.27 及以上版本的 Linux内核(包括KVM模块),使用较新的 qemu-kvm(如0.13版本以上),在客户机中也使用 2.6.27 及以上内核且将“CONFIG_VIRTIO_BALLOON”配置为模块或编译到内核。在很多Linux发行版中都已经配置有“CONFIG_VIRTIO_BALLOON=m”,所以用较新的Linux作为客户机系统,一般不需要额外配置virtio_balloon驱动,使用默认内核配置即可。
原理:
优势和不足:
在QEMU monitor中,提供了两个命令查看和设置客户机内存的大小。
(1)启动一个虚机,内存为 2048M,启用 virtio-balloon
(2)通过 vncviewer 进入虚机,查看 pci 设备
(3)看看内存情况,共 2G 内存
(4)进入 QEMU Monitor,调整 balloon 内存为 500M
(5)回到虚机,查看内存,变为 500 M
2.7 RedHat 的 多队列 Virtio (multi-queue)
目前的高端服务器都有多个处理器,虚拟使用的虚拟CPU数目也不断增加。默认的 virtio-net 不能并行地传送或者接收网络包,因为 virtio_net 只有一个TX 和 RX 队列。而多队列 virtio-net 提供了一个随着虚机的虚拟CPU增加而增强网络性能的方法,通过使得 virtio 可以同时使用多个 virt-queue 队列。
它在以下情况下具有明显优势:
注意:对队列 virtio-net 对流入的网络流工作得非常好,但是对外发的数据流偶尔会降低性能。打开对队列 virtio 会增加中的吞吐量,这相应地会增加CPU的负担。 在实际的生产环境中需要做必须的测试后才确定是否使用。
在 RedHat 中,要使用多队列 virtio-net,在虚机的 XML 文件中增加如下配置:
然后在主机上运行下面的命令:
ethtool -L eth0 combined M ( 1 <= M <= N)
2.8 Windows 客户机的 virtio 前端驱动
Windows 客户机下的 virtio 前端驱动必须下载后手工安装。 RedHat Linux 这篇文章 说明了在 Windows 客户机内安装virtio 驱动的方法。
参考文档:
(责任编辑:IT) |