NVMe over Fabric(简称NVMe-oF)是把本地高速NVMe存储通过网络延伸出去的一套协议方案。它保留了NVMe协议本身多队列、低延迟的优势,同时借助RDMA、FC、TCP等传输层,让多台服务器像访问本地磁盘一样访问远端闪存。这篇文章从架构原理讲到具体命令,完整演示一次集群存储场景下的NVMe-oF部署过程。

一、NVMe-oF架构与传输层选型
先看清楚NVMe-oF在协议栈里的位置。传统的FC-SAN或者iSCSI方案,块设备请求要经过SCSI协议栈,SCSI是单队列模型,一个设备只有一个提交队列和一个完成队列,多核CPU争抢锁的开销非常明显。而NVMe原生支持64K个队列,每个CPU核心可以绑定独立队列,队列深度也大幅提升,这正是NVMe-oF性能优势的根源。NVMe-oF并没有重新发明协议,而是定义了一个 NVMe传输层绑定规范,把NVMe命令封装到不同的底层网络里。
目前可用的传输层有三种主流选择。第一种是RDMA,包括RoCE v2和InfiniBand,延迟最低,单跳往返延迟可以做到20微秒以内,但需要支持RDMA的网卡(如Mellanox ConnectX系列)和正确的无损以太网配置,部署门槛最高。第二种是FC,适合已有FC-SAN基础设施的传统企业,投资保护最好。第三种是NVMe/TCP,从Linux 5.0内核开始支持,普通万兆网卡就能跑,延迟比RDMA高一些但部署极其简单,非常适合先做技术验证再逐步升级。
本文的实战环境选择RoCE v2,这是目前性价比最高的方案。硬件配置如下:一台target存储节点(内核5.15,配ConnectX-5网卡,本地有一块Intel P4510 U.2 SSD),两台initiator应用节点,交换机需要开启PFC(优先级流控)和ETS,确保RDMA流量不丢包。网络规划为存储网段10.0.10.0/24,MTU统一设置为9000开启巨帧。
二、target端配置:导出NVMe namespace
target端的核心是内核的nvmet框架。首先确认内核模块已加载,然后配置/etc/nvmet/config.json,或者使用nvmetcli工具交互式配置。下面给出最常用的命令行方式,先加载模块并创建端口:
# 加载nvmet内核模块 modprobe nvmet modprobe nvmet_rdma # 创建namespace目录结构(使用configfs) cd /sys/kernel/config/nvmet mkdir subsystems/nvme-sub1 mkdir namespaces/1 # 将本地NVMe设备绑定到namespace echo -n /dev/nvme0n1 > namespaces/1/device_path echo 1 > namespaces/1/enable # 创建端口并设置传输类型为RDMA mkdir ports/1 echo rdma > ports/1/addr_trtype echo 10.0.10.10 > ports/1/addr_traddr echo 4420 > ports/1/addr_trsvcid # 将subsystem挂接到端口 ln -s subsystems/nvme-sub1 ports/1/subsystems/nvme-sub1
执行完上述命令后,可以用dmesg | grep nvmet确认没有报错,target端就开始监听4420端口了。这里有几个容易踩的坑需要提醒。第一,device_path必须写裸设备路径,不能是分区,也不能是带了文件系统的设备。第二,RoCE环境下如果交换机没配PFC,RDMA连接会频繁重传,表现为能发现设备但IO延迟抖动巨大,这类问题在排障时经常被误判为软件配置错误。第三,生产环境建议把config.json持久化到/etc/nvmet/config.json,然后通过systemd单元在开机时执行nvmetcli restore,否则重启后导出配置全部丢失。
三、initiator端配置与多路径高可用
initiator端的配置相对简单,重点是内核要编译了nvme-rdma驱动。执行发现和连接命令:
# 加载nvme-rdma模块 modprobe nvme_rdma # 发现target端导出的subsystem nvme discover -t rdma -a 10.0.10.10 -s 4420 # 连接到指定subsystem nvme connect -t rdma -a 10.0.10.10 -s 4420 -n nvme-sub1 # 查看挂载的设备 nvme list lsblk
连接成功后,本地会出现/dev/nvme1n1这样的设备,可以直接mkfs.xfs格式化后使用。但单链路在生产环境是不够的,必须做高可用。NVMe-oF原生的多路径方案是内核的nvme-multipath,开启方式是设置内核参数nvme_core.multipath=Y(新内核默认已开启)。配置好之后,如果同一台initiator通过多条网络路径连到多个target端口,内核会自动生成/dev/nvme1c0n1这样的共享设备节点,路径之间支持负载均衡。
多路径的调度策略通过/sys/class/nvme-subsystem/nvme1/iopolicy切换,默认是round-robin轮询分发,对顺序读多的小文件业务可以改成queue-depth,让IO自动压到最空闲的路径上。同时别忘了在initiator端做连接持久化,把connect命令写进systemd服务,或者使用nvmf-autoconnect的systemd单元配合/etc/nvme/discovery.conf配置文件,开机自动完成发现和连接。
四、性能调优与故障排查
部署完成后先做基线测试。用fio对RDMA设备做4K随机读写压测:
fio --filename=/dev/nvme1n1 --direct=1 --rw=randread \
--bs=4k --ioengine=libaio --iodepth=128 --numjobs=4 \
--runtime=60 --group_reporting --name=nvmeof-test
调优主要围绕三个方向。第一个是中断与队列绑定,使用irqbalance关闭自动绑定,手动把网卡队列中断绑定到NUMA本地节点,避免跨NUMA访问带来的延迟恶化。第二个是巨帧与流量控制,确认两端和交换机MTU一致,RoCE流量所在的队列开启PFC。第三个是nr_requests和预读参数,块层队列深度调大一些,对高队列深度的NVMe设备有明显收益。经过调优,双节点RoCE环境下单路径4K随机读可以达到80万以上IOPS,往返延迟稳定在60微秒左右,相比iSCSI方案有数倍提升。
排障思路也简单梳理一下。nvme discover没结果,优先查网络连通性和target端防火墙的4420端口;能发现但连接失败,检查dmesg里的RDMA报错,多数是网卡固件版本或者addr_adrfam地址族配置不匹配;连接成功但IO报错超时,几乎都是无损以太网没配置到位导致丢包。定位工具推荐perfquery看RDMA计数器,rxe_cfg和show_gids用于确认RoCE状态,配合nvme-cli的nvme show-subsys可以直观看到每条路径的状态,一旦某条路径故障,多路径会在几秒内把IO切到健康路径上,业务无感知。
整体来看,NVMe-oF的部署难度主要集中在无损网络和持久化配置这两块,协议本身的配置反而很简单。如果是初次接触,建议先用NVMe/TCP模式跑通流程,再切换到RDMA拿性能,这样可以大幅缩短学习曲线。
NVMe over Fabric集群存储NVMe-oF部署修改时间:2026-09-06 09:04:36