NVMe over TCP and ANA

NVMe over TCP and ANA

nvme over fabrics 是比SRP, iSER 效率更高的存储协议,主要表现在延时降低,iops和本地使用相差无几。从NVMe –oF 1.4开始,有了ANA(Asymmetric Namespace Access),简单说,它就相当于SCSI家族协议(iSCSI,SRP,iSER)的ALUA,可以实现所谓的“双活”。ALUA和ANA的详细定义我就不废话了,大家都可以去网上搜,这篇文章也只是记录下如何配置实现ANA,以及如何和linux multipath-tool配合。至于原生的nvme multipath,不是我们的重点,有时间原生的nvme multipath单写一篇。

本次测试本想用nvme over fabrics(infiniband),但是实验服务器被同事占用,在ANA这块,nvme over fabrics和nvme over tcp没什么区别,所以用虚拟机和nvme over tcp来演示ANA的配置。

首先,nvme over tcp应该要升级内核到比较高的版本,具体从哪个版本开始支持的我不记得了,只确定是5.x,本次测试用的最近的稳定版本5.7.8。当然,如果使用nvme over fabrcis (IB or RoCE)+ ANA,可以用4.19.x内核。

其次,支持ANA的multipath-tool版本至少是redhat(centos) 7.7 自带的device-mapper-mulitpath 0.49-127, 因为手头没有x86版的7.7,就用了7.8,但是我也不是整个OS都是7.8,而是在安装了centos7.5之后,单独升级device-mapper-multipath相关软件包到0.49-131。

所以我的配置最后就是2台centos75的VM,升级内核到5.7.8,升级device-mapper-multipath到0.49-131。

编译内核的步骤就不废话了,主要的当然是要把nvme over tcp模块选上,具体方法可以参考mellanox的 https://community.mellanox.com/s/article/howto-compile-linux-kernel-for-nvme-over-fabrics,文章讲的是怎么编译4.8,但是5.7.8的过程也差不多。

编译后,内核会自带nvme over tcp target 和 nvme over tcp host driver:

[root@centos75vm6 ~]# modprobe nvmet
[root@centos75vm6 ~]# modprobe nvmet_tcp
[root@centos75vm6 ~]# lsmod |grep nvme
nvmet_tcp              28672  0 
nvmet                 102400  1 nvmet_tcp
nvme_tcp               36864  0 
nvme_fabrics           28672  1 nvme_tcp
nvme                   49152  0 
nvme_core              98304  3 nvme_tcp,nvme,nvme_fabrics
t10_pi                 16384  2 sd_mod,nvme_core

为了方便配置和测试,我们还要安装最新的nvme-cli和nvmetcli,一个是host端用,一个是target端用。

centos 7.5 自带的两个工具的版本比较旧,建议下载最新版本:

nvme-cli:https://github.com/linux-nvme/nvme-cli/releases,我用的1.12版

nvmetcli:http://git.infradead.org/users/hch/nvmetcli.git,我用的是0.7版

下面的setup过程:

1. 安装两个centos7.5 虚拟机,各有3个网卡,保证3个网卡在三个不同网段,彼此能ping通。

centos75vm6 centos75vm7
网卡1:ens33 192.168.204.126 192.168.204.127
网卡2:ens34 192.168.42.126 192.168.42.127
网卡3:ens35 192.168.10.126 192.168.10.127

2.   在其中一台vm添加一个虚拟nvme设备,对应设备名为/dev/nvme0n1

3.  使用nvmetcli配置target端,三个port,两个是optimized,一个是non-optimized:

[root@centos75vm7 dist]# nvmetcli
/> ls
o- / ......................................................................................................................... [...]
   o- hosts ................................................................................................................... [...]
   o- ports ................................................................................................................... [...]
   | o- 1 ................................................. [trtype=tcp, traddr=192.168.10.127, trsvcid=4420, inline_data_size=16384]
   | | o- ana_groups .......................................................................................................... [...]
   | | | o- 1 ..................................................................................................... [state=optimized]
   | | o- referrals ........................................................................................................... [...]
   | | o- subsystems .......................................................................................................... [...]
   | |   o- testnqn ........................................................................................................... [...]
   | o- 2 ................................................. [trtype=tcp, traddr=192.168.42.127, trsvcid=4420, inline_data_size=16384]
   | | o- ana_groups .......................................................................................................... [...]
   | | | o- 1 ..................................................................................................... [state=optimized]
   | | o- referrals ........................................................................................................... [...]
   | | o- subsystems .......................................................................................................... [...]
   | |   o- testnqn ........................................................................................................... [...]
   | o- 3 ................................................ [trtype=tcp, traddr=192.168.204.127, trsvcid=4420, inline_data_size=16384]
   |   o- ana_groups .......................................................................................................... [...]
   |   | o- 1 ................................................................................................. [state=non-optimized]
   |   o- referrals ........................................................................................................... [...]
   |   o- subsystems .......................................................................................................... [...]
   |     o- testnqn ........................................................................................................... [...]
   o- subsystems .............................................................................................................. [...]
     o- testnqn ................................................................. [version=1.3, allow_any=1, serial=6945bae9473e0b0e]
       o- allowed_hosts ....................................................................................................... [...]
       o- namespaces .......................................................................................................... [...]
         o- 1 ...................................... [path=/dev/nvme0n1, uuid=fb5bc33c-26b5-41f5-85f7-7fcaa70f8574, grpid=1, enabled]
/>

注意

set addr trtype=tcp
set addr adrfam=ipv4

这个版本比以前版本,在每个port里面多设置一个名为1的ana_groups中的state,一个是non-optimized,两个是optimized,其他的和普通的nvme over fabrics没啥区别,设置完成后的json文件:

{
   "hosts": [],
   "ports": [
     {
       "addr": {
         "adrfam": "ipv4",
         "traddr": "192.168.204.127",
         "treq": "not specified",
         "trsvcid": "4420",
         "trtype": "tcp"
       },
       "ana_groups": [
         {
           "ana": {
             "state": "non-optimized"
           },
           "grpid": 1
         }
       ],
       "param": {
         "inline_data_size": "16384"
       },
       "portid": 3,
       "referrals": [],
       "subsystems": [
         "testnqn"
       ]
     },
     {
       "addr": {
         "adrfam": "ipv4",
         "traddr": "192.168.42.127",
         "treq": "not specified",
         "trsvcid": "4420",
         "trtype": "tcp"
       },
       "ana_groups": [
         {
           "ana": {
             "state": "optimized"
           },
           "grpid": 1
         }
       ],
       "param": {
         "inline_data_size": "16384"
       },
       "portid": 2,
       "referrals": [],
       "subsystems": [
         "testnqn"
       ]
     },
     {
       "addr": {
         "adrfam": "ipv4",
         "traddr": "192.168.10.127",
         "treq": "not specified",
         "trsvcid": "4420",
         "trtype": "tcp"
       },
       "ana_groups": [
         {
           "ana": {
             "state": "optimized"
           },
           "grpid": 1
         }
       ],
       "param": {
         "inline_data_size": "16384"
       },
       "portid": 1,
       "referrals": [],
       "subsystems": [
         "testnqn"
       ]
     }
   ],
   "subsystems": [
     {
       "allowed_hosts": [],
       "attr": {
         "allow_any_host": "1",
         "cntlid_max": "65519",
         "cntlid_min": "1",
         "model": "hthorizon",
         "serial": "6945bae9473e0b0e",
         "version": "1.3"
       },
       "namespaces": [
         {
           "ana_grpid": 1,
           "device": {
             "nguid": "00000000-0000-0000-0000-000000000000",
             "path": "/dev/nvme0n1",
             "uuid": "fb5bc33c-26b5-41f5-85f7-7fcaa70f8574"
           },
           "enable": 1,
           "nsid": 1
         }
       ],
       "nqn": "testnqn"
     }
   ]
}

4  在host端连接和nvme over fabris区别不大,-t 后面把rdma换成tcp就可以:

[root@centos75vm6 ~]# nvme discover -t tcp -a 192.168.204.127 -s 4420

Discovery Log Number of Records 1, Generation counter 4
=====Discovery Log Entry 0======
trtype:  tcp
adrfam:  ipv4
subtype: nvme subsystem
treq:    not specified, sq flow control disable supported
portid:  3
trsvcid: 4420
subnqn:  testnqn
traddr:  192.168.204.127
sectype: none

[root@centos75vm6 ~]# nvme connect -t tcp -a 192.168.204.127 -s 4420 -n testnqn
[root@centos75vm6 ~]# 
[root@centos75vm6 ~]# nvme list
Node             SN                   Model                                    Namespace Usage                      Format           FW Rev  
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1     0e0b3e47e9ba4569     hthorizon                                1           4.29  GB /   4.29  GB    512   B +  0 B   5.7.8

依次连接另两个port:

[root@centos75vm6 ~]# nvme connect -t tcp -a 192.168.42.127 -s 4420 -n testnqn   
[root@centos75vm6 ~]# nvme connect -t tcp -a 192.168.10.127 -s 4420 -n testnqn  
[root@centos75vm6 ~]# 
[root@centos75vm6 ~]# 
[root@centos75vm6 ~]# nvme list
Node             SN                   Model                                    Namespace Usage                      Format           FW Rev  
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1     0e0b3e47e9ba4569     hthorizon                                1           4.29  GB /   4.29  GB    512   B +  0 B   5.7.8   
/dev/nvme1n1     0e0b3e47e9ba4569     hthorizon                                1           4.29  GB /   4.29  GB    512   B +  0 B   5.7.8   
/dev/nvme2n1     0e0b3e47e9ba4569     hthorizon                                1           4.29  GB /   4.29  GB    512   B +  0 B   5.7.8

5. 配置multipath.conf

defaults {
         polling_interval        10
         path_selector           "round-robin 0"
         path_grouping_policy     group_by_prio
         prio                    ana
         path_checker            readsector0
         failback                immediate
         no_path_retry           fail
         user_friendly_names     yes
}

两个主要参数:path_selector 一定要是 group_by_prio,prio 值一定要是ana

[root@centos75vm6 etc]# multipath –ll

……
mpathf (uuid.fb5bc33c-26b5-41f5-85f7-7fcaa70f8574) dm-8 NVME,hthorizon
size=4.0G features='0' hwhandler='0' wp=rw
|-+- policy='round-robin 0' prio=50 status=active
| |- 1:2:1:1 nvme1n1 259:1 active ready running
| `- 2:3:1:1 nvme2n1 259:2 active ready running
`-+- policy='round-robin 0' prio=10 status=enabled
`- 0:1:1:1 nvme0n1 259:0 active ready running

有时,在真正有io操作之前,两个组的status都是enabled,正常。

6  测试:

在centos75vm6 对 dm-8 进行fio测试:

fio --rw=randread --bs=8k --numjobs=4 --iodepth=32 --runtime=120 --ioengine=libaio  --direct=1 --time_based --name task1 --filename=/dev/dm-8

另开一个窗口查看iostat:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
            1.40    0.00   68.91    0.00    0.00   29.69

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sda               0.00     1.00    0.00    4.50     0.00    48.75    21.67     0.01    2.11    0.00    2.11   0.33   0.15
dm-0              0.00     0.00    0.00    5.50     0.00    48.75    17.73     0.01    2.00    0.00    2.00   0.27   0.15
dm-1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdc               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdd               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sde               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdf               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-2              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-3              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-4              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-5              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-6              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdg               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-7              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
nvme0n1           0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-8              0.00     0.00 19106.50    0.00 152908.00     0.00    16.01   128.28    6.71    6.71    0.00   0.05  99.15
nvme1n1           0.00     0.00 9540.50    0.00 76324.00     0.00    16.00    63.33    6.64    6.64    0.00   0.10  99.35
nvme2n1           0.00     0.00 9573.00    0.00 76584.00     0.00    16.00    59.34    6.20    6.20    0.00   0.10  99.45

可以发现io主要集中在nvme1n1和nvme2n1连个设备上,因为这两个设备是optimized组的,优先级为50,而优先级为10的non-optimized的nvme0n1,则不会有io。

在target端,down掉nvme1n1和nvme2n1对应的网卡,在host端:

[root@centos75vm6 etc]# multipath –ll

……
mpathf (uuid.fb5bc33c-26b5-41f5-85f7-7fcaa70f8574) dm-8 NVME,hthorizon                               
size=4.0G features='0' hwhandler='0' wp=rw
|-+- policy='round-robin 0' prio=0 status=enabled
| |- 1:2:1:1 nvme1n1 259:1 failed faulty running
| `- 2:3:1:1 nvme2n1 259:2 failed faulty running
`-+- policy='round-robin 0' prio=10 status=active
   `- 0:1:1:1 nvme0n1 259:0 active ready running

这时候再对dm-8做fio测试,io就集中到prio为10的那一个链路了:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
            1.15    0.00   61.49    0.00    0.00   37.36

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sda               0.00     0.50    0.00    2.00     0.00    16.00    16.00     0.00    0.25    0.00    0.25   0.25   0.05
dm-0              0.00     0.00    0.00    2.50     0.00    16.00    12.80     0.00    0.00    0.00    0.00   0.20   0.05
dm-1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdc               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdd               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sde               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdf               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-2              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-3              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-4              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-5              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-6              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdg               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-7              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
nvme0n1           0.00     0.00 20557.00    0.00 164456.00     0.00    16.00   119.41    5.81    5.81    0.00   0.05 100.00
dm-8              0.00     0.00 20556.50    0.00 164456.00     0.00    16.00   122.21    5.94    5.94    0.00   0.05  96.55
nvme1n1           0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
nvme2n1           0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
Comments are closed.