主题
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.0、d1:00.0,做 bondmlx5_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_0、ib0)编写,本机是多卡 bond 环境,照抄会错位
一、前置检查:sriov_numvfs 文件不存在 ≠ 驱动没装
接手文档第一行就是 cat /sys/class/infiniband/mlx5_2/device/sriov_numvfs,输出为空。逐层排查:
| 检查项 | 命令 | 本案例结果 |
|---|---|---|
| 该设备是 PF 还是 VF | readlink /sys/bus/pci/devices/0000:a8:00.0/driver | PF(有 sriov_numvfs 的才是 PF) |
| BIOS | 开机界面 | 已开 SR-IOV / VT-d |
| 网卡固件开关 | `mlxconfig q | grep SRIOV` |
| 内核 PCI IOV | grep CONFIG_PCI_IOV /boot/config-$(uname -r) | 已编译 |
| 当前 VF 数 | cat /sys/class/infiniband/mlx5_2/device/sriov_numvfs | 0 |
| 实际 VF 设备 | `lspci | grep -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=0,echo 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-config 的 config.json 里资源 mlnx_ib_kubevirt_vf 的 selectors 用 PCI 地址 + rdmaSubType: ib 过滤,两个问题:
- PCI 地址写死到不存在的 VF(如
0000:a8:02.0,实际 VF 只到a8:01.7)→ 插件找不到设备,上报 0 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+bind、reset(FLR)步骤多为作者排障残留,目标直通用只执行vfio-pci相关的绑定,不要照单全收
相关文档
- Calico(etcd datastore)IPAM 残留清理(同集群 VM 网络故障)
- Venus(KubeVirt)GPU / IB 直通集群网络拓扑
- 系统化排障方法见
mellanox-sriov-enablement/mellanox-ib-sriov-passthroughskills