闪存数据,第二部分:使用 NVMe 驱动器和创建 NVMe over Fabrics 网络
按照设计,NVMe 驱动器旨在为插入它们的机器提供本地访问;然而,NVMe over Fabric 规范旨在通过启用对同一设备的远程网络访问来解决这一限制。
本文将实践您在第一部分中学到的知识,并展示如何在 Linux 环境中使用 NVMe 驱动器。但是,在继续之前,您首先需要确保您的物理(或虚拟)机是最新的。一旦您确认了这一点,请确保您能够看到所有连接的 NVMe 设备
$ cat /proc/partitions |grep -e nvme -e major
major minor #blocks name
259 0 3907018584 nvme2n1
259 1 3907018584 nvme3n1
259 2 3907018584 nvme0n1
259 3 3907018584 nvme1n1
这些设备也会出现在 sysfs
中
$ ls /sys/block/|grep nvme
nvme0n1
nvme1n1
nvme2n1
nvme3n1
如果您没有看到任何连接的 NVMe 设备,请确保内核模块已加载
petros@ubu-nvme1:~$ lsmod|grep nvme
nvme 32768 0
nvme_core 61440 1 nvme
接下来,安装名为 nvme-cli
的驱动器管理实用程序。此实用程序由定义 NVMe 规范的 NVM Express 委员会定义和维护。nvme-cli 源代码托管在 GitHub 上。幸运的是,一些操作系统在其内部存储库中提供了此软件包。在最新的 Ubuntu 上安装它看起来像这样
petros@ubu-nvme1:~$ sudo add-apt-repository universe
petros@ubu-nvme1:~$ sudo apt update && sudo apt install
↪nvme-cli
使用此实用程序,您可以列出所有连接的 NVMe 驱动器的更多详细信息(注意:下面的表格输出已重新格式化和截断,以便更好地在此处显示)
$ sudo nvme list
Node SN Model Namespace Usage Format FW Rev
--------------------------------------------------------------
/dev/nvme0n1 PHLF814001... Dell Express Flash NVMe P4500 4.0TB SFF 1
↪4.00 TB / 4.00 TB 512 B + 0 B QDV1DP12
/dev/nvme1n1 PHLF814300... Dell Express Flash NVMe P4500 4.0TB SFF 1
↪4.00 TB / 4.00 TB 512 B + 0 B QDV1DP12
/dev/nvme2n1 PHLF814504... Dell Express Flash NVMe P4500 4.0TB SFF 1
↪4.00 TB / 4.00 TB 512 B + 0 B QDV1DP12
/dev/nvme3n1 PHLF814502... Dell Express Flash NVMe P4500 4.0TB SFF 1
↪4.00 TB / 4.00 TB 512 B + 0 B QDV1DP12
注意:如果您没有物理 NVMe 驱动器连接到您的机器,但仍想(以有限的形式)继续学习,您可以在最新的 VirtualBox 虚拟化应用程序中安装和模拟 NVMe 控制器以及驱动器。
驱动器管理在命令行上发出 nvme
命令会打印一个在线帮助菜单,其中包含完整的功能列表,其中一些功能可以定位和识别各种 NVMe 控制器、驱动器及其命名空间
list List all NVMe devices and namespaces on machine
list-subsys List nvme subsystems
id-ctrl Send NVMe Identify Controller
id-ns Send NVMe Identify Namespace, display structure
list-ns Send NVMe Identify List, display structure
nvme-cli 实用程序的其他功能引入了命名空间管理
ns-descs Send NVMe Namespace Descriptor List, display
↪structure
create-ns Creates a namespace with the provided parameters
delete-ns Deletes a namespace from the controller
attach-ns Attaches a namespace to requested controller(s)
detach-ns Detaches a namespace from requested controller(s)
命名空间是 NVMe 驱动器的独特功能。可以将它们视为物理设备的虚拟分区。命名空间是已定义的非易失性存储器量,可以格式化为逻辑块。配置后,一个或多个命名空间连接到控制器(或主机,有时是远程的)。每个命名空间可以支持各种块大小(例如 512 字节、4 KB 等)。定义后,它们将作为单独的块设备出现在主机上。
如果驱动器包含单个命名空间,则列出它将显示以下内容
$ nvme list-ns /dev/nvme0
[ 0]:0x1
如果您开始创建更多命名空间,它将反映在列表中
$ sudo nvme list-ns /dev/nvme0
[ 0]:0x1
[ 1]:0x2
并在您的操作系统注册的块设备数量中再次反映
$ cat /proc/partitions |grep nvme0
259 0 1953509292 nvme0n1
259 1 1953509292 nvme0n2
使用相同的实用程序,您可以访问驱动器级别的日志记录
get-log Generic NVMe get log, returns log in raw format
fw-log Retrieve FW Log, show it
smart-log Retrieve SMART Log, show it
error-log Retrieve Error Log, show it
effects-log Retrieve Command Effects Log, show it
您还可以设置驱动器级别的功能
get-feature Get feature and show the resulting value
set-feature Set a feature and show the resulting value
set-property Set a property and show the resulting value
例如,假设您要启用 (1) 或禁用 (0) 驱动器的易失性写入缓存 (VWC)。您可以像这样列出其当前设置
$ sudo nvme id-ctrl /dev/nvme0|grep vwc
vwc : 0
并像这样设置它
$ sudo nvme set-feature /dev/nvme0 -f 0x6 -v 1
您可以管理和更新驱动器固件
fw-commit Verify and commit firmware to a specific slot
↪(fw-activate in old version < 1.2)
fw-download Download new firmware
重置控制器(但不重置连接的驱动器)
reset Resets the controller
subsystem-reset Resets the controller
发现并连接到网络上的其他 NVMe 设备(见下文)
discover Discover NVMeoF subsystems
connect-all Discover and Connect to NVMeoF subsystems
connect Connect to NVMeoF subsystem
disconnect Disconnect from NVMeoF subsystem
gen-hostnqn Generate NVMeoF host NQN
以及更多。
该实用程序甚至具有插件扩展来支持供应商特定的功能。最新版本包括
intel Intel vendor specific extensions
lnvm LightNVM specific extensions
memblaze Memblaze vendor specific extensions
wdc Western Digital vendor specific extensions
huawei Huawei vendor specific extensions
netapp NetApp vendor specific extensions
toshiba Toshiba NVME plugin
micron Micron vendor specific extensions
seagate Seagate vendor specific extensions
通过网络访问驱动器
让我们看看如何利用高速 SSD 技术并将其扩展到本地服务器之外。NVMe 不必局限于物理插入它的服务器。在此示例中,让我们在传统 TCP/IP 之上配置软 RDMA over Converged Ethernet (RoCE) 网络,并通过此方法导出/导入 NVMe 块设备。这将是您的 NVMeoF 网络。
但在继续之前,您需要了解几个概念
- 主机:就当前环境而言,主机将是连接到远程块设备的服务器——具体来说,是 NVMe 目标。
- 目标:目标将是跨网络和向主机服务器导出 NVMe 设备的服务器。
在本示例中,为了方便起见,我描述了使用两台虚拟机来创建网络。这样做绝对没有任何优势,我不建议任何人这样做,除非是为了跟随练习。实际上,您应该仅在连接了高速网卡的物理机上启用以下操作。话虽如此,在目标虚拟机中,让我们连接几个低容量的虚拟 NVMe 驱动器(每个 2GB)
$ sudo nvme list
Node SN Model Namespace Usage Format FW Rev
--------------------------------------------------------------
/dev/nvme0n1 VB1234-56789 ORCL-VBOX-NVME-VER12 1 2.15 GB / 2.15 GB
↪512 B + 0 B 1.0
/dev/nvme0n2 VB1234-56789 ORCL-VBOX-NVME-VER12 2 2.15 GB / 2.15 GB
↪512 B + 0 B 1.0
(注意:上面的表格输出已编辑以适合列宽。)
同样,我一直在使用最新版本的 Ubuntu。为了准备主机和目标操作环境,请安装以下软件包
$ sudo apt install libibverbs-dev libibverbs1 rdma-core
↪ibverbs-utils
在某些发行版上,您可能需要指定 librxe
软件包(在 Ubuntu 上,其功能打包在 rdma-core
中)。
同样,在主机和目标上,您现在将加载所需的内核模块(有几个)
$ sudo modprobe nvme-rdma
$ sudo modprobe ib_uverbs
$ sudo modprobe rdma_ucm
$ sudo modprobe rdma_rxe
$ sudo modprobe nvmet
$ sudo modprobe nvmet-rdma
以下说明在很大程度上依赖于 sysfs
虚拟文件系统。从理论上讲,您可以使用 nvmet-cli
开源实用程序导出 NVMe 目标,该实用程序完成了所有复杂的繁重工作。但是,那样还有什么乐趣呢?
设置 Soft-RoCE 网络
需要在主机和目标服务器之间建立 RDMA 网络。在每台服务器上,确定要为此传输方法启用的网络接口
$ ip addr show enp0s3
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc
↪fq_codel state UP group default qlen 1000
link/ether 08:00:27:15:4b:da brd ff:ff:ff:ff:ff:ff
inet 192.168.1.85/24 brd 192.168.1.255 scope global
↪dynamic enp0s3
valid_lft 85865sec preferred_lft 85865sec
inet6 fe80::a00:27ff:fe15:4bda/64 scope link
valid_lft forever preferred_lft forever
让我们在首选的以太网接口之上配置 RDMA 接口,但在这样做之前,首先验证是否已存在一个
$ sudo rxe_cfg status
Name Link Driver Speed NMTU IPv4_addr RDEV RMTU
enp0s3 yes e1000
启用 RDMA 环境并添加以太网接口
$ sudo rxe_cfg start
$ sudo rxe_cfg add enp0s3
验证您现在是否拥有 RDMA 接口 (rxe
)
$ sudo rxe_cfg status
Name Link Driver Speed NMTU IPv4_addr RDEV RMTU
enp0s3 yes e1000 rxe0 (?)
您还将在 sysfs
中找到此接口的列表
$ ls /sys/class/infiniband
rxe0
在主机和目标机器上应用相同的说明后,您需要测试 RDMA 网络。
在主机上,设置服务器
$ sudo ibv_rc_pingpong -d rxe0 -g 0
local address: LID 0x0000, QPN 0x000011, PSN 0x5db323,
↪GID fe80::a00:27ff:fe48:d511
remote address: LID 0x0000, QPN 0x000011, PSN 0x3403d4,
↪GID fe80::a00:27ff:fe15:4bda
8192000 bytes in 0.40 seconds = 164.26 Mbit/sec
1000 iters in 0.40 seconds = 398.97 usec/iter
在目标上,设置客户端(将 IP 替换为主机机器的 IP 地址)
$ sudo ibv_rc_pingpong -d rxe0 -g 0 192.168.1.85
local address: LID 0x0000, QPN 0x000011, PSN 0x3403d4,
↪GID fe80::a00:27ff:fe15:4bda
remote address: LID 0x0000, QPN 0x000011, PSN 0x5db323,
↪GID fe80::a00:27ff:fe48:d511
8192000 bytes in 0.40 seconds = 164.46 Mbit/sec
1000 iters in 0.40 seconds = 398.50 usec/iter
如果您得到如上所示的响应,则说明您已成功在 TCP 之上配置了 RDMA 网络。
导出目标
挂载内核用户配置文件系统。这是必需的。您的所有 NVMe 目标指令都要求 NVMe 目标树在此文件系统中可用
$ sudo /bin/mount -t configfs none /sys/kernel/config/
创建一个 NVMe 目标子系统以托管您的设备(要导出),并更改到其目录
$ sudo mkdir /sys/kernel/config/nvmet/subsystems/nvmet-test
$ cd /sys/kernel/config/nvmet/subsystems/nvmet-test
本示例通过允许任何和所有尝试连接到它的主机访问新创建的子系统来简化主机连接(在生产环境中,您绝对应该通过其 NQN 将其锁定到特定的主机机器)
$ echo 1 |sudo tee -a attr_allow_any_host > /dev/null
导出目标时,它是使用“唯一”的 NVMe Qualified Name (NQN) 完成的。该概念与 iSCSI Qualified Name (IQN) 非常相似。此 NQN 使其他操作系统能够导入和使用可能托管多个 NVMe 设备的网络上的远程 NVMe 设备。
定义一个子系统命名空间并更改到其目录
$ sudo mkdir namespaces/1
$ cd namespaces/1/
将本地 NVMe 设备设置为新创建的命名空间
$ echo -n /dev/nvme0n1 |sudo tee -a device_path > /dev/null
并启用命名空间
$ echo 1|sudo tee -a enable > /dev/null
现在,您将创建一个 NVMe 目标端口来导出新创建的子系统,并更改到其目录路径
$ sudo mkdir /sys/kernel/config/nvmet/ports/1
$ cd /sys/kernel/config/nvmet/ports/1
还记得您为 RDMA 通信启用的以太网接口吗?嗯,导出您的子系统时将使用它的 IP 地址
$ echo 192.168.1.92 |sudo tee -a addr_traddr > /dev/null
接下来,您将设置一些其他参数
$ echo rdma|sudo tee -a addr_trtype > /dev/null
$ echo 4420|sudo tee -a addr_trsvcid > /dev/null
$ echo ipv4|sudo tee -a addr_adrfam > /dev/null
然后创建一个软链接以将子系统指向您新创建的端口
$ sudo ln -s /sys/kernel/config/nvmet/subsystems/nvmet-test/
↪/sys/kernel/config/nvmet/ports/1/subsystems/nvmet-test
您现在应该在 dmesg
中看到以下消息
$ dmesg |grep "nvmet_rdma"
[24457.458325] nvmet_rdma: enabling port 1 (192.168.1.92:4420)
导入目标
主机当前没有 NVMe 设备
$ nvme list
Node SN Model Namespace Usage Format FW Rev
------- ------ -------- --------- -------- ---------- ------
让我们扫描目标机器以查找任何导出的 NVMe 卷
$ sudo nvme discover -t rdma -a 192.168.1.92 -s 4420
Discovery Log Number of Records 1, Generation counter 1
=====Discovery Log Entry 0======
trtype: rdma
adrfam: ipv4
subtype: nvme subsystem
treq: not specified
portid: 1
trsvcid: 4420
subnqn: nvmet-test
traddr: 192.168.1.92
rdma_prtype: not specified
rdma_qptype: connected
rdma_cms: rdma-cm
rdma_pkey: 0x0000
今天你真幸运。看起来目标机器正在导出一个或多个卷。您需要记住它的 subnqn
字段:nvmet-test
。您现在将连接到 subnqn
$ sudo nvme connect -t rdma -n nvmet-test -a 192.168.1.92
↪-s 4420
如果您返回以列出所有 NVMe 设备,您现在应该看到由该 subnqn
导出的所有设备(注意:下面的表格输出已重新格式化以适合)
$ sudo nvme list
Node SN Model Namespace Usage Format FW Rev
------- ---- ------ --------- -------- --------- ------
/dev/nvme1n1 8e0999a558e17818 Linux 1 2.15 GB / 2.15 GB
↪512 B + 0 B 4.15.0-3
验证它也像您的其他块设备一样显示
$ cat /proc/partitions |grep nvme
259 1 2097152 nvme1n1
您可以通过键入以下内容断开与目标设备的连接
$ sudo nvme disconnect -d /dev/nvme1n1
您已经成功了:通过 NVMe over Fabrics 网络导出的远程 NVMe 块设备。您现在可以像任何其他本地连接的高性能块设备一样对其进行写入和读取。
注意:如果您看到 I/O 错误,则 Linux rxe
代码存在已知问题,您可能需要运行较新的内核。据信内核提交 2da36d44a9d54a2c6e1f8da1f7ccc26b0bc6cfec 解决了此问题,并且已合并到较后的 4.16 版本中。
NVMe 驱动器改变了高速计算的格局。规范和技术都重新定义了对基于 NAND 的 SSD 介质的访问,并已更新以更好地适应现代工作负载。尽管 NVMe 通常在本地机器中运行,但它并不局限于此。使用 NVMe over Fabrics 技术,NVMe 可以扩展到本地服务器之外,并跨越整个高速网络。
资源