概述

NVMe协议制定了本机高速访问PCIe SSD的规范,为了把本地高速访问的优势暴露给远端应用, 诞生了NVMe-oF 协议。NVMe-oF target 是NVMe协议在不同传输网络 (transport) 上面的延伸。NVMe-oF 协议中的 transport 可以多种多样, 诸如 Ethernet, Fibre Channel,Infiniband等。当前比较流行的transport实现是基于RDMA的Ethernet transport, Linux Kernel 和SPDK的NVMe-oF target 都支持。

overview

名词解释

nvme over fabric

  • controller:nvme的字符设备,对应为/dev/nvmeX,是我们下发控制命令的设备。
  • namespace:nvme的块设备,对应为/dev/nvmeXnX,也是我们下发IO的设备。
  • host:client端。
  • target:处理client请求,连接实际存储设备。
  • transport:Transport是连接Host和Target的桥梁,可以是PCIE/RDMA/FC/TCP
  • subNQN:用于识别远程NVMe存储目标controller. 保存在identify controller
  • EUI64/UUID/NGUID: 用于识别远程NVMe namespace. 保存在NVMe Namespace Descriptor List,EUI64/NGUID同时保存在identify namespace
    • 注意:spdk使用uuid作为identifier连接kernel nvme initiator,在重连的时候有bug,这个bug在kernel5.13上才被修复掉。

conn

spdk nvmf

subsystem:spdk创建的nvme controller。相当于nvme controller,拥有了subsystem就可以被nvme host识别到并挂载了,就算他名下没有namespace。

spdk-nvmf

nvmf initiator 和 target

主要介绍 linux kernel nvme initiator + spdk nvmf target。spdk的nvmf initiator使用方法和访问pcie盘类似,不再详述。

spdk nvmf target

nvmf和vhost一样都是spdk的一个模块。启动nvmf模块就相当于启动了一个nvme over fabrics target。启动后可以通过rpc创建nvmf subsystem,并把bdev挂载到namespace上。最后通过监听端口,实现远端nvme initiator的访问。

spdk nvmf target 创建示例:

# 创建相应的transport,可以使TCP或者RDMA
python scripts/rpc.py nvmf_create_transport -t RDMA -u 8192 -p 2 -c 4096
# 创建一个 bdev
python scripts/rpc.py construct_malloc_bdev  bdev_test
# 创建一个NVM subsystem
python scripts/rpc.py nvmf_create_subsystem nqn.2020-05.io.spdk:bdev_test -a -m 10  # -a = allow all
# 给NVM subsystem 增加一个namespace,使用malloc bdev。
python scripts/rpc.py nvmf_subsystem_add_ns nqn.2020-05.io.spdk:bdev_test  bdev_test -g 9EF1D3DAB2044ABA8F83B0427E58AEB0
# 让nvmf subsystem监听对应的端口,至此一块nvmf 盘已经建立成功,可以成功的被远端host discover到。
python scripts/rpc.py nvmf_subsystem_add_listener nqn.2020-05.io.spdk:bdev_test -t rdma -a 172.0.0.1 -s 4420

linux kernel NVMeOF initiator

  • nvme over fabrics驱动默认不会被加载,我们一般看到的nvme驱动是pcie驱动。我们使用modprobe nvme-rdma启动 nvmf rdma驱动
  • 使用命令工具nvme让nvme host挂载对应target上的盘,下面是一个示例:
# Discovery 列出spdk nvmf target所有的subsystem
nvme discover -t rdma -a 172.0.0.1 -s 4420
# 连接一块nvmf盘,使用-n参数指定subnqn,只连接对应subnqn的盘。
nvme connect -t rdma -n "nqn.2020-05.io.spdk:bdev_test" -a 172.0.0.1 -s 4420
# 连接对应spdk nvmf target下所有的盘。
nvme connect-all -t rdma -a 172.0.0.1 -s 4420
# 两种disconnect的方式,一种是指定盘符,一种是指定subnqn
nvme disconnect  -d /dev/nvme0
nvme disconnect -n "nqn.2020-05.io.spdk:bdev_test"
multipath

同一个subsystem在initiator端挂载两次(例如从两个IP连过来),initiator端能识别到两次挂载实际上是同一块盘,这就是multipath功能,开启multipath有如下好处:;

  1. 保护同一个subsystem不会再同一个host上挂载多次
  2. 多次挂载冗余保护,例如:一个IP上的网卡宕机

linux kernel 4.15可以配置CONFIG_NVME_MULTIPATH启动multipath功能。启动之后,假设我们对用一个subsystem挂载两次,nvme0和nvme1,/dev目录会显示如下

$ ll /dev/nvme*
/dev/nvme0
/dev/nvme0n1
/dev/nvme1

如果nvme0因为某种原因断开,只要nvme1不断开,那么nvme0n1就会可用。

与之对应,如果不启动multipath,/dev目录会显示两个controller和两个namespace

实践注意事项

  1. spdk会以roundrobin的形式分配IO queue到spdk core,因此仅增加io queue而不增加spdk core,可能性能并不会有很好的提升。
  2. 如果spdk重启,需要依赖另一端initiator重连,kernel intiator默认的重连频率是10秒。
  3. 如果性能不达标,可以尝试修改nvmf上的网络参数,比如包大小之类。
  4. 对于bdev的异步事件:扩容和bdev关闭,spdk-nvmf已经实现了通知机制,通知initiator。
  5. 使用kernel initiator要注意内核驱动的操作是否有幂等性、超时等保证,否则极其容易造成kernel D住。建议在可以允许的范围内选择高版本的kernel。当然实践过程中或许不可避免的要backport。

参考链接

  1. NVMe over Fabrics 技术特征
  2. 深入理解 SPDK NVMeTCP transport的设计
  3. 基于SPDK的高效NVMe-oF target
  4. 20.01 SPDK NVMe-oF RDMA Performance Report官方详细的性能测试结果,可作为后续性能优化的依据
  5. NVMe over Fabrics Target官方例子,如何起spdk nvmf target
  6. SPDK NVMe-oF target 多路功能介绍
  7. 搭建远端存储,深度解读SPDK NVMe-oF target
  8. SPDK线程模型解析
  9. NVMe Over Fabrics video from the 2016 OpenFabrics Workshop
GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐