跳转到内容

Mellanox IB 卡 SR-IOV VF 直通给 KubeVirt VM(computing-8 现场案例)

结论:在 Mellanox ConnectX-6 IB 卡上给 KVM/KubeVirt 开 SR-IOV 并把 VF 直通给 Windows VM,完整链路是 BIOS/固件/内核三前置检查 → echo N > sriov_numvfs 建 VF(改固件需重启)→ vfio-pci 绑定 → 配 IB GUID + state enable → device plugin 上报资源。本案例目标是 computing-8 上 16 个 VF:vf0–7(a8:00.1~a8:01.0)直通给 8 个 VM,vf8–15 留宿主机(与其他服务器一致)。已踩的关键坑:① sriov_numvfs 文件不存在要先查网卡固件 SRIOV_EN 与内核 CONFIG_PCI_IOV,不是驱动没装;② iproute2 配 VF GUID 语法是 vf 0(空格)不是 vf-0(连字符),后者静默无效导致 state 生效而 GUID 没生效;③ sriov-device-plugin 配了 rdmaSubType: ib 只认 mlx5 驱动设备,VF 绑 vfio-pci 后插件看不到,资源上报为 0。

适用范围与环境

  • 节点:computing-8(Ubuntu x86,MLNX_OFED 5.8 已装,MFT 工具可用)
  • 网卡:2× ConnectX-6 IB(PCI a8:00.0d1:00.0,做 bond mlx5_bond_0)+ 2× ConnectX-4 Lx(31:00.0/31:00.1
  • 目标:给 Venus/KubeVirt 的 8 个 Windows VM 各直通 1 个 IB VF(VM 内跑 NFS over IPoIB 访问存储)
  • 参照:同批其他服务器配置为 NUM_OF_VFS=16、vf0–7 直通、vf8–15 留宿主机
  • 接手的是他人项目,文档按单卡机器(mlx5_0ib0)编写,本机是多卡 bond 环境,照抄会错位

一、前置检查:sriov_numvfs 文件不存在 ≠ 驱动没装

接手文档第一行就是 cat /sys/class/infiniband/mlx5_2/device/sriov_numvfs,输出为空。逐层排查:

检查项命令本案例结果
该设备是 PF 还是 VFreadlink /sys/bus/pci/devices/0000:a8:00.0/driverPF(有 sriov_numvfs 的才是 PF)
BIOS开机界面已开 SR-IOV / VT-d
网卡固件开关`mlxconfig qgrep SRIOV`
内核 PCI IOVgrep CONFIG_PCI_IOV /boot/config-$(uname -r)已编译
当前 VF 数cat /sys/class/infiniband/mlx5_2/device/sriov_numvfs0
实际 VF 设备`lspcigrep -i mellanox`

要点:Mellanox 的 SR-IOV 由三处共同决定——BIOS、网卡固件(SRIOV_EN,OEM 定制卡默认关,BIOS 开了不等于网卡开)、内核 CONFIG_PCI_IOV。三处都满足后,写 sriov_numvfs 才会生效。OVS 桥/多卡 bond 环境下 mlx5_2 只是驱动自动编号,不要按文档里别的机器(mlx5_0/ib0)的设备名对号入座

二、创建 VF(16 个)

bash
# 确认目标 PF 编号与 IB 名
ibstat | grep -E "^CA |State:|Rate:"          # mlx5_2/mlx5_3 = 两张 CX6 PF,Active
# 写 VF 数(临时生效;改固件/驱动参数后需重启才持久)
echo 16 > /sys/class/infiniband/mlx5_2/device/sriov_numvfs
# 重启后验证出现 Virtual Function
lspci | grep -i mellanox     # 应看到 a8:00.1 ~ a8:01.7 共 16 个 VF

本案例重启前固件 NUM_OF_VFS=0echo 16 后需重启才在 lspci 出现 VF;重启后 VF 由 mlx5_core 接管,ip a | grep ib 能看到 ibs102v0-v15(IPoIB 接口名 ibs102v<N>)。

三、vfio-pci 绑定 vf0–7(直通给 VM)

bash
modprobe vfio-pci    # 不加载则 bind 失败;Ubuntu 内核自带,重复执行无副作用

# vf0-7 = a8:00.1 ~ a8:01.0;vf8-15 留宿主机不绑(与其他服务器一致)
for vf in 00.1 00.2 00.3 00.4 00.5 00.6 00.7 01.0; do
  d=0000:a8:$vf
  echo $d > /sys/bus/pci/devices/$d/driver/unbind 2>/dev/null
  echo vfio-pci > /sys/bus/pci/devices/$d/driver_override
  echo $d > /sys/bus/pci/drivers/vfio-pci/bind
done

# 验证:前 8 个 VF 显示 vfio-pci
lspci -s a8:00 -nnk | grep -E "Virtual Function|Kernel driver"
# 预期:a8:00.0 = PF 仍 mlx5_core;a8:00.1 ~ a8:01.0 = vfio-pci;a8:01.1+ 未绑仍是 mlx5_core

绑定成功后 ip a | grep ib 里 v0–v7 消失(被 vfio 接管),只剩 v8–v15 + calib...(Calico veth,名字带 ib 是误匹配,与 IB 无关)。

四、配置 IB VF GUID + state(大坑:语法)

IB VF 必须有唯一 GUID,SM 才认、链路才起来。文档写的是 vf-0(连字符),iproute2 正确语法是 vf 0(空格)——连字符写法静默无效,导致 state enable 生效了、GUID 没配进去。

bash
# 正确语法(空格):
ip link set ibs102 vf 0 node_guid b8:e9:24:03:00:52:8d:56
ip link set ibs102 vf 0 port_guid b8:e9:24:03:00:52:8d:56
# vf1-7 依此类推,每 VF 一个在 IB 子网内唯一的 GUID
for i in 0 1 2 3 4 5 6 7; do
  ip link set ibs102 vf $i state enable
done

# 验证:
ip link show ibs102 | grep -E "vf [0-7] "     # 应看到 GUID 与 state enable

验证命令不要用 ip link show ibs102 | grep "vf [0-7]" 的精确匹配之外的形式——ip a | grep ib 会把 Calico veth(calibd...)也列进来,干扰判断。

五、KubeVirt 资源上报(sriov-device-plugin)

VM 调度报 0/10 nodes available: 1 Insufficient intel.com/mlnx_ib_kubevirt_vf 时,是该资源在 computing-8 上为 0。检查:

bash
kubectl -n kube-system get pod -o wide | grep sriov
kubectl -n kube-system logs <sriov-device-plugin-pod>
kubectl -n kube-system describe cm sriovdp-config   # 看 resourceList

本案例 sriovdp-configconfig.json 里资源 mlnx_ib_kubevirt_vf 的 selectors 用 PCI 地址 + rdmaSubType: ib 过滤,两个问题:

  1. PCI 地址写死到不存在的 VF(如 0000:a8:02.0,实际 VF 只到 a8:01.7)→ 插件找不到设备,上报 0
  2. rdmaSubType: ib 只认 mlx5 驱动下的 RDMA 设备——为了直通把 v0–v7 绑到 vfio-pci 后,插件就看不到这些 VF;容器型资源 mlnx_ib_container_vf 与直通型 mlnx_ib_kubevirt_vf 的过滤逻辑不同,直通用 vfio 的设备需插件支持 driver: vfio-pci 的选择器(或改走 KubeVirt hostDevices 直通 PCI 地址,不经 device plugin 资源)

六、VM 侧错误(会话结束时未闭环)

  • 第 8 个 VM 报 Requested operation is not valid: unmanaged pcidevice 0000:a8:00.1 must be manually detached from the host——KubeVirt 要求设备先与宿主机驱动分离(已绑 vfio-pci 应满足,但设备仍在宿主侧被识别为未托管时需确认 device plugin 上报与 VM hostDevices 声明一致)
  • VM 一直重启伴随 parsing time ... qemu-system-org 类日志(时间解析噪声,非直通根因)

未知:本案例会话结束时该错误尚未完全闭环;GUID/state 与 device plugin 配置修正后需在真机上验证 8 个 VM 全部能拿到 IB VF。

风险与边界

  • 所有 sysfs/ip 操作重启后丢失,生产要持久化需写 udev rule / systemd unit / 网卡配置(本案例重启后配置丢了,与会话中"重启后 VF 还在但绑定丢了"现象一致)
  • GUID 必须在整个 IB 子网唯一,不要自己编,从同批服务器同规律续排或确认唯一后再配
  • 改固件参数(NUM_OF_VFS)有重启窗口;该卡 bond 着跑存储,确认维护窗口再动
  • 文档里的 mlx5_core/unbind+bindreset(FLR)步骤多为作者排障残留,目标直通用只执行 vfio-pci 相关的绑定,不要照单全收

相关文档

基于 MIT 许可发布