【SPDK 用户态存储】vhost / virtio 边界:对 VMM 提供块后端的位置

💡 原文中文,约7700字,阅读约需19分钟。
📝

内容提要

本文介绍SPDK作为虚拟机块设备后端(vhost/virtio)的机制。SPDK通过vhost-user协议(Unix套接字+共享内存)在用户态轮询队列,替代内核vhost,减少VMEXIT。文章对比vhost-scsi与vhost-blk的差异,强调共享内存(hugepage)、NUMA绑核等硬前提,并给出排障要点,区分与NVMe-oF及内核vhost的定位。

🔎

延伸解读

vhost-scsi 与 vhost-blk 的选型差异

vhost-scsi 支持热挂/热摘 bdev,适合需要运行时换盘的场景;vhost-blk 语义更薄,但物理拔掉 NVMe 时无优雅 hot-detach,可能导致 guest 日志被错误灌满。选型应基于运维习惯和换盘窗口的失败语义,而非口味。

共享内存与 NUMA 绑核是硬前提

vhost-user 要求 guest 内存对 SPDK 进程可见,必须使用 share=on 的 hugepage 内存后端,并确保 SPDK 与 VM 在同一 NUMA socket 上绑核。否则即使 socket 能连上,数据面也会在映射阶段失败,或表现为尾延迟差。

排障先看环境而非 virtio 规范

遇到问题应先核对 socket 路径、controller 存在性、bdev 与 guest 盘名一致性,再谈队列与性能。大页总量被 QEMU 与 SPDK 分食、socket 文件残留或启动用户不一致等环境问题,常被误判为 virtio 配置错误。

与 NVMe-oF 和内核 vhost 的定位差异

SPDK vhost-user 解决同主机地址空间共享下的 virtio 后端,NVMe-oF 解决跨主机块语义,内核 vhost 则留在内核。三者机制不互换,不能将 NVMe-oF 配置经验直接套用到 vhost,尤其要留意共享内存契约和 guest 队列通知的差异。

Q&A

SPDK vhost 与内核 vhost 有什么区别?

SPDK vhost 将 vhost 后端从内核移到用户态进程,通过 vhost-user 协议(Unix 套接字和共享内存)与 QEMU 通信,并使用用户态轮询处理 I/O,从而减少 VMEXIT。而内核 vhost 由内核模块处理,走内核块层。

vhost-scsi 和 vhost-blk 在热插拔支持上有什么不同?

vhost-scsi 支持热挂/热摘 bdev,通过 RPC 如 vhost_scsi_controller_add/remove_target 实现;而 vhost-blk 没有对等的热挂 RPC,物理拔掉 NVMe 时,vhost-blk 上的 I/O 会被中止,可能灌满 guest 日志。

配置 SPDK vhost 时,共享内存和 NUMA 有哪些硬性要求?

必须使用 share=on 的 memory-backend-file 并指向 hugepage 路径,否则数据面映射会失败。同时,SPDK 的轮询核(-m 或 --cpumask)应选择与 VM 同一 NUMA socket 的核,以避免跨 NUMA 带来的尾延迟。

SPDK vhost 与 NVMe-oF 在定位上有什么不同?

SPDK vhost 解决同主机地址空间共享下的 virtio 后端,面向本机 VM;而 NVMe-oF 解决跨主机的块语义,面向远端 initiator。两者机制不同,不能互换。

使用 SPDK vhost 时,如果 guest 看不见盘,应该先检查哪些方面?

先检查 socket 路径、权限、SPDK 是否在监听(vhost_get_controllers),再确认 scsi/blk 配置、target/LUN、bootindex 等是否正确。

SPDK vhost 中,vhost-scsi 和 vhost-blk 在选型上有什么建议?

如果需要运行时换盘或对齐 SCSI 管理习惯,选择 vhost-scsi;如果希望更薄的块语义并接受换盘需重建 controller,选择 vhost-blk。

SPDK vhost 排障时,为什么建议将 guest dmesg、QEMU 日志和 SPDK 日志对齐?

因为三者时间源可能不一致,对齐后可以在秒级窗口内查找 socket accept、controller 创建和 bdev 删除事件,有助于定位问题,避免单独抠 virtio 规范。

🏷️

标签

➡️

继续阅读