目录
全虚拟化
硬件辅助的IO虚拟化
Passthrough
SR-IOV
virtio
QEMU作为后端处理IO请求
vhost-kernel
vhost-user
全虚拟化
对于全虚拟化有两种思路。一种是把模拟设备放在VMM(VMware),另一种是放在user space,如qemu(KVM)。模拟设备只是用软件实现了各种接口共Guest OS使用,hypervisor监测Guest OS对于虚拟设备的操作,然后将其转化到实际的物理设备。实现了一个物理设备在多个OS之间共享的目的。左侧图显示的是VMware的solution(不是所有的模拟设备都放在vmm,还有一些是放在vmx),右边是KVM。
通过设备模拟,虽然可以实现共享,但是由于加了一层,会有一些性能损失,对于高吞吐量的workload而言就不能满足了。
硬件辅助的IO虚拟化
需要CPU支持VT-D或者IOMMU。
Passthrough
Passthru方式将物理设备直接映射到Guest OS的地址空间,可以达到近乎裸机的性能,但是它也失去了虚拟机的一些关键特性,如live migration。同时一个物理设备只能被一个VM使用。
SR-IOV
目前许多PCI设备都支持SR-IOV(Single Root I/O Virtualization),把一个物理设备虚拟出许多虚拟设备(PF -> VFs)。也就是说末端的PCI device 原生支持虚拟化。VFs共享PF的资源。每个/几个 VFs可以分配给VM使用。效果类似于passthru。
PF:全功能的PCIe功能,可以想普通PCIe设备一样被使用。
VF:与物理功能关联的一种轻量级PCIe功能,VF之间共享PF的资源。
virtio
先回顾下KVM IO虚拟化的发展历程
1. QEMU纯软件模拟
qemu模拟IO设备给虚拟机使用,虚拟机内OS不用做任何修改,直接使用,缺点是性能较低,需要频繁vm-exit. KVM截获IO请求,将具体信息保存在IO sharing page,然后通知QEMU进行处理。待QEMU处理完成,将结果同样保存在IO sharing page,通知KVM,然后其把结果返回给虚机
2. virtio半虚拟化
在虚拟机中安装virtio driver作为前端,virtio后端处理前端发送的读写请求,可减少vm-exit与内存拷贝,virtio基于vring的通讯机制,由QEMU模拟PCIe设备,供虚拟机使用,其遵循PCI规范,具有配置空间、中断配置等功能。
QEMU作为后端处理IO请求
- Guest 发起 I/O 操作,Guest 内核Virtio驱动写 PCI 配置空间, 触发 VM EXIT,返回到 Host KVM 中(通知 KVM)
- QEMU 的 vCPU 线程从 KVM 内核态回到 QEMU,让 QEMU Device 来处理 Virtio Vring 请求
- QEMU 通过 iSCSI Drive 发起存储连接(iscsi over tcp to localhost)
- 通过 Socket 将请求连接到存储进程提供的 iSCSI Target,存储服务器处理IO请求
- I/O 操作结束,通过上述逆过程返回至 Virtio 后端 Device,QEMU会向模拟的PCI发送中断通知,从而Guest基于该中断完成整个 I/O 流程
vhost-kernel
IO处理模块放在QEMU进程外,统称为vhost,这里先介绍vhost-kernel。
由于上面的virtio流程中,存在多次user space与kernel space的切换和多次内存拷贝(例如 guest 发包给外部网络,首先,guest 需要切换到 host kernel,然后 host kernel 会切换到 qemu 来处理 guest 的请求, Hypervisor 通过系统调用将数据包发送到外部网络后,会切换回 host kernel , 最后再切换回 guest。这样漫长的路径无疑会带来性能上的损失),所以可以在kernel中完成虚机的IO请求(vhost-net.ko),数据面由kernel接管,但是控制面仍然由QEMU实现。具体方法是在初始化vhost时,创建一个叫vhost-$PID的kthread,它与Guest间通过virtqueue交互IO信息,vhost将部分virtio驱动从用户态迁移到内核态,减少了用户态/内核态间的切换(只需一次)。
vhost-user
IO处理模块放在用户态,1. 后端采用轮询方式减少vm-exit所带来的开销。2.用户态进程内存共享
依赖DPDK,在用户态操作网卡,直接收发数据
- 当 Guest 发起 I/O 操作后,存储软件通过 Polling 机制感知新的请求动作,从 virtqueue 获取数据;
- 后端处理IO请求
- I/O 操作完成后,由 vhost device 发送 irqfd(eventfd)通知到 KVM;
- KVM 注入中断通知 Guest OS 完成 I/O
前端与后端通过socket传递控制信息
不同virtio版本
virtio现在分为0.95/1.0/1.1三个版本,其中0.95只支持单队列,1.0/1.1开始支持多队列。
此为1.0版本驱动:
0.95版本要使用老版本Linux,例如centos6.8x86_64
新版本设备可以兼容旧驱动,这里可强制使用0.95驱动