【协议】NVMe over RoCE |nvmeof

目录

简单说明

什么是nvme

什么是nvmeof

详细说明

ISER和NVMe-oF 的区别,target是什么?

NVMe-oF与本地NVMe相比

NVMe-oF:NVMe 的高速网络(Fabrics)

NVMe Initiator 和 target 配置

target 端配置

initiator 端配置

配置成功状态

性能测试

遇到的问题

nvme-cli 用户文档

NVMe over RoCE应用场景

参考文档



简单说明

什么是nvme

nvme ssd和普通ssd区别

ssd是固态硬盘,普通的ssd配的是SATA口(AHCI协议),nvme ssd配的是PCIe口(nvme传输协议)

相比普通SSD的SATA口,nvme的PCIe口有巨大的性能优势。

更多详情见:【协议】 SATA接口(AHCI协议)、PCIe 接口(NVMe 协议)|nvme ssd和普通ssd区别_ahci nvme-CSDN博客


 

什么是nvmeof

简介:

nvmeof就是 NVMe over Fabrics ,Fabrics 可理解为高速网络。NVMe over Fabrics 说白了就是把本地NVMe协议扩展成了网络的NVMe,原先的主板总线PCIe变成了RDMA等高速网络,扩展了原先NVME的协议。

为什么需要nvmeof:

NVMe协议的PCIe 接口的使用,使得处理单元和硬盘之间的传输速度快很多,但是一但磁盘不在本机,而是分布式的在其他机器上,跨网络去读其他机器的磁盘,当前的网络又成了瓶颈。

“数据中心的问题仍然存在于存储网络协议上。尽管 NVMe 兴起,但它的收益仅限于每个单独的设备。事实上,闪存和其他企业级(昂贵)设备,例如 AFA,并不是为了将其卓越的性能隔离在机箱内。相反,它们旨在用于大型并行计算机集群,将它们与其他和多个设备(例如其他服务器和存储)连接起来。这种设备的互连就是我们所说的结构,即存储网络,包括交换机、路由器、协议桥、网关设备和电缆。”

所以,要使用新型高速网络:Fabrics。

“2016 年推出了 NVMe-oF 行业标准。协议规范使用以太网、光纤通道、RoCE 或 InfiniBand 将 NVMe 的高性能性能从存储阵列控制器延申到Fabrics高速网络。

Fabrics 建立在发送和接收消息的概念之上,而端点之间没有共享内存。NVMe 结构消息传输将 NVMe 命令和响应封装到基于消息的系统中,该系统包括一个或多个 NVMe 命令或响应。”

 如下图,主机通过NVMEoF高速网络连接其他主机上的NVME磁盘:

详细说明

摘抄和修改自:《NVMe over Fabrics:概念、应用和实现

        NVMf的贡献在于提供除PCIe (本地访问)外访问NVM的另一个途径-Fabrics (网络分布式访问),并且将fabrics链路在latency上增加的overhead维持在10us以内。来自NVMf spec的一张图清晰的展示了它的野心,围绕着NVMe的战场再一次扩大了。

提供fabrics途径后,可以在其他节点直接访问NVMe设备,那么最基本的应用就是替代传统的iSCSI,在闪存系统中导出(暴露/提供)NVMe。

NVMf以NVMe为基石,适配Fabrics场景,新增或删减了的一些Command、概念。

1,Host,Target和Transport

client端称作Host,处理client请求的部分称作Target端(连接物理NVMe设备),Host和Target之间使用NVMe命令交流。Transport是连接Host和Target的桥梁,可以是RDMA或者FC。在Fabrics传输过程中,NVMe命令会被相应的Transport代码封装(Capsule)和解析。

2,NVMe Subsystem,NVMe Namespace和Port

一个Subsystem就是一个NVMe子系统,Subsystem在target端,Host可以申请连接某个target的Subsystem。一个Port代表一个Transport资源。Subsystem必须和Namespace,Port建立关系,但是他们的联系又是很灵活的:即一个Subsystem可以包含多个Namespace,一个Namespace可以加入多个Subsystem,一个Port可以放入多个Subsystem。如下可以将一个NVMe Namespace放入两个Subsystem中形成Fabric多路径配置。

3,NVMe Subsystem中的NVMe Controller

在NVMe Subsystem中,NVMe Controller是一个虚拟的概念,但是具有NVMe协议规定的属性(如部分NVMe寄存器,NVMe Queue和处理NVMe Command)。当一个host接入Subsystem后,就会创建一个Controller对象。那么如何处理NVMe寄存器的访问呢?这就要涉及到NVMf定义的几个Command。

4,NVMf新增和删减Command

在NVMf下,Host和Target之间的传输舍弃了Doorbell的设计,删除了NVMe Queue Create等Admin Command。NVMe Queue的创建在构建Controller后就已经完成了。

NVMf协议新增加的Command如下图,其中Property用来访问NVMe Controller寄存器(仅限于有限的几个寄存器,如Controller Configuration),Connect用来连接Host与Controller的NVMe Queue,Authentication则用于权限管理。

5,NVMe Command的传输方式

Host和Target间的NVMe命令可以在Transport封装时将I/O 数据置于NVMe Command(64Bytes)之后,或者使用SGL表示。如果是前者,则target直接从offset处读取数据,如果是后者,则需要通过RDMA read获取数据(Transport为RDMA的情况下)。虽然声称使用SGL,但是无论是SPDK还是Kernel 实现的Target在提交给物理设备的时候都会转换成PRP,所以目前的NVMe SSD还无需担心由于无法处理SGL请求导致的问题。

NVMf的推广很大程度上要依赖于其代码的实现,好在从Linux Kernel 4.8开始就被收纳,目前只有RDMA一种Fabric Transport。接下来我们看看内核态NVMf的代码框架。

Host端,主要是Host端代码和非NVMf模式下Local NVMe的处理。不管是Host端,还是Local的请求都会经过Linux blk-mq再下发到物理NVMe设备。当然,在经过Fabrics前,I/O请求会先被封装成NVMe Command格式。

Target端,实现了两种Transport(Loopback和RDMA),用户设置通过configfs进行。在收到Host端的I/O请求后,Target也是经过blk-mq下发到物理设备(其实是通过submit_bio向Host端的Local NVMe代码发起请求,类似于文件系统的方式)。

SPDK也加入了NVMf阵营,实现了Target端的代码。由于SPDK天然的优势,Target端的I/O请求可以直接发给物理Controller(Direct模式下),并且按照NVMf的规定将物理Controller作为NVMf独占,在I/O路径和框架上看起来更简洁。

不过,值得一提的是,无论是SPDK还是内核NVMf,从Host端过来的NVMe Command都要被Target代码解析成普通的I/O Request发给PCIe NVMe代码处理,所以NVMf下无论是NVMe Queue还是NVMe Command都是相对于Subsystem和host之间而言。

说明

本文最先发布于公众号《存储技术最前线》,欢迎关注获取最新NVMe技术和资讯

参考资料

1, NVM Express over Fabrics Revision 1.0 spec

2, NVM Express Over Fabrics by Dave Minturn,Intel undle Openfabrics Alliance

3, Under the Hood with NVMe over Fabrics by Dave Minturn,Intel at SNIA forum

4, NVM Express Device Drivers by Uma M.Parepalli at FlashMemroy Summit

ISER和NVMe-oF 的区别,target是什么?

ISER 就是iSCSI走RDMA 网络的扩展。

NVMe-oF 就是nvme 走RDMA 网络的扩展。

-----------------------------------------------------------


主机上直连的存储协议有:iSCSI 和nvme
扩展到网络中,然后网络的传输协议都用rdma的时候,这两个就变成了:ISER 和NVMe-oF

ISER (iSCSI Extensions for RDMA) 和 NVMe-oF 是两种不同的存储网络协议,实现方式:
• ISER 是基于 RDMA (Remote Direct Memory Access) 技术的一种 iSCSI 扩展,它在 iSCSI 协议的基础上利用 RDMA 技术提供高性能的数据传输。
• NVMe-oF 是一种专门设计用于网络中传输 NVMe 命令和数据的协议,它直接在网络层传输 NVMe 命令,绕过了传统的 SCSI 和 TCP/IP 协议栈。
 

target 就是存储资源,走iSCSI 协议的就是iSCSI -target ,走nvme协议的就是nvme-target

NVMe-oF与本地NVMe相比

相比与普通的 NVMe 命令,NVMe over Fabrics 扩展了 NVMe 标准命令和数据传输方式,比如增加了互联命令,discover,connect、Property Get/Set、Authentication Send/Receive等。可以让 发起(读写)者--initiator 端发现并连接target 端(磁盘或带有磁盘的服务器)

initiator 端,又称为host/client端,initiator 配置前提:RDMA基础环境已搭建。通过NVMe 互联命令探测和连接target 端 NVMe SSD 即可。

nvme over pcie

nvme over tcp

nvme over fabric

nvme over rdma

nvme over roce

 

 

https://www.flashmemorysummit.com/English/Collaterals/Proceedings/2017/20170808_FA12_PartB.pdf

NVMe-oF与本地NVMe相比

NVMe-oF:NVMe 的高速网络(Fabrics)

(参考:什么是 NVMe-oF? - 知乎)

NVMe 支持和使用的三种高速网络(Fabrics):

1、基于RDMA 的 NVMe-oF、

2、基于光纤通道的 NVMe-oF

3、基于 TCP 的 NVMe-oF。


NVMe-oF over RDMA

基于RDMA的高速网络(Fabrics)

RDMA,即 Remote Direct Memory Access,是一种绕过远程主机 OS kernel 访问其内存中数据的技术,概念源自于 DMA 技术。在 DMA 技术中,外部设备(PCIe 设备)能够绕过 CPU 直接访问 host memory,不仅可以访问本地主机的内存,还能够访问另一台主机上的用户态内存( 通俗的看成是远程的DMA技术)。

RDMA允许用户态的应用程序直接读取或写入远程内存,不经过操作系统,无内核干预和内存拷贝发生,节省了大量 CPU 资源,提高了系统吞吐量、降低了系统的网络通信延迟。
更多介绍见:https://blog.csdn.net/bandaoyu/article/details/112859853

典型的 RDMA 实现包括verbs 、RoCE、InfiniBand、Omni-Path 和 iWARP。目前使用最多的是 RoCE、InfiniBand 和 iWARP。


NVMe over Fibre Channel (NVMe over FC)


使用 NVMe over Fibre Channel (FC) 的组合通常称为 FC-NVMe、NVMe over FC,有时也称为 NVMe/FC。光纤通道是一种用于在存储阵列和服务器之间传输数据的强大协议,大多数企业 SAN 系统都使用它。在 FC-NVMe 中,命令被封装在 FC 帧中。它基于标准 FC 规则,与支持访问共享 NVMe 闪存的标准 FC 协议相匹配。SCSI 命令封装在 FC 帧中;但是,将它们解释和转换为 NVMe 命令会带来性能损失。


基于 TCP/IP 的 NVMe


这种传输类型是 NVMe-oF 中的最新发展之一。NVMe over TCP(传输控制协议)使用 NVMe-oF 和 TCP 传输协议跨 IP(以太网)网络传输数据。NVMe 通过以太网作为物理传输在 TCP 数据报内传输。尽管有 RDMA 和光纤通道,但 TCP 提供了一种可能更便宜、更灵活的替代方案。此外,与同样使用以太网的 RoCE 相比,NVMe/TCP 的性能更像 FC-NVMe,因为它们使用消息传递语义进行 I/O。


将 NVMe-oF 与 RDMA、光纤通道或 TCP 结合使用,可构建完整的端到端 NVMe 存储解决方案。这些解决方案提供显着的高性能,同时通过 NVMe 保持极低的延迟。


NVMe over RDMA over Converged Ethernet (RoCE)


在 RDMA 协议中,RoCE 脱颖而出。我们知道 RDMA 和 NVMe-oF 是什么,现在我们有了融合以太网 (CE),即通过以太网支持 RDMA。CE 就像一个增强的以太网版本,也称为数据中心桥接和数据中心以太网。它封装了以太网上的 InfiniBand 传输数据包。其解决方案提供了链路级流量控制机制,即使在网络饱和时也能确保零丢失。RoCE 协议允许比其前身 iWARP 协议更低的延迟。

(更多介绍见博客的其他文章介绍)

NVMe Initiator 和 target 配置

target端即磁盘阵列或其他装有磁盘的主机。通过iscsitarget工具将磁盘空间映射到网络上,initiator端就可以寻找发现并使用该磁盘。

Initiator(发起者) 和 target 连接方式如下图所示,左侧为initiator,其右为target。

在NVMe协议中,NVMe 控制器是与 initiator 进行沟通的实体。

通过确定 PCIe port 、NVMe controller 和NVMe namespace,initiator 端可以通过 discover 和 connect 互联命令发现 target 端 NVMe namespace 并将其连接至本地。

引用至《深入浅出SSD》

NVMe over Fabrics 协议定义了使用各种事务层协议来实现 NVMe 功能,其中包括 RDMA、FibreChannel等。

相比与普通的 NVMe 命令,NVMe over Fabrics 扩展了 NVMe 标准命令和数据传输方式,比如增加了互联命令,discover,connect、Property Get/Set、Authentication Send/Receive等。connect 命令携带 Host NQN、NVM Subsystem NQN 、PCIe port 和 Host identifier 信息可以连接到 target 端 NVMe 控制器。

本文中 NVMe over RoCE 调用关系如下图所示,内核 nvme_rdma 模块相当于胶水层,连接 rdma stack 和 nvme core接口,即 NVMe 队列接口可以对接 RDMA 队列接口,进而调用下层 rdma stack 中 verbs 传输接口。

NVMe over RoCE 调用关系

target 端配置

# NVMe target configuration
# Assuming the following:
# IP is 192.168.13.147/24
# link is up
# using ib device eth2
# modprobe nvme and rdma module

modprobe nvmet
modprobe nvmet-rdma
modprobe nvme-rdma

# 1、config nvme subsystem
mkdir /sys/kernel/config/nvmet/subsystems/nvme-subsystem-name
cd /sys/kernel/config/nvmet/subsystems/nvme-subsystem-name

# 2、allow any host to be connected to this target
echo 1 > attr_allow_any_host

# 3、create a namesapce,example: nsid=10
mkdir namespaces/10
cd namespaces/10

# 4、set the path to the NVMe device
echo -n /dev/nvme0n1> device_path
echo 1 > enable

# 5、create the following dir with an NVMe port
mkdir /sys/kernel/config/nvmet/ports/1
cd /sys/kernel/config/nvmet/ports/1

# 6、set ip address to traddr
echo "192.168.13.147" > addr_traddr

# 7、set rdma as a transport type,addr_trsvcid is unique.
echo rdma > addr_trtype
echo 4420 > addr_trsvcid

# 8、set ipv4 as the Address family
echo ipv4 > addr_adrfam

# 9、create a soft link
ln -s /sys/kernel/config/nvmet/subsystems/nvme-subsystem-name /sys/kernel/config/nvmet/ports/1/subsystems/nvme-subsystem-name

# 10、Check dmesg to make sure that the NVMe target is listening on the port
dmesg -T| grep "enabling port"
[369910.403503] nvmet_rdma: enabling port 1 (192.168.13.147:4420)

initiator 端配置

initiator 端,又称为host/client端,initiator 配置前提:RDMA基础环境已搭建。通过NVMe 互联命令探测和连接target 端 NVMe SSD 即可。

# 探测 192.168.13.147 机器上 4420 端口 nvme ssd
nvme discover -t rdma -q nvme-subsystem-name -a 192.168.13.147 -s 4420

# 连接 192.168.13.147 4420 端口 nvme ssd
nvme connect -t rdma -q nvme-subsystem-name -n nvme-subsystem-name  -a 192.168.13.147 -s 4420

# 与target 端 nvme ssd 断开连接
nvme disconnect -n nvme-subsystem-name

配置成功状态

配置前 initiator 和 target 各有 4块 NVMe SSD,使用上述 initator 和 target 配置方法,将 target 上 4 块 NVMe SSD 挂载至 initator,配置后的现象是 initiator 会显示 8 块 NVMe SSD,target 仍然是 4 块。经验证: target 不可以操作被挂载至 initiator 端的 NVMe SSD。配置状态如下图所示:

配置前

配置后

性能测试

下面对比测试本地 NVMe SSD 和 NVMe over RoCE SSD之间的顺序/随机性能,单盘+ext4文件系统,结论是:通过性能数据表明,NVMe over RoCE方法顺序读性能下降约 14%,随机写和随机读性能分别下降约 6% 和 2%,顺序写性能无影响。

I/O类型Local NVMe SSDNVMe over RoCE SSD
顺序写 (MB/s)20352031
顺序读 (MB/s)33742889
随机写 (IOPS)51.6k48.4k
随机读 (IOPS)571k557k

注:NVMe 裸盘测试性能正常,挂载文件系统后性能急剧下降,后续会在文件系统层面研究如何调优。

测试方法:将 NVMe SSD 全盘顺序写2遍后,使用 fio 测试工具

# 顺序写:
fio --iodepth=128 --numjobs=4 --size=1TB --norandommap --readwrite=write --bs=128k  --filename=/partition1/write.txt --runtime=1200 --time_based --ioengine=libaio --direct=1 --group_reporting --name=write

# 顺序读:
fio --iodepth=128 --numjobs=4 --size=1TB --norandommap --readwrite=read --bs=128k  --filename=/partition1/write.txt --runtime=120 --time_based --ioengine=libaio --direct=1 --group_reporting --name=read

# 随机写:
fio --iodepth=128 --numjobs=4 --size=1TB --norandommap --readwrite=randwrite --bs=4k --runtime=1200 --time_based --filename=/partition1/randwrite.txt --ioengine=libaio --direct=1 --group_reporting --name=rand_write

# 随机读:
fio --iodepth=128 --numjobs=4 --size=1TB --norandommap --readwrite=randread --bs=4k --runtime=300 --time_based --filename=/partition1/randwrite.txt --ioengine=libaio --direct=1 --group_reporting --name=rand_read

target 中同 1 个子系统(例如:nvme-subsystem-name)可供多个 initiator 连接。target 子系统关联的硬盘为 /dev/nvme0n1,此时 initiator1 和 initiator2 同时连接 target nvme-subsystem-name,挂载分区后的效果是: initiator1 和 initiator2 均可对 /dev/nvme0n1分区正常读写,但不会同步,仅有等待 disconnect ,再次 connect 后才会进行数据同步。

遇到的问题

问题1:nvmet 模块无法加载的问题

# 导入nvmet内核模块
modprobe nvmet
dmesg | tail
[87679.872351] device-mapper: ioctl: 4.39.0-ioctl (2018-04-03) initialised: dm-devel@redhat.com
[87776.766628] nvmet: Unknown symbol nvme_find_pdev_from_bdev (err -2)
[87850.518208] nvmet: Unknown symbol nvme_find_pdev_from_bdev (err -2)
[88090.703738] nvmet: Unknown symbol nvme_find_pdev_from_bdev (err -2)
[88093.708573] nvmet: Unknown symbol nvme_find_pdev_from_bdev (err -2)

# 解决方法:删除 nvme 模块后,重新加载 nvme 即可
rmmod nvme
modprobe nvme nvmet

问题2:在 initiation 端执行 nvme discover 命令时,遇到 Failed to write to /dev/nvme-fabrics: Invalid argument报错

# 通过 dmesg 发现如下日志,说明 hostnqn 参数没有指定。
[Sat Jan  9 23:00:19 2021] nvme_fabrics: unknown parameter or missing value 'hostnqn=' in ctrl creation request

# 解决方法
nvme discover 添加 -q nvme-subsystem-name 参数

nvme-cli 用户文档

nvme 是 NVMe SSD和 NVMe oF 存储命令行管理工具,nvme安装包为 nvme-cli,它依赖Linux内核 IOCTL 系统调用,该调用连接用户层和NVMe驱动层,当用户执行 nvme commands 时,IOCTL 会将命令参数传递至 NVMe common 层,该层代码解析命令并执行命令,将命令封装至 capsule ,进而传递至 NVMe Submission 队列,Controller 处理后将 capsule 传递至 NVMe Completion 队列,应用从 Completion 队列取出 capsule,完成一次通信。

nvme 安装和常用命令

# 安装nvme-cli
apt-get install pkg-config uuid-runtime -y
git clone https://github.com/linux-nvme/nvme-cli.git
cd nvme-cli && make && make install

# nvme 命令使用方式:
usage: nvme <command> [<device>] [<args>]
# 其中 device 要么是 NVMe 字符设备,例如 /dev/nvme0,要么是 NVMe 块设备,例如 /dev/nvm0n1。

# 查看所有nvme块设备
nvme list

# 查看命名空间结构
nvme id-ns /dev/nvme1n1

# 创建命名空间,分为3个步骤:create-ns、attach-ns 和 reset;
# create-ns 命令中 -s -c 参数分别对应nsze、ncap,可以参考 nvme id-ns /dev/nvme1n1 输出结果
nvme create-ns -s 0xba4d4ab0 -c 0xba4d4ab0 -f 0 -d 0 -m 0 /dev/nvme0

# 将命令空间1关联至控制器0
nvme attach-ns /dev/nvme0 -c 0 -n 1

# 重置 /dev/nvme0,使得创建的命名空间以块设备形式显示在OS中
nvme reset /dev/nvme0

# 查看 /dev/nvme0 拥有的命名空间
nvme list-ns /dev/nvme0

# 删除 /dev/nvme0 第1个命令空间
nvme delete-ns /dev/nvme0 -n 1

# 查看 /dev/nvme0 拥有的控制器
nvme list-ctrl /dev/nvme0

查看 NVMe SSD smartctl 信息

# 使用 smartctl 命令查看 nvme 盘信息,例如,device_name 为 /dev/nvme0n1
apt-get install smartmontools -y
smartctl -a -d nvme $device_name

NVMe over RoCE应用场景

1、刀片仅有 2 个盘位,可以通过 RoCE 连接 NVMe SSD 存储池。

当刀片存储容量不够用时,可以使用 RoCE 连接 NVMe SSD存储池。

2、读写分离场景,可以使用 NVMe over RDMA 搭建 NFS。

target 上 NVMe SSD 可以划分分区,格式化文件系统,写入数据。
target NVMe SSD以块设备形式挂载至 initiator后,仅需 mount 操作即可使用。前提是仅有读操作,各 initator 往同1块 NVMe SSD 上写数据时,各 initator 并不会同步数据。

3、NVMe SSD创建多个命名空间,通过 RoCE 供多个租户使用。

公有云/私有云场景,如下图所示,将 1 块大容量 NVMe SSD 划分为多个命名空间,虚拟化后提供给多个租户,可以充分发挥 NVMe SSD 的性能。 

创建多个命名空间

参考文档

1、Kingston, Understanding SSD Technology: NVMe, SATA, M.2

2、nvme-command user guide

3、what is a namespace ?

4、NVMe over RoCE Storage Fabrics for noobs

5、HowTo Configure NVMe over Fabrics

6、深入浅出SSD

  • 0
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值