SPDK vhost介绍
目录
- 1. vhost技术的背景与动机
- Virtio 介绍
- virtio-blk数据路径为例
- 2. vhost技术的核心原理
- 2.1 vhost-kernel
- 2.2 vhost-user
- 举例
- 2.3 SPDK vhost
- vhost的优势
- IO请求处理
- 数据传输
- 控制链路调整
- 3. SPDK vhost的实现与配置
- 3.1 环境准备
- 3.2 启动SPDK vhost服务
- 3.3 创建虚拟块设备
- 3.4 创建vhost设备
- 3.5 配置QEMU
- 4. SPDK vhost的优势
- vhost的限制
- 虚拟机内存
- 磁盘限速
- 迁移
- 参考
vhost技术:加速虚拟化I/O的利器在虚拟化环境中,虚拟机(VM)的I/O性能一直是影响系统性能的关键因素之一。传统的I/O虚拟化方案往往存在性能瓶颈,尤其是在处理高负载的存储I/O时。为了突破这些限制,vhost技术应运而生。
1. vhost技术的背景与动机
在虚拟化环境中,虚拟机通过虚拟设备与宿主机的物理设备进行通信。传统的I/O虚拟化方案主要有以下几种:
- 纯软件模拟:通过软件完全模拟设备,性能较差,但兼容性好。
- 半虚拟化(Para-Virtualization):通过在虚拟机中安装特定的驱动程序(如virtio驱动),与宿主机的后端进行通信,性能优于纯软件模拟。
- 硬件虚拟化:如SR-IOV和VT-D,直接将物理设备或其虚拟功能(VF)分配给虚拟机,性能最高,但对硬件和操作系统支持要求较高。
然而,即使是半虚拟化的virtio方案,也存在一些性能瓶颈。例如,当虚拟机向宿主机提交I/O请求时,需要通过PCI配置空间通知宿主机,这会导致VM_EXIT事件,增加CPU上下文切换的开销。此外,数据在用户态和内核态之间的复制也会降低性能。
Virtio 介绍
Virtio 基于 Vring 的 I/O 通讯机制,相比 QEMU 的纯软件模拟,有效降低了 I/O 延迟,具有性能优势。
Virtio的引入,也开始让不同厂商的半虚拟化IO设备的实现方式趋于统一。
Virtio 由三部分组成:
- 前端是驱动层,位于 Guest 系统内部
- 中间是虚拟队列(virtqueue),负责数据传输和命令交互
- 后端设备层,用于具体处理 Guest 发送的请求。
virtio-blk数据路径为例
- 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;
- 存储引擎接收请求并进行 I/O 处理;
- 存储引擎发起对本地存储介质的 I/O;
- I/O 操作结束,通过上述逆过程返回至 Virtio 后端 Device,QEMU 会向模拟的 PCI 发送中断通知,从而 Guest 基于该中断完成整个 I/O 流程。
下图的讲解更加详细(基于SmartX ZBS),但内容是一致的:
数据流从用户态到内核态再到用户态。
2. vhost技术的核心原理
如前所述,Virtio 后端 Device 用于具体处理 Guest 的请求,负责 I/O 的响应,把 I/O 处理模块放在 QEMU 进程之外,并将其放到用户态或内核态的后端进程中,从而减少了上下文切换和数据拷贝的开销。
这种实现的方案称为 vhost。
vhost技术的核心在于优化虚拟机与宿主机之间的I/O通信路径。它通过以下几种方式实现性能提升:
2.1 vhost-kernel
vhost-kernel是vhost技术的早期实现,将I/O处理逻辑放到Linux内核中。它通过内核模块直接处理虚拟机的I/O请求,减少了用户态到内核态的上下文切换。然而,尽管vhost-kernel优化了数据处理路径,但虚拟机仍然需要通过PCI配置空间通知宿主机,这仍然会导致VM_EXIT事件。
2.2 vhost-user
vhost-user是vhost技术的另一种实现方式,将I/O处理逻辑完全放到用户态进程中。与vhost-kernel相比,vhost-user通过轮询机制检测I/O请求,避免了虚拟机更新PCI配置空间的需要,从而消除了VM_EXIT事件。此外,vhost-user还支持零拷贝技术,进一步减少了数据拷贝的开销。
举例
- 当 Guest 发起 I/O 操作后,存储软件通过 Polling 机制感知新的请求动作,从 virtqueue 获取数据;
- 存储引擎接收请求并进行 I/O 处理;
- 存储引擎发起对本地存储介质的 I/O;
- I/O 操作完成后,由 vhost device 发送 irqfd(eventfd)通知到 KVM;
- KVM 注入中断通知 Guest OS 完成 I/O。
下图的讲解更加详细(基于SmartX ZBS),但内容是一致的:
整个过程,绕开QEMU,存储可以直接处理IO请求。
2.3 SPDK vhost
SPDK是一个高性能的存储开发工具包,它通过用户态编程和轮询机制实现了高效的I/O处理。SPDK vhost是基于vhost-user技术的进一步优化,它结合了SPDK的高性能存储后端(如NVMe、malloc ramdisk等),提供了极致的I/O性能。
vhost的优势
IO请求处理
开启vhost之前的IO:Guest OS -> QEMU -> Storage -> QEMU -> KVM -> Guest OS
开启vhost之后的IO:Guest OS -> Storage -> KVM -> Guest OS
通过 vhost-user target 来直接处理 IO 请求,不再需要 QEMU 的参与,绕开了由 QEMU 处理 IO 请求的线程资源有限所造成的瓶颈
数据传输
未启用vhost。在原有的 IO 路径下,数据需要经过 iSCSI 协议的封装而后通过 TCP 完成 QEMU 和 Chunk 之间的传输,在这个过程中,有两个方面造成了数据写入的性能损耗:
- iSCSI over TCP 模式在本地网络协议栈传输存在性能衰减
- 使用 iSCSI 协议造成的封装开销
启用vhost,由于其共享内存,Storage和Guest OS直接共享数据,不依靠iSCSI传输数据。
控制链路调整
3. SPDK vhost的实现与配置
SPDK vhost支持多种虚拟化设备,包括vhost-scsi和vhost-blk。以下是一个典型的SPDK vhost配置和使用流程:
3.1 环境准备
安装SPDK:根据SPDK的官方文档,编译并安装SPDK。
配置hugepages:SPDK需要使用hugepages来分配大页内存,以减少内存碎片和提高性能。例如,可以使用以下命令分配4GiB的hugepages:
HUGEMEM=4096 scripts/setup.sh
3.2 启动SPDK vhost服务
启动SPDK vhost服务时,需要指定CPU核心和socket路径。例如,以下命令在CPU核心0和1上启动vhost服务,并将socket文件放在/var/tmp目录下:
build/bin/vhost -S /var/tmp -m 0x3
3.3 创建虚拟块设备
SPDK支持多种存储后端,包括NVMe、malloc ramdisk和Linux AIO等。以下命令创建一个64MB的malloc ramdisk块设备:
scripts/rpc.py bdev_malloc_create 64 512 -b Malloc0
3.4 创建vhost设备
接下来,创建一个vhost-scsi控制器,并将其与malloc块设备绑定:
scripts/rpc.py vhost_create_scsi_controller --cpumask 0x1 vhost.0
scripts/rpc.py vhost_scsi_controller_add_target vhost.0 0 Malloc0
3.5 配置QEMU
最后,启动虚拟机并连接到SPDK vhost设备。以下是一个示例QEMU命令:
qemu-system-x86_64 \
--enable-kvm \
-cpu host -smp 2 \
-m 1G -object memory-backend-file,id=mem0,size=1G,mem-path=/dev/hugepages,share=on -numa node,memdev=mem0 \
-drive file=guest_os_image.qcow2,if=none,id=disk \
-device ide-hd,drive=disk,bootindex=0 \
-chardev socket,id=spdk_vhost_scsi0,path=/var/tmp/vhost.0 \
-device vhost-user-scsi-pci,id=scsi0,chardev=spdk_vhost_scsi0,num_queues=2
4. SPDK vhost的优势
SPDK vhost通过以下方式显著提升了虚拟化环境中的I/O性能:
零拷贝技术:通过内存共享和轮询机制,消除了数据在用户态和内核态之间的拷贝。
减少上下文切换:通过轮询机制避免了虚拟机更新PCI配置空间的需要,减少了VM_EXIT事件。
高性能存储后端:结合SPDK的高性能存储后端(如NVMe),提供了极致的I/O性能。
灵活的配置:支持多种存储后端和虚拟化设备,适用于不同的应用场景。
vhost的限制
虚拟机内存
vhost-user 的共享内存机制对 VM 的运行有两个要求:
- Huge page(大页内存),提供给 VM 的内存不再是普通的内存,而是 Huge page 模式;
- 完全预留,VM 使用的内存在运行时需要全部分配并始终独占,不支持 VM 内存超分。
磁盘限速
一开始的QOS基于QEMU,由于启用后不再经过qemu,所以仅支持存储端的磁盘限速
迁移
不支持 开启与没开启的集群之间 热迁移
参考
SPDK: vhost Target
SPDK Vhost-user 如何帮助超融合架构实现 I/O 存储性能提升