Metonymical Deflection

ゆるく日々のコト・たまにITインフラ

CentOS7 + SPDKでNVMe-oF (NVMe over Fabric) target構築

CentOS7上でSPDKをビルドして、NVMe-oF(NVMe over Fabric) targetを構築しました。

1.環境

1-1.筐体1 NVMe over Fabric Target
筐体                             : ProLiant DL360p Gen8
System ROM                       : P71 01/22/2018
NIC                              : Mellanox ConnectX-3pro MCX311A-XCCT
SSD                   : Samsung SSD 250GB 970 EVO M.2 Type2280 PCIe3.0×4 NVMe1.3
Adapter                          : GLOTRENDS M.2 PCIe NVMe or PCIe AHCI SSD to PCIe 3.0 x4 Adapter Card
OS                               : CentOS7.5(1804)
Kernel                           : 4.18.4-1.el7.elrepo.x86_64
Installed Environment Groups     : Minimal Install
SPDK                         : v18.10-pre
DPDK                             : v18.05.0
1-2.筐体2 NVMe over Fabric Initiator
筐体                             : ProLiant DL360p Gen8
System ROM                       : P71 01/22/2018
NIC                              : Mellanox ConnectX-3pro MCX311A-XCCT
OS                               : CentOS7.5(1804)
Kernel                           : 4.18.4-1.el7.elrepo.x86_64
Installed Environment Groups     : Minimal Install
1-3.全体の構成

f:id:metonymical:20180823134430j:plain
RoCEv2のフレームをPcapしたかったためTargetとInitiatorの間にスイッチを挟んでいますが、DAS(直結)構成でも大丈夫です。

1-4.全体の流れ

Kernelのアップグレード
事前準備
SPDKのビルド
SPDKのnvmf.conf設定
NVMe-oF Initiatorからのアクセス

2.Kernelのアップグレード

今回の構成ではRoCEv2を使用します。
RoCEv2を使用する場合、Kernel4.5以上でないとサポートされないため、ELRepoから最新のKernelにアップグレードします。
この作業はTargetおよびInitiatorの両方で行ってください。

2-1.リポジトリの登録
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm

GPG-KeyとELRepoの登録を実施。

# yum list installed | grep kernel
kernel.x86_64                         3.10.0-862.el7                   @anaconda
kernel-tools.x86_64                   3.10.0-862.el7                   @anaconda
kernel-tools-libs.x86_64              3.10.0-862.el7                   @anaconda

現在インストールされているKernelのバージョンを確認

2-2.Kernelのアップグレード
yum --enablerepo=elrepo-kernel install kernel-ml

最新Kernelのインストール*1

# awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
0 : CentOS Linux (4.18.4-1.el7.elrepo.x86_64) 7 (Core)
1 : CentOS Linux (3.10.0-862.el7.x86_64) 7 (Core)
2 : CentOS Linux (0-rescue-626b869879714a9cbe128e5b6f85dd89) 7 (Core)

# grub2-set-default 0
# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.18.4-1.el7.elrepo.x86_64
Found initrd image: /boot/initramfs-4.18.4-1.el7.elrepo.x86_64.img
Found linux image: /boot/vmlinuz-3.10.0-862.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-862.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-626b869879714a9cbe128e5b6f85dd89
Found initrd image: /boot/initramfs-0-rescue-626b869879714a9cbe128e5b6f85dd89.img
done
# reboot

menuentryを確認
初期起動Kernelに4.18.4-1.el7.elrepo.x86_64を選択
grub.cfgへの反映
再起動

なお、Initiatorはここまでで完了です。
Targetはspdkのビルドを行うため、この後のkernel-ml-develやkernel-ml-headersのインストールも行ってください。

2-3.既存Kernel削除とその他のアップグレード
uname -r
yum remove kernel
yum list installed | grep kernel
yum -y update kernel-tools-libs kernel-tools
yum list installed | grep kernel

起動Kernelのバージョン確認
既存Kernelの削除
現在インストールされているKernel関連のパッケージの確認
tools類のアップデート*2
現在インストールされているKernel関連のパッケージの再確認

2-4.elrepo-kernelの常時有効化
vi /etc/yum.repos.d/elrepo.repo

[elrepo-kernel]
name=ELRepo.org Community Enterprise Linux Kernel Repository - el7
baseurl=http://elrepo.org/linux/kernel/el7/$basearch/
        http://mirrors.coreix.net/elrepo/kernel/el7/$basearch/
        http://mirror.rackspace.com/elrepo/kernel/el7/$basearch/
        http://repos.lax-noc.com/elrepo/kernel/el7/$basearch/
        http://mirror.ventraip.net.au/elrepo/kernel/el7/$basearch/
mirrorlist=http://mirrors.elrepo.org/mirrors-elrepo-kernel.el7
enabled=1 #0→1に修正
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elrepo.org
protect=0
2-5.tools類のアップグレードとdevel&headersのインストール
yum swap kernel-tools-libs kernel-tools -- kernel-ml-tools-libs kernel-ml-tools
yum -y install kernel-ml-devel kernel-ml-headers
yum list installed | grep kernel

kernel-*とkernel-ml-*のswap
kernel-ml-develとkernel-ml-headersのインストール
現在インストールされているKernel関連のパッケージの確認

# yum list installed | grep kernel
kernel-ml.x86_64                   4.18.4-1.el7.elrepo            @elrepo-kernel
kernel-ml-devel.x86_64             4.18.4-1.el7.elrepo            @elrepo-kernel
kernel-ml-headers.x86_64           4.18.4-1.el7.elrepo            @elrepo-kernel
kernel-ml-tools.x86_64             4.18.4-1.el7.elrepo            @elrepo-kernel
kernel-ml-tools-libs.x86_64        4.18.4-1.el7.elrepo            @elrepo-kernel

上記のような出力になっていれば完了です。

3.事前準備

3-1.セキュリティ設定の無効化

firewalldとSELinuxを無効化します。

systemctl disable firewalld

vi /etc/selinux/config
で開いて
SELINUX=disabled
にして保存。
3-2.grubの設定

grubにHugePageの設定追加

vi /etc/default/grub

GRUB_CMDLINE_LINUX=の行末に追加
default_hugepagesz=1G hugepagesz=1G hugepages=8

保存後、grubに反映
grub2-mkconfig -o /etc/grub2.cfg
3-3.NICIPアドレス設定

nmcli devなどでMellanox製NICのデバイス名を確認の上、IPアドレスを設定してください。今回構築するNVMe-oF targetはRoCEv2で動作するため、NICにはIPアドレスが必要となります。

nmcli connection add type ethernet autoconnect yes con-name ens1 ifname ens1
nmcli connection modify ens1 ipv4.method manual ipv4.addresses 192.168.20.200/24
nmcli connection up ens1
3-4.numactl-develのインストール

dpdkがnumactl-develやopenssl-devel を必要とするようなのでインストール。

yum -y install numactl-devel openssl-devel 

reboot

再起動後にHugePageを確認。
# cat /proc/meminfo | grep ^Huge
HugePages_Total:       8
HugePages_Free:        8
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:    1048576 kB

4.SPDKのビルド

4-1.gitインストールからspdkのビルドまで

以下を流し込んでください。

yum -y install git && \
cd /usr/src && \
git clone https://github.com/spdk/spdk && \
cd spdk && \
git submodule update --init && \
scripts/pkgdep.sh && \
./configure --with-rdma --enable-debug && \
make

gitインストール
/usr/srcにcd
spdkのソースをgitから取得
/usr/src/spdkにcd*3
アップデート
必要なパッケージのインストール
makeファイル生成
ビルド

iSCSI Targetと異なる点
--with-rdmaは必須となります。
また、nvmf_tgtを起動した際に「-L」オプションでDebugログが見れるようになるため、--enable-debugを追加しています。正常起動しているのか?固まっているのか?を見極めるためにも、あった方がいいかなと思います。

4-2.unittest.shの実行

ビルドが完了したら、最後に各モジュールのテストを実施してみてください。

./test/unit/unittest.sh

 出力結果省略

=====================
All unit tests passed
=====================
WARN: lcov not installed or SPDK built without coverage!
WARN: neither valgrind nor ASAN is enabled!

多数の出力結果が表示されますが、最後に「All unit tests passed」と表示されればOKです。
Warringが2件表示されてますが、気にせず先に進んでください。

5.spdkのnvmf.confファイル設定

5-1.設定ファイルの作成
# cd /usr/src/spdk/app/nvmf_tgt
# vi nvmf.conf

[Global]
  ReactorMask 0x0F

[Nvmf]
  MaxQueuesPerSession 4
  MaxQueueDepth 1024
  AcceptorPollRate 10000

[Nvme]
  TransportId "trtype:PCIe traddr:0000:04:00.0" Nvme0
  RetryCount 4
  TimeoutUsec 1
  ActionOnTimeout None
  AdminPollRate 100000
  HotplugEnable No

[Subsystem1]
  NQN nqn.2016-06.io.spdk:cnode1
  Listen RDMA 192.168.20.200:4791
  AllowAnyHost Yes
  Host nqn.2016-06.io.spdk:init
  SN SPDK00000000000001
  Namespace Nvme0n1 1

ReactorMaskの掛け方は最後に詳細を記載したいと思います。
わからなければ、コメントアウトしても問題ありません。

TransportIdの確認方法
私の場合、Samsung SSD 250GB 970を使用したため、lspciで以下のようにgrepしました。

# lspci |grep Samsung
04:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd Device a808

SSDのbsf(bus slot function)番号が判明したら、頭にDomain番号「0000:」を付けてください。
サンプルconfがspdk/etc/spdk/nvmf.conf.inにあるので、これをコピーしてnvmf.confを作成してもよいと思います。

5-2.setup.shの起動

カーネル上での制御からSPDK(正確にはDPDK)上での制御に移行します。
ますはステータス確認から。

# cd /usr/src/spdk
# scripts/setup.sh status
Hugepages
node     hugesize     free /  total
node0   1048576kB        8 /      8
node1   1048576kB        8 /      8
NVMe devices
BDF		Numa Node	Driver name		Device name
0000:03:00.0	0		nvme			nvme0
I/OAT DMA
BDF		Numa Node	Driver Name
0000:00:04.0	0		ioatdma
0000:20:04.0	1		ioatdma
0000:00:04.1	0		ioatdma
0000:20:04.1	1		ioatdma
0000:00:04.2	0		ioatdma
0000:20:04.2	1		ioatdma
0000:00:04.3	0		ioatdma
0000:20:04.3	1		ioatdma
0000:00:04.4	0		ioatdma
0000:20:04.4	1		ioatdma
0000:00:04.5	0		ioatdma
0000:20:04.5	1		ioatdma
0000:00:04.6	0		ioatdma
0000:20:04.6	1		ioatdma
0000:00:04.7	0		ioatdma
0000:20:04.7	1		ioatdma
virtio
BDF		Numa Node	Driver Name		Device Name

現在はカーネル上のnvmeやioatdmaドライバで制御していることがわかります。

オプション無しでsetup.shを実行すると、uio_pci_genericに移行します。*4

# scripts/setup.sh
0000:03:00.0 (144d a808): nvme -> uio_pci_generic
0000:00:04.0 (8086 3c20): ioatdma -> uio_pci_generic
0000:20:04.0 (8086 3c20): ioatdma -> uio_pci_generic
0000:00:04.1 (8086 3c21): ioatdma -> uio_pci_generic
0000:20:04.1 (8086 3c21): ioatdma -> uio_pci_generic
0000:00:04.2 (8086 3c22): ioatdma -> uio_pci_generic
0000:20:04.2 (8086 3c22): ioatdma -> uio_pci_generic
0000:00:04.3 (8086 3c23): ioatdma -> uio_pci_generic
0000:20:04.3 (8086 3c23): ioatdma -> uio_pci_generic
0000:00:04.4 (8086 3c24): ioatdma -> uio_pci_generic
0000:20:04.4 (8086 3c24): ioatdma -> uio_pci_generic
0000:00:04.5 (8086 3c25): ioatdma -> uio_pci_generic
0000:20:04.5 (8086 3c25): ioatdma -> uio_pci_generic
0000:00:04.6 (8086 3c26): ioatdma -> uio_pci_generic
0000:20:04.6 (8086 3c26): ioatdma -> uio_pci_generic
0000:00:04.7 (8086 3c27): ioatdma -> uio_pci_generic
0000:20:04.7 (8086 3c27): ioatdma -> uio_pci_generic

以下のようになっていれば、OKです。

# scripts/setup.sh status
Hugepages
node     hugesize     free /  total
node0   1048576kB        0 /      1
node1   1048576kB        0 /      1
NVMe devices
BDF             Numa Node       Driver name             Device name
0000:03:00.0    0               uio_pci_generic         -
I/OAT DMA
BDF             Numa Node       Driver Name
0000:00:04.0    0               uio_pci_generic
0000:20:04.0    1               uio_pci_generic
0000:00:04.1    0               uio_pci_generic
0000:20:04.1    1               uio_pci_generic
0000:00:04.2    0               uio_pci_generic
0000:20:04.2    1               uio_pci_generic
0000:00:04.3    0               uio_pci_generic
0000:20:04.3    1               uio_pci_generic
0000:00:04.4    0               uio_pci_generic
0000:20:04.4    1               uio_pci_generic
0000:00:04.5    0               uio_pci_generic
0000:20:04.5    1               uio_pci_generic
0000:00:04.6    0               uio_pci_generic
0000:20:04.6    1               uio_pci_generic
0000:00:04.7    0               uio_pci_generic
0000:20:04.7    1               uio_pci_generic
virtio
BDF             Numa Node       Driver Name             Device Name
5-3.Targetプログラムの実行

/usr/src/spdkのパス上で以下を実行。

app/nvmf_tgt/nvmf_tgt -c app/nvmf_tgt/nvmf.conf

以下、出力結果。
# app/nvmf_tgt/nvmf_tgt -c app/nvmf_tgt/nvmf.conf
Starting SPDK v18.07-pre / DPDK 18.02.0 initialization...
[ DPDK EAL parameters: nvmf -c 0x0F --file-prefix=spdk_pid23820 ]
EAL: Detected 8 lcore(s)
EAL: Multi-process socket /var/run/.spdk_pid23820_unix
EAL: Probing VFIO support...
app.c: 530:spdk_app_start: *NOTICE*: Total cores available: 4
reactor.c: 718:spdk_reactors_init: *NOTICE*: Occupied cpu socket mask is 0x1
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 1 on socket 0
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 2 on socket 0
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 3 on socket 0
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 0 on socket 0
EAL: PCI device 0000:03:00.0 on NUMA socket 0
EAL:   probe driver: 144d:a808 spdk_nvme
rdma.c:1454:spdk_nvmf_rdma_create: *ERROR*: rdma_create_event_channel() failed, No such device
Segmentation fault (core dumped)

初回起動時に赤文字のエラーを吐く場合は、一度サーバを再起動してみてください。

nvmf_tgtはフォアグラウンドで稼働してしまうため、上記出力(赤文字以外の出力)でプロンプトが停止したように見えますが、nvmf targetは正常に起動できています。
iscsi targetとは異なり、-b(バックグラウンド)オプションはないようです。

また、Debugオプションを使用したい場合、まずは-Lに指定可能な引数を確認するため、-hオプションでnvmf_tgtを起動してあげてください。

# app/nvmf_tgt/nvmf_tgt -h
app/nvmf_tgt/nvmf_tgt [options]
options:
 -c config  config file (default /usr/local/etc/nvmf/nvmf.conf)
 -d         disable coredump file enabling
 -e mask    tracepoint group mask for spdk trace buffers (default 0x0)
 -g         force creating just one hugetlbfs file
 -h         show this usage
 -i shared memory ID (optional)
 -m mask    core mask for DPDK
 -n channel number of memory channels used for DPDK
 -p core    master (primary) core for DPDK
 -q         disable notice level logging to stderr
 -r         RPC listen address (default /var/tmp/spdk.sock)
 -s size    memory size in MB for DPDK (default: all hugepage memory)
 -u         disable PCI access.
 -w         wait for RPCs to initialize subsystems
 -B addr    pci addr to blacklist
 -R         unlink huge files after initialization
 -W addr    pci addr to whitelist (-B and -W cannot be used at the same time)
 -L flag    enable debug log flag (all, aio, bdev, bdev_malloc, bdev_null, bdev_nvme, blob, blob_rw, copy_ioat, gpt_parse, ioat, log, lvol, lvolrpc, nbd, nvme, nvmf, rdma, reactor, rpc, vbdev_gpt, vbdev_lvol, vbdev_passthru, vbdev_split, virtio, virtio_blk, virtio_dev, virtio_pci, virtio_user)

実際にDebugオプションを付けて起動した場合は、こんな感じです。
このように起動した後、Initiatorからアクセスすると、Targetの動きがわかります。

# app/nvmf_tgt/nvmf_tgt -L nvme -L nvmf -L rdma -c app/nvmf_tgt/nvmf.conf

6.NVMe-oF Initiatorからのアクセス

6-1.Initiator側の事前準備

Initiatorのインストール

yum -y install nvme-cli

modprobe実施

modprobe ib_core
modprobe ib_umad
modprobe ib_uverbs
modprobe iw_cm
modprobe rdma_cm
modprobe rdma_ucm
modprobe mlx4_core
modprobe mlx4_ib
modprobe nvme_rdma

上記のmodprobeが正常終了していれば、以下のように/dev/nvme-fabricsが追加されているハズです。

# ls /dev/
autofs           fuse              net                 rtc       tty13  tty30  tty48  tty8     vcs6
block            hpet              network_latency     rtc0      tty14  tty31  tty49  tty9     vcsa
bsg              hpilo             network_throughput  sda       tty15  tty32  tty5   ttyS0    vcsa1
btrfs-control    hugepages         null                sda1      tty16  tty33  tty50  ttyS1    vcsa2
bus              hwrng             nvme-fabrics        sda2      tty17  tty34  tty51  ttyS2    vcsa3
centos           infiniband        nvram               sg0       tty18  tty35  tty52  ttyS3    vcsa4
char             initctl           port                sg1       tty19  tty36  tty53  uhid     vcsa5
console          input             ppp                 shm       tty2   tty37  tty54  uinput   vcsa6
core             ipmi0             ptmx                snapshot  tty20  tty38  tty55  urandom  vfio
cpu              kmsg              ptp0                snd       tty21  tty39  tty56  usbmon0  vga_arbiter
cpu_dma_latency  kvm               ptp1                stderr    tty22  tty4   tty57  usbmon1  vhci
cuse             lightnvm          ptp2                stdin     tty23  tty40  tty58  usbmon2  vhost-net
disk             log               ptp3                stdout    tty24  tty41  tty59  usbmon3  vhost-vsock
dm-0             loop-control      ptp4                tty       tty25  tty42  tty6   vcs      watchdog
dm-1             mapper            ptp5                tty0      tty26  tty43  tty60  vcs1     watchdog0
dri              mcelog            ptp6                tty1      tty27  tty44  tty61  vcs2     zero
fb0              mem               pts                 tty10     tty28  tty45  tty62  vcs3
fd               memory_bandwidth  random              tty11     tty29  tty46  tty63  vcs4
full             mqueue            raw                 tty12     tty3   tty47  tty7   vcs5

Discover実施Initiator側

# nvme discover -t rdma -a 192.168.20.200 -s 4791

Discovery Log Number of Records 1, Generation counter 4
=====Discovery Log Entry 0======
trtype:  rdma
adrfam:  ipv4
subtype: nvme subsystem
treq:    not specified
portid:  0
trsvcid: 4791
subnqn:  nqn.2016-06.io.spdk:cnode1
traddr:  192.168.20.200
rdma_prtype: not specified
rdma_qptype: connected
rdma_cms:    rdma-cm
rdma_pkey: 0x0000

Discover実施Target側

# app/nvmf_tgt/nvmf_tgt -L nvmf -c app/nvmf_tgt/nvmf.conf

request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x01 cid 1
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xbeee9c800 key 0x10110 len 0x400
ctrlr.c: 321:spdk_nvmf_ctrlr_connect: *INFO*: recfmt 0x0 qid 0 sqsize 31
ctrlr.c: 323:spdk_nvmf_ctrlr_connect: *INFO*: Connect data:
ctrlr.c: 324:spdk_nvmf_ctrlr_connect: *INFO*:   cntlid:  0xffff
ctrlr.c: 332:spdk_nvmf_ctrlr_connect: *INFO*:   hostid: 0259e14b-3479-4850-be97-f6006ffa084c ***
ctrlr.c: 349:spdk_nvmf_ctrlr_connect: *INFO*:   subnqn: "nqn.2014-08.org.nvmexpress.discovery"
ctrlr.c: 366:spdk_nvmf_ctrlr_connect: *INFO*:   hostnqn: "nqn.2014-08.org.nvmexpress:uuid:eb63ddbc-c01f-4435-8e0b-bbbaf22639f2"
ctrlr.c: 389:spdk_nvmf_ctrlr_connect: *INFO*: Connect Admin Queue for controller ID 0xffff
ctrlr.c: 207:spdk_nvmf_ctrlr_create: *INFO*: cap 0x20010103ff
ctrlr.c: 208:spdk_nvmf_ctrlr_create: *INFO*: vs 0x10300
ctrlr.c: 209:spdk_nvmf_ctrlr_create: *INFO*: cc 0x0
ctrlr.c: 210:spdk_nvmf_ctrlr_create: *INFO*: csts 0x0
ctrlr.c: 104:ctrlr_add_qpair_and_update_rsp: *INFO*: connect capsule response: cntlid = 0x0001
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=1 cdw0=0x00000001 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 1, offset 0x0
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: cap
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x20010103ff
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x010103ff rsvd1=32 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x00 cid 26
ctrlr.c: 598:spdk_nvmf_property_set: *INFO*: size 0, offset 0x14, value 0x460001
ctrlr.c: 608:spdk_nvmf_property_set: *INFO*: name: cc
ctrlr.c: 438:nvmf_prop_set_cc: *INFO*: cur CC: 0x00000000
ctrlr.c: 439:nvmf_prop_set_cc: *INFO*: new CC: 0x00460001
ctrlr.c: 449:nvmf_prop_set_cc: *INFO*: Property Set CC Enable!
ctrlr.c: 480:nvmf_prop_set_cc: *INFO*: Prop Set IOSQES = 6 (64 bytes)
ctrlr.c: 487:nvmf_prop_set_cc: *INFO*: Prop Set IOCQES = 4 (16 bytes)
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x1c
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: csts
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x1
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000001 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x8
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: vs
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x10300
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00010300 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 1, offset 0x0
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: cap
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x20010103ff
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x010103ff rsvd1=32 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x06 fuse 0 cid 26 nsid 0 cdw10 0x00000001
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xc026a1000 key 0x10111 len 0x1000
ctrlr.c:1172:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ctrlr data: maxcmd 0x400
ctrlr.c:1173:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: sgls data: 0x100005
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x02 fuse 0 cid 26 nsid 0 cdw10 0x00030070
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xc09c46000 key 0x10112 len 0x10
ctrlr.c:1082:spdk_nvmf_ctrlr_get_log_page: *INFO*: Get log page: LID=0x70 offset=0x0 len=0x10
ctrlr_discovery.c:  63:nvmf_update_discovery_log: *INFO*: Generating log page for genctr 4
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x02 fuse 0 cid 26 nsid 0 cdw10 0x01ff0070
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xbdc640000 key 0x10113 len 0x800
ctrlr.c:1082:spdk_nvmf_ctrlr_get_log_page: *INFO*: Get log page: LID=0x70 offset=0x0 len=0x800
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x00 cid 8
ctrlr.c: 598:spdk_nvmf_property_set: *INFO*: size 0, offset 0x14, value 0x464001
ctrlr.c: 608:spdk_nvmf_property_set: *INFO*: name: cc
ctrlr.c: 438:nvmf_prop_set_cc: *INFO*: cur CC: 0x00460001
ctrlr.c: 439:nvmf_prop_set_cc: *INFO*: new CC: 0x00464001
ctrlr.c: 463:nvmf_prop_set_cc: *INFO*: Property Set CC Shutdown 01b!
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=8 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 8
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x1c
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: csts
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x8
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=8 cdw0=0x00000008 rsvd1=0 status=0x0000

Connect実施Initiator側
iSCSIのときとは違い、Successなどは出力されません。

# nvme connect -t rdma -n nqn.2016-06.io.spdk:cnode1 -a 192.168.20.200 -s 4791

Connect実施Target側
Connectが完了すると、定期的にKeepaliveメッセージが流れます。

# nvme connect -t rdma -n nqn.2016-06.io.spdk:cnode1 -a 192.168.20.200 -s 4791

request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x01 cid 0
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xbeee99000 key 0x10111 len 0x400
ctrlr.c: 321:spdk_nvmf_ctrlr_connect: *INFO*: recfmt 0x0 qid 0 sqsize 31
ctrlr.c: 323:spdk_nvmf_ctrlr_connect: *INFO*: Connect data:
ctrlr.c: 324:spdk_nvmf_ctrlr_connect: *INFO*:   cntlid:  0xffff
ctrlr.c: 332:spdk_nvmf_ctrlr_connect: *INFO*:   hostid: 07ca1c45-8f62-493f-a732-7fd3c721f6f9 ***
ctrlr.c: 349:spdk_nvmf_ctrlr_connect: *INFO*:   subnqn: "nqn.2016-06.io.spdk:cnode1"
ctrlr.c: 366:spdk_nvmf_ctrlr_connect: *INFO*:   hostnqn: "nqn.2014-08.org.nvmexpress:uuid:eb63ddbc-c01f-4435-8e0b-bbbaf22639f2"
ctrlr.c: 389:spdk_nvmf_ctrlr_connect: *INFO*: Connect Admin Queue for controller ID 0xffff
ctrlr.c: 207:spdk_nvmf_ctrlr_create: *INFO*: cap 0x20010103ff
ctrlr.c: 208:spdk_nvmf_ctrlr_create: *INFO*: vs 0x10300
ctrlr.c: 209:spdk_nvmf_ctrlr_create: *INFO*: cc 0x0
ctrlr.c: 210:spdk_nvmf_ctrlr_create: *INFO*: csts 0x0
ctrlr.c: 104:ctrlr_add_qpair_and_update_rsp: *INFO*: connect capsule response: cntlid = 0x0001
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=0 cdw0=0x00000001 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 1, offset 0x0
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: cap
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x20010103ff
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x010103ff rsvd1=32 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x00 cid 26
ctrlr.c: 598:spdk_nvmf_property_set: *INFO*: size 0, offset 0x14, value 0x460001
ctrlr.c: 608:spdk_nvmf_property_set: *INFO*: name: cc
ctrlr.c: 438:nvmf_prop_set_cc: *INFO*: cur CC: 0x00000000
ctrlr.c: 439:nvmf_prop_set_cc: *INFO*: new CC: 0x00460001
ctrlr.c: 449:nvmf_prop_set_cc: *INFO*: Property Set CC Enable!
ctrlr.c: 480:nvmf_prop_set_cc: *INFO*: Prop Set IOSQES = 6 (64 bytes)
ctrlr.c: 487:nvmf_prop_set_cc: *INFO*: Prop Set IOCQES = 4 (16 bytes)
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x1c
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: csts
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x1
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000001 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x8
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: vs
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x10300
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00010300 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 1, offset 0x0
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: cap
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x20010103ff
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x010103ff rsvd1=32 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x06 fuse 0 cid 26 nsid 0 cdw10 0x00000001
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xc026a2000 key 0x10112 len 0x1000
ctrlr.c:1172:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ctrlr data: maxcmd 0x400
ctrlr.c:1173:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: sgls data: 0x100005
ctrlr_bdev.c:  73:spdk_nvmf_subsystem_bdev_io_type_supported: *INFO*: All devices in Subsystem nqn.2016-06.io.spdk:cnode1 support io_type 3
ctrlr_bdev.c:  73:spdk_nvmf_subsystem_bdev_io_type_supported: *INFO*: All devices in Subsystem nqn.2016-06.io.spdk:cnode1 support io_type 9
ctrlr.c:1215:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: ioccsz 0x104
ctrlr.c:1217:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: iorcsz 0x1
ctrlr.c:1219:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: icdoff 0x0
ctrlr.c:1221:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: ctrattr 0x0
ctrlr.c:1223:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: msdbd 0x1
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x02 fuse 0 cid 26 nsid 4294967295 cdw10 0x03ff0005
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xc026a3000 key 0x10113 len 0x1000
ctrlr.c:1082:spdk_nvmf_ctrlr_get_log_page: *INFO*: Get log page: LID=0x05 offset=0x0 len=0x1000
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000

~・~一部省略~・~

ctrlr.c:1548:spdk_nvmf_ctrlr_keep_alive: *INFO*: Keep Alive
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=0 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x18 fuse 0 cid 0 nsid 0 cdw10 0x00000000
ctrlr.c:1548:spdk_nvmf_ctrlr_keep_alive: *INFO*: Keep Alive
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=0 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: o

List確認Initiator側

# nvme list
Node             SN                   Model                                    Namespace Usage                      Format           FW Rev
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1     SPDK00000000000001   SPDK bdev Controller                     1         250.06  GB / 250.06  GB    512   B +  0 B   18.10

List確認Target側

request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x06 fuse 0 cid 18 nsid 0 cdw10 0x00000001
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xbe37f8000 key 0x10120 len 0x1000
ctrlr.c:1172:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ctrlr data: maxcmd 0x400
ctrlr.c:1173:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: sgls data: 0x100005
ctrlr_bdev.c:  73:spdk_nvmf_subsystem_bdev_io_type_supported: *INFO*: All devices in Subsystem nqn.2016-06.io.spdk:cnode1 support io_type 3
ctrlr_bdev.c:  73:spdk_nvmf_subsystem_bdev_io_type_supported: *INFO*: All devices in Subsystem nqn.2016-06.io.spdk:cnode1 support io_type 9
ctrlr.c:1215:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: ioccsz 0x104
ctrlr.c:1217:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: iorcsz 0x1
ctrlr.c:1219:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: icdoff 0x0
ctrlr.c:1221:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: ctrattr 0x0
ctrlr.c:1223:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: msdbd 0x1
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=18 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x06 fuse 0 cid 18 nsid 1 cdw10 0x00000000
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xbe37f8000 key 0x10121 len 0x1000
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=18 cdw0=0x00000000 rsvd1=0 status=0x0000

bdevとして認識されていることを確認*5

# lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda               8:0    0 136.8G  0 disk
tqsda1            8:1    0     1G  0 part /boot
mqsda2            8:2    0 135.7G  0 part
  tqcentos-root 253:0    0 131.7G  0 lvm  /
  mqcentos-swap 253:1    0     4G  0 lvm  [SWAP]
sr0              11:0    1  1024M  0 rom
nvme0n1         259:0    0 232.9G  0 disk

Disconnect実施Initiator側

# nvme disconnect -n "nqn.2016-06.io.spdk:cnode1"
NQN:nqn.2016-06.io.spdk:cnode1 disconnected 1 controller(s)

Disconnect実施Target側

request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x00 cid 18
ctrlr.c: 598:spdk_nvmf_property_set: *INFO*: size 0, offset 0x14, value 0x464001
ctrlr.c: 608:spdk_nvmf_property_set: *INFO*: name: cc
ctrlr.c: 438:nvmf_prop_set_cc: *INFO*: cur CC: 0x00460001
ctrlr.c: 439:nvmf_prop_set_cc: *INFO*: new CC: 0x00464001
ctrlr.c: 463:nvmf_prop_set_cc: *INFO*: Property Set CC Shutdown 01b!
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=18 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 18
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x1c
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: csts
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x8
request.c:  92:spdk_nvmf_request_complete: *INFO*: cpl: cid=18 cdw0=0x00000008 rsvd1=0 status=0x0000

上記InitiatorとTargetのやり取りをPcapしたファイルを以下にアップしておきます。
roce02.pcapng

あとは、iSCSI Targetと同様に動作しますので、Initiator側でmkfsするなり、fioで速度測定するなりご自由にどうぞ。

以上です。

7.補足その1:ReactorMaskについて

ReactorMaskとは、PMD(Poll Mode Driver)で専有させるCPUコアを明示的に指定するためのものです。NVMe-oF targetの場合、SSDが管理されているNUMA socket*6と同じNUMA socket上のCPUコアを明示的に指定することでパフォーマンスが向上します。このため、ReactorMaskでPMDが専有するCPUコアを明示的に指定することが重要となってきます。

それでは、CPUコアを明示的に指定する方法を具体例を交えて解説します。

lscpuの結果

# lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
Thread(s) per core:    1
Core(s) per socket:    4
Socket(s):             2
NUMA node(s):          2
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 45
Model name:            Intel(R) Xeon(R) CPU E5-2407 0 @ 2.20GHz
Stepping:              7
CPU MHz:               1200.000
CPU max MHz:           2200.0000
CPU min MHz:           1200.0000
BogoMIPS:              4389.14
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              10240K
NUMA node0 CPU(s):     0-3
NUMA node1 CPU(s):     4-7
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb tpr_shadow vnmi flexpriority ept vpid xsaveopt ibpb ibrs stibp dtherm arat pln pts spec_ctrl intel_stibp

今回使用したサーバ(DL360e)の場合、2ソケット、Hyperスレッド無し、4コアなので、トータル8コアあります。
さらに、NUMA socketの割り当ては以下のようになっています。
 NUMA socket(node)0:0-3コア
 NUMA socket(node)1:4-7コア

また、nvmf_tgtの実行結果から、SSDがNUMA socket(node)0で動作していることがわかります。

# app/nvmf_tgt/nvmf_tgt -c app/nvmf_tgt/nvmf.conf
Starting SPDK v18.07-pre / DPDK 18.02.0 initialization...
[ DPDK EAL parameters: nvmf -c 0x0E --file-prefix=spdk_pid17014 ]
EAL: Detected 8 lcore(s)
EAL: Multi-process socket /var/run/.spdk_pid17014_unix
EAL: Probing VFIO support...
app.c: 530:spdk_app_start: *NOTICE*: Total cores available: 3
reactor.c: 718:spdk_reactors_init: *NOTICE*: Occupied cpu socket mask is 0x1
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 2 on socket 0
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 3 on socket 0
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 1 on socket 0
EAL: PCI device 0000:03:00.0 on NUMA socket 0
EAL:   probe driver: 144d:a808 spdk_nvme

上記結果より、PMDに専有させたいコアは「NUMA socket(node)0:0-3」となります。

このときのReactorMaskの指定方法は、

[Global]
  ReactorMask 0x0F

となります。

CPUコアの並び順は以下のようになっています。

7654 3210

lscpuの結果より、
 7654がNUMA socket(node)1
 3210がNUMA socket(node)0
となります。

ReactorMaskのうち、0x0Fを2進数に変換すると、以下のようになります。

16進数
0x0F
2進数
0000 1111

CPUコアの並びと2進数に変換したReactorMaskを合わせると

7654 3210
0000 1111

となり、ReactorMaskのうち「1」が立っているCPUがPMDに専有されます。
考え方としては、SubnetMaskと同様ですね。

今回の場合、あまり意味はないですが、例えば、奇数番号のコアだけを使用したい場合は、

CPUコア
7654 3210
2進数
1010 1010
16進数
0xAA

となります。

8.補足その2:fioの実施結果

fioを実施してみました。
結果、10Gbpsをフルに使用したパフォーマンスを出してくれました。
但し、Samsung SSD 250GB 970 EVOのシーケンシャルリードの公称値が3400MBps(27.2Gbps)なので、Mellanox製NICボトルネックとなっています。
これについては、40GNIC or 100GNICで試せたらいいなと考えています。

fio設定ファイル

# cat seqread4.fio

[global]
filename=/dev/nvme0n1
group_reporting=1
direct=1
ioengine=libaio

[seqread4]
readwrite=read
blocksize=32m
size=10g
numjobs=2
loops=2

fio実行結果

# fio seqread4.fio

seqread4: (g=0): rw=read, bs=(R) 32.0MiB-32.0MiB, (W) 32.0MiB-32.0MiB, (T) 32.0MiB-32.0MiB, ioengine=libaio, iodepth=1
...
fio-3.1
Starting 2 processes
Jobs: 2 (f=2): [R(2)][100.0%][r=1185MiB/s,w=0KiB/s][r=37,w=0 IOPS][eta 00m:00s]
seqread4: (groupid=0, jobs=2): err= 0: pid=13105: Thu Aug 23 15:26:47 2018
   read: IOPS=36, BW=1167MiB/s (1224MB/s)(40.0GiB/35097msec)
    slat (usec): min=26489, max=30909, avg=28159.67, stdev=289.25
    clat (usec): min=13362, max=27098, avg=26659.48, stdev=449.47
     lat (usec): min=40354, max=56431, avg=54820.49, stdev=422.94
    clat percentiles (usec):
     |  1.00th=[25560],  5.00th=[26346], 10.00th=[26346], 20.00th=[26608],
     | 30.00th=[26608], 40.00th=[26608], 50.00th=[26608], 60.00th=[26608],
     | 70.00th=[26870], 80.00th=[26870], 90.00th=[26870], 95.00th=[26870],
     | 99.00th=[26870], 99.50th=[26870], 99.90th=[27132], 99.95th=[27132],
     | 99.99th=[27132]
   bw (  KiB/s): min=588646, max=656673, per=49.95%, avg=596887.99, stdev=20330.41, samples=140
   iops        : min=   17, max=   20, avg=18.20, stdev= 0.61, samples=140
  lat (msec)   : 20=0.08%, 50=99.92%
  cpu          : usr=0.02%, sys=3.94%, ctx=21806, majf=0, minf=1107
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwt: total=1280,0,0, short=0,0,0, dropped=0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
   READ: bw=1167MiB/s (1224MB/s), 1167MiB/s-1167MiB/s (1224MB/s-1224MB/s), io=40.0GiB (42.9GB), run=35097-35097msec

Disk stats (read/write):
  nvme0n1: ios=325850/0, merge=0/0, ticks=6298513/0, in_queue=6471868, util=99.76%

1224MBps=9792Mbps

9.最後に

以下のサイトを参考にさせて頂きました。
SPDK: NVMe over Fabrics Target
Intel SPDK NVMe-oF Target Performance Tuning. Part 2: Preparing testing environment | StarWind Blog
CentOS7でelrepoリポジトリを有効化してkernel-mlを入れる - Qiita

kernelのBugにヒットした際、仕方なく4.17系でリビルドして何とかPcapに成功したのですが、リビルドの手順も合せてこのBlogに記載するのは本編からブレるため、4.18.4がリリースされるまで待ちました。ただ予想以上に早くリリースして頂いたので、コミッターの方にはとても感謝しています。

この記事によるとNVMe市場は2020年までに570億ドル(日本円で6兆円超)規模の市場になるらしいです。
blog.calsoftinc.com

なので、早めにキャッチアップ&修得しておいて損はない技術かなと思っています。

また、以前FCoEの勉強をしていたため、RoCEは前々から気になっていました。
metonymical.hatenablog.com
FCoEはあっという間に消えてしまいましたが、RoCEはNVMe-oFのうちover Fabricの部分で残りそうな予感がしています。
oEやoCEの部分では既に規格があります*7が、RoCEv2がいいかも?と思った点は、それに加えて、IP&UDPを乗せたところだと思っています。
EthernetやIPの世界では既に400Gbpsのスイッチも市場に出始めていますし、100G×32ポート程度のスイッチであれば100万円ちょい&100GBase-SR4のQSFP28でも1万円ちょいで購入できます。
このような状況を踏まえれば、EthernetやIPをFabricとして使用したとしても、高性能なNVMe対応ストレージに対して、充分な性能を担保できるのでは?と考えています。また、導入コストやスケーラビリティの点を含めて考えても、IBやFCと対等に渡り合えるのではないかと考えています。
なので、例えば、IP CLOSネットワーク上でRoCEv2を動作させて、障害時の切替検証や複数InitiatorからTargetへのアクセス時における負荷分散など、といったシチュエーションにおける最適なネットワーク設計を検討していきたいと考えています。

*1:あえて、-yオプションを付けていません。万が一、4.18系Kernelで、4.18.4-1以前のバージョンだった場合、リポジトリからミラーサイトのURLを全て削除してください。4.18.1-1や4.18.3-1などの場合、uio_pci_genericのBugを踏むことになりTargetを起動できません。

*2:この後、yum swapしますので、最新までアップデートしてください。

*3:ここのパスが基点となります。

*4:GRUB_CMDLINE_LINUX=の行末に、intel_iommu=on iommu=pt pci=realloc も追記すると、uioの代わりにvfio-pciで稼働するようになりますが、HPのアドバイザリにヒットしたため、今回はuio_pci_genericで行っています。また、Kernel4.18系のうち、4.18.3-1以前のバージョンの場合、uio_pci_genericに移行できず、空欄となるBugを踏むことになります。

*5:setup.shの実行直後にlsblkを実行すると、nvmeはカーネルの制御から解放されているためlsblkでは見えなくなります。その後、Initiator側からConnectして、lsblkを実行すると、nvme0n1が見えるようになります。

*6:NUMA socketとかNUMA nodeと言ったりします。厳密には異なりますが、今回は同じ用語だと考えてください。

*7:DCBXとして、802.1Qau(Congestion Notification)、802.1Qaz(Enhanced Transmission Selection)、802.1Qbb(Priority-based Flow Control)に加えて、SPB、TRILLなどがあります。

MPLS over GRE over IPSec with IKEv2

Cisco891FJ×2台構成でMPLS over GRE over IPSec with IKEv2を実装してみました。

IPSec with IKEv2の部分について
トンネルの暗号化はcrypto mapを使うとACLを書くのが大変なので、AWSのVGWでもサンプルConfigが公開されているipsec profileにしています。
また、isakmpはちょっぴり不安なのでIKEv2に変更しています。

MPLS over GREの部分について
MP-BGPにてMPLSを使うため、tunnel mode ipsec ipv4ではなく、多少のオーバーヘッドは掛かりますが、デフォルトのtunnel mode gre ip(DefaultなのでConfig上は表示されません)にしました。

1.構成

f:id:metonymical:20180714182611j:plain

RTAとRTBがCisco891FJとなっています。
Versionは15.7(3)M2ですが、多少古くても大丈夫だと思います。
Internetを模倣するために、RTAとRTBの間にCat3560Eを挟んでConnected同士でRoutingしています。

四の五の説明するより、Configを見てもらった方が早いと思います。

2.RTAのConfig

!
hostname RTA
!
ip cef
!
ip vrf r1
 rd 10.0.0.1:1
 route-target export 65000:1
 route-target import 65000:1
!
ip vrf r2
 rd 10.0.0.1:2
 route-target export 65000:2
 route-target import 65000:2
!
!
crypto ikev2 proposal ikev2prop
 encryption aes-cbc-256
 integrity sha256
 group 14
!
crypto ikev2 policy ikev2poli
 proposal ikev2prop
!
crypto ikev2 keyring ikev2key
 peer RTB
  address 2.2.2.2
  pre-shared-key PASSWORD
!
crypto ikev2 profile ikev2prof
 match identity remote address 2.2.2.2 255.255.255.255 
 identity local address 1.1.1.1
 authentication remote pre-share
 authentication local pre-share
 keyring local ikev2key
 lifetime 3600
!
!
crypto ipsec transform-set LAB-TS esp-aes 256 esp-sha256-hmac 
 mode tunnel
!
crypto ipsec profile LAB-ipsec-profile
 set transform-set LAB-TS
 set ikev2-profile ikev2prof
!
!
interface Tunnel100
 ip address 10.0.0.1 255.255.255.0
 mpls bgp forwarding
 mpls ip
 tunnel source 1.1.1.1
 tunnel destination 2.2.2.2
 tunnel path-mtu-discovery
 tunnel protection ipsec profile LAB-ipsec-profile
!
interface GigabitEthernet8
 ip address 1.1.1.1 255.255.255.0
 duplex auto
 speed auto
!
interface Vlan11
 ip vrf forwarding r1
 ip address 192.168.11.1 255.255.255.0
!
interface Vlan12
 ip vrf forwarding r2
 ip address 192.168.12.1 255.255.255.0
!
!
router bgp 65000
 bgp router-id 10.0.0.1
 bgp log-neighbor-changes
 neighbor 10.0.0.2 remote-as 65001
 neighbor 10.0.0.2 update-source Tunnel100
 !
 address-family ipv4
  neighbor 10.0.0.2 activate
  neighbor 10.0.0.2 soft-reconfiguration inbound
 exit-address-family
 !
 address-family vpnv4
  neighbor 10.0.0.2 activate
  neighbor 10.0.0.2 send-community both
 exit-address-family
 !
 address-family ipv4 vrf r1
  network 192.168.11.0
 exit-address-family
 !
 address-family ipv4 vrf r2
  network 192.168.12.0
 exit-address-family
!
!
mpls ldp router-id Tunnel100
!
ip route 0.0.0.0 0.0.0.0 1.1.1.2
!

3.RTBのConfig

!
hostname RTB
!
ip cef
!
ip vrf r1
 rd 10.0.0.2:1
 route-target export 65000:1
 route-target import 65000:1
!
ip vrf r2
 rd 10.0.0.2:2
 route-target export 65000:2
 route-target import 65000:2
!
!
crypto ikev2 proposal ikev2prop
 encryption aes-cbc-256
 integrity sha256
 group 14
!
crypto ikev2 policy ikev2poli
 proposal ikev2prop
!
crypto ikev2 keyring ikev2key
 peer RTA
  address 1.1.1.1
  pre-shared-key PASSWORD
!
crypto ikev2 profile ikev2prof
 match identity remote address 1.1.1.1 255.255.255.255 
 identity local address 2.2.2.2
 authentication remote pre-share
 authentication local pre-share
 keyring local ikev2key
 lifetime 3600
!
!
crypto ipsec transform-set LAB-TS esp-aes 256 esp-sha256-hmac 
 mode tunnel
!
crypto ipsec profile LAB-ipsec-profile
 set transform-set LAB-TS
 set ikev2-profile ikev2prof
!
!
interface Tunnel100
 ip address 10.0.0.2 255.255.255.0
 mpls bgp forwarding
 mpls ip
 tunnel source 2.2.2.2
 tunnel destination 1.1.1.1
 tunnel path-mtu-discovery
 tunnel protection ipsec profile LAB-ipsec-profile
!
interface GigabitEthernet8
 ip address 2.2.2.2 255.255.255.0
 duplex auto
 speed auto
!
interface Vlan13
 ip vrf forwarding r1
 ip address 192.168.13.1 255.255.255.0
!
interface Vlan14
 ip vrf forwarding r2
 ip address 192.168.14.1 255.255.255.0
!
!
router bgp 65001
 bgp router-id 10.0.0.2
 bgp log-neighbor-changes
 neighbor 10.0.0.1 remote-as 65000
 neighbor 10.0.0.1 update-source Tunnel100
 !
 address-family ipv4
  neighbor 10.0.0.1 activate
  neighbor 10.0.0.1 soft-reconfiguration inbound
 exit-address-family
 !
 address-family vpnv4
  neighbor 10.0.0.1 activate
  neighbor 10.0.0.1 send-community both
 exit-address-family
 !
 address-family ipv4 vrf r1
  network 192.168.13.0
 exit-address-family
 !
 address-family ipv4 vrf r2
  network 192.168.14.0
 exit-address-family
!
!
mpls ldp router-id Tunnel100
!
ip route 0.0.0.0 0.0.0.0 2.2.2.1
!

以上です。

4.最後に

以下のサイトを参考にさせて頂きました。
http://www.networking-forum.com/viewtopic.php?t=28459#

今回は検証できていませんが、複数拠点で構成する場合、tunnel mode gre multipointでもイケる気がしています。そうすることで(Ciscoの)FlexVPNとしての実装もできそうな感じがします。

先にも書きましたが、tunnel mode ipsec ipv4について少々補足します。ipsec ipv4にした場合、VTI(VirtualTunnelInterface)を使用することになるため、オーバーヘッドが減少するそうです。しかし、今回の場合は、ipsec ipv4を入れると、MPLSヘッダのついたパケットがIPパケットとして(当然のことながら)認識されないためトンネルを越えられなくなります。このため、Defaultのgre ipとしています。

もう一点、rdとroute-targetについて補足します。

ip vrf r1
 rd 10.0.0.1:1
 route-target export 65000:1
 route-target import 65000:1

rdは一般的に双方のRTで合わせますが、異なっていても問題ありません。
しかし、route-targetは双方のRTで一致していないといけないため、65000:1としていますが、(router bgpに記載のASNと一致させなくてもよいという意味で)10:1とかでも問題ありません。

CentOS7でCephブロックデバイスの構築

CentOS7上でCephブロックデバイスを構築しました。
Cephは、オブジェクト、ブロック、ファイルストレージを1つの統一されたシステムで独自に提供してくれます。今回はこのうちブロックデバイスの構築を実施します。

Windows版VMWareWorkstation12上でCentOS7.5を3台稼働させて構築しましたが、同様の手順でベアメタルサーバ上にも構築できます。

1.環境

1-1.VMWare
筐体                             : 自作PC
CPU                           : Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
VMWare              : VMware(R) Workstation 12 Pro 12.5.9 build-7535481  
OS                               : CentOS7.5(1804)
Kernel                           : 3.10.0-862.el7.x86_64
Installed Environment Groups     : Server with GUI

WinおよびVMWare環境は以下の画像で確認してもらった方が良いかもしれません。
Win環境
f:id:metonymical:20180529200243j:plain
VMWare環境
f:id:metonymical:20180707151258p:plain
50GBのOS用とは別に100GB×2のHDDを追加しています。
これをマスター(ceph00)として、クローンを3台分(ceph01,ceph02,ceph03)作成しておきます。

1-3.全体の流れ

各ノード共通設定
cephのインストール
cephブロックデバイス設定

2.各ノード共通設定

3台のノード全てに同一の設定を行っていきます。

2-1.セキュリティ設定の無効化

firewalldとSELinuxを無効化します。

systemctl disable firewalld

vi /etc/selinux/config
で開いて
SELINUX=disabled
にして保存。

また、ここでは触れませんが、chronyなどで時刻同期を行ってください。

2-2.パスワード無しsshログイン設定
#ssh-keygen -N "" -t rsa

Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):  #そのままEnter
Created directory '/root/.ssh'.
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:oaQzt0YznhT9W2ZjSQtqSNgT8+OE2y5zUp7J9++aCeM root@ceph01.md.jp
The key's randomart image is:
+---[RSA 2048]----+
|      o          |
|     o *         |
|    . B * . .    |
|     + X = o o   |
|    + X S . O    |
|     B @ o * .   |
|      O B =      |
|     . = o + o   |
|          E =+o  |
+----[SHA256]-----+

次に3台のノードにそれぞれ鍵をコピーしていきます。
このとき、ホスト名もしくはFQDNで各ノードにアクセスできるようにhostsファイルもしくはDNSサーバの設定を実施しておいてください。

#ssh-copy-id root@ceph01.md.jp

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host 'ceph01.md.jp (192.168.11.121)' can't be established.
ECDSA key fingerprint is SHA256:nC6u8EYKElp2okhoYNCqJatrYlCzWi8ZtRudjt9VHQA.
ECDSA key fingerprint is MD5:6e:45:af:09:1a:be:10:af:8f:31:b9:f1:81:2a:2a:58.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@ceph01.md.jp's password:  #パスワードを入力

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@ceph01.md.jp'"
and check to make sure that only the key(s) you wanted were added.

上記と同様に他2台分のカギもコピー
#ssh-copy-id root@ceph02.md.jp
#ssh-copy-id root@ceph03.md.jp
2-4.ceph-deployのインストール

ceph-deployをインストールしておくことにより、3台のノードを1台のadminノードから全てコントロールすることが可能となるようです。

# mkdir /root/ceph
# cd /root/ceph/

# yum -y install ceph-deploy

3.cephのインストール

ここからはadminノード(ceph01)のみで操作を行います。

3-1.OSDとして登録

OSDノードとして登録

# ceph-deploy new ceph01.md.jp ceph02.md.jp ceph03.md.jp
3-2.ceph.confの設定

各ノード間通信を行うNWアドレスを追加

# vi ceph.conf

[global]
fsid = fad4e572-b6cb-47e7-b38e-ed41fa1545c0
mon_initial_members = ceph01, ceph02, ceph03
mon_host = 192.168.11.121,192.168.11.122,192.168.11.123
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
public network = 192.168.11.0/24
3-3.cephのインストール

何も問題がなければ、以下のコマンド一発でインストール可能なのですが、途中で止まる時がちょいちょいありました。なので、エラー吐いて止まった場合は、「5.トラブルシュート」を参照してください。

# ceph-deploy install --release mimic ceph01.md.jp ceph02.md.jp ceph03.md.jp
3-4.インストール後の設定

監視ノードの初期化
設定とadminキーを各ノードに展開
各ノードのディスクをOSDとして登録

# ceph-deploy mon create-initial

# ceph-deploy admin ceph01.md.jp ceph02.md.jp ceph03.md.jp

# ceph-deploy osd create ceph01.md.jp --data /dev/sdb && \
ceph-deploy osd create ceph01.md.jp --data /dev/sdc && \
ceph-deploy osd create ceph02.md.jp --data /dev/sdb && \
ceph-deploy osd create ceph02.md.jp --data /dev/sdc && \
ceph-deploy osd create ceph03.md.jp --data /dev/sdb && \
ceph-deploy osd create ceph03.md.jp --data /dev/sdc
3-5.管理マネージャの起動

ディレクトリと空ファイル作成
mgr.adminのキー生成
空ファイルにキーを追記
管理マネージャ起動

# mkdir /var/lib/ceph/mgr/ceph-admin
# touch /var/lib/ceph/mgr/ceph-admin/keyring
# ceph --cluster ceph auth get-or-create mgr.admin mon 'allow profile mgr' osd 'allow *' mds 'allow *'
[mgr.admin]
        key = AQAXT0BbUiPaCRAAwqwc/7UEzfzB8Ts9qDNf2g==

#上記の鍵を空ファイルに追記して保存
# vi /var/lib/ceph/mgr/ceph-admin/keyring

[mgr.admin]
        key = AQAXT0BbUiPaCRAAwqwc/7UEzfzB8Ts9qDNf2g==

# ceph-mgr -i admin
3-6.起動確認
#ps -C ceph-mgr
    PID TTY          TIME CMD
  58425 ?        00:00:00 ceph-mgr

# ceph -s
  cluster:
    id:     fad4e572-b6cb-47e7-b38e-ed41fa1545c0
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum ceph01,ceph02,ceph03
    mgr: admin(active)
    osd: 6 osds: 6 up, 6 in
 
  data:
    pools:   0 pools, 0 pgs
    objects: 0 objects, 0 bytes
    usage:   6163 MB used, 593 GB / 599 GB avail
    pgs:     
 

4.cephブロックデバイス設定

4-1.プール作成およびイメージ作成

poolの作成
poolの初期化
イメージの作成
イメージとブロックデバイスマッピング

# ceph osd pool create pool01 128
pool 'pool01' created

# rbd pool init pool01

# rbd create vol01 -p pool01 --size 10G --image-feature layering

# rbd map vol01 -p pool01
/dev/rbd0 

pool01という名前のプール作成
pool01を初期化
pool01上にvol01という名前の10GB空イメージを作成
pool01上のvol01をブロックデバイスとしてマッピングすることで、/dev/rbd0というデバイスが追加される。
あとは、通常のディスク(ブロックデバイス)と同様にfdiskやmkfsを構成することが可能です。

4-2.各種情報の確認

プールの確認
プール内イメージの確認
イメージの情報(容量など)確認
ブロックデバイスの確認

# rados lspools
pool01
# rbd ls pool01
vol01
# rbd info pool01/vol01
rbd image 'vol01':
	size 10240 MB in 2560 objects
	order 22 (4096 kB objects)
	block_name_prefix: rbd_data.103f74b0dc51
	format: 2
	features: layering
	flags: 
	create_timestamp: Sat Jul  7 13:35:56 2018

# lsblk
NAME                                                                   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                                                                      8:0    0   50G  0 disk 
tqsda1                                                                   8:1    0    1G  0 part /boot
mqsda2                                                                   8:2    0   49G  0 part 
  tqcentos-root                                                        253:0    0   47G  0 lvm  /
  mqcentos-swap                                                        253:1    0    2G  0 lvm  [SWAP]
sdb                                                                      8:16   0  100G  0 disk 
mqceph--fab7c5a8--f170--4a59--93b4--68948d9c91a1-osd--block--9024dc2b--ef0e--403b--bbd1--eec740127c24
                                                                       253:2    0  100G  0 lvm  
sdc                                                                      8:32   0  100G  0 disk 
mqceph--4fc60b45--ac73--470f--beac--ea58fcb809ee-osd--block--ecff0a57--aee5--4119--9769--0156b634ad34
                                                                       253:3    0  100G  0 lvm  
sr0                                                                     11:0    1 1024M  0 rom  
rbd0                                                                   252:0    0   10G  0 disk 
4-3.プールやイメージの削除方法

Default設定ではプール削除などができないようになっているため少々厄介です。

イメージのアンマップ
イメージの削除(1つのプールに複数のイメージがある場合は全イメージを削除)
pool削除の許可設定を追加
ceph-monのリスタート
poolの削除禁止設定を無効化
プールの削除

# rbd unmap -p pool01 --image vol01

# rbd remove -p pool01 --image vol01
Removing image: 100% complete...done.

#vi /etc/ceph/ceph.conf
最終行に以下を追記

[mon]
mon allow pool delete = true

# systemctl restart ceph-mon.target

# for pool in $(rados lspools); do ceph osd pool set $pool nodelete false; done
set pool 1 nodelete to false

# ceph osd pool delete pool01 pool01 --yes-i-really-really-mean-it

5.トラブルシュート

私の場合、なぜか?土日にインストールコマンドを実行すると、YumのDL時に途中で止まる事象を確認しました。
途中で止まってしまう箇所は以下の通り。

以下、抜粋
[ceph01.md.jp][DEBUG ] Dependencies Resolved
[ceph01.md.jp][DEBUG ] 
[ceph01.md.jp][DEBUG ] ================================================================================
[ceph01.md.jp][DEBUG ]  Package                 Arch     Version                        Repository
[ceph01.md.jp][DEBUG ]                                                                            Size
[ceph01.md.jp][DEBUG ] ================================================================================
[ceph01.md.jp][DEBUG ] Installing:
[ceph01.md.jp][DEBUG ]  ceph                    x86_64   2:12.2.5-0.el7                 Ceph     3.0 k
[ceph01.md.jp][DEBUG ]  ceph-radosgw            x86_64   2:12.2.5-0.el7                 Ceph     3.8 M
[ceph01.md.jp][DEBUG ] Installing for dependencies:
[ceph01.md.jp][DEBUG ]  ceph-base               x86_64   2:12.2.5-0.el7                 Ceph     3.9 M
[ceph01.md.jp][DEBUG ]  ceph-common             x86_64   2:12.2.5-0.el7                 Ceph      15 M
[ceph01.md.jp][DEBUG ]  ceph-mds                x86_64   2:12.2.5-0.el7                 Ceph     3.6 M
[ceph01.md.jp][DEBUG ]  ceph-mgr                x86_64   2:12.2.5-0.el7                 Ceph     3.6 M
[ceph01.md.jp][DEBUG ]  ceph-mon                x86_64   2:12.2.5-0.el7                 Ceph     5.0 M
[ceph01.md.jp][DEBUG ]  ceph-osd                x86_64   2:12.2.5-0.el7                 Ceph      13 M
[ceph01.md.jp][DEBUG ]  ceph-selinux            x86_64   2:12.2.5-0.el7                 Ceph      20 k
[ceph01.md.jp][DEBUG ]  leveldb                 x86_64   1.12.0-11.el7                  epel     161 k
[ceph01.md.jp][DEBUG ]  libbabeltrace           x86_64   1.2.4-3.el7                    epel     147 k
[ceph01.md.jp][DEBUG ]  libcephfs2              x86_64   2:12.2.5-0.el7                 Ceph     432 k
[ceph01.md.jp][DEBUG ]  libradosstriper1        x86_64   2:12.2.5-0.el7                 Ceph     330 k
[ceph01.md.jp][DEBUG ]  librgw2                 x86_64   2:12.2.5-0.el7                 Ceph     1.7 M
[ceph01.md.jp][DEBUG ]  lttng-ust               x86_64   2.4.1-4.el7                    epel     176 k
[ceph01.md.jp][DEBUG ]  mailcap                 noarch   2.1.41-2.el7                   base      31 k
[ceph01.md.jp][DEBUG ]  pyOpenSSL               x86_64   0.13.1-3.el7                   base     133 k
[ceph01.md.jp][DEBUG ]  python-babel            noarch   0.9.6-8.el7                    base     1.4 M
[ceph01.md.jp][DEBUG ]  python-beaker           noarch   1.5.4-10.el7                   base      80 k
[ceph01.md.jp][DEBUG ]  python-cephfs           x86_64   2:12.2.5-0.el7                 Ceph      82 k
[ceph01.md.jp][DEBUG ]  python-cherrypy         noarch   3.2.2-4.el7                    base     422 k
[ceph01.md.jp][DEBUG ]  python-flask            noarch   1:0.10.1-4.el7                 extras   204 k
[ceph01.md.jp][DEBUG ]  python-itsdangerous     noarch   0.23-2.el7                     extras    24 k
[ceph01.md.jp][DEBUG ]  python-jinja2           noarch   2.7.2-2.el7                    base     515 k
[ceph01.md.jp][DEBUG ]  python-mako             noarch   0.8.1-2.el7                    base     307 k
[ceph01.md.jp][DEBUG ]  python-markupsafe       x86_64   0.11-10.el7                    base      25 k
[ceph01.md.jp][DEBUG ]  python-paste            noarch   1.7.5.1-9.20111221hg1498.el7   base     866 k
[ceph01.md.jp][DEBUG ]  python-pecan            noarch   0.4.5-2.el7                    epel     255 k
[ceph01.md.jp][DEBUG ]  python-prettytable      noarch   0.7.2-3.el7                    base      37 k
[ceph01.md.jp][DEBUG ]  python-rados            x86_64   2:12.2.5-0.el7                 Ceph     172 k
[ceph01.md.jp][DEBUG ]  python-rbd              x86_64   2:12.2.5-0.el7                 Ceph     105 k
[ceph01.md.jp][DEBUG ]  python-requests         noarch   2.6.0-1.el7_1                  base      94 k
[ceph01.md.jp][DEBUG ]  python-rgw              x86_64   2:12.2.5-0.el7                 Ceph      73 k
[ceph01.md.jp][DEBUG ]  python-simplegeneric    noarch   0.8-7.el7                      epel      12 k
[ceph01.md.jp][DEBUG ]  python-singledispatch   noarch   3.4.0.2-2.el7                  epel      18 k
[ceph01.md.jp][DEBUG ]  python-tempita          noarch   0.5.1-6.el7                    base      33 k
[ceph01.md.jp][DEBUG ]  python-urllib3          noarch   1.10.2-5.el7                   base     102 k
[ceph01.md.jp][DEBUG ]  python-webob            noarch   1.2.3-7.el7                    base     202 k
[ceph01.md.jp][DEBUG ]  python-webtest          noarch   1.3.4-6.el7                    base     102 k
[ceph01.md.jp][DEBUG ]  python-werkzeug         noarch   0.9.1-2.el7                    extras   562 k
[ceph01.md.jp][DEBUG ]  userspace-rcu           x86_64   0.7.16-1.el7                   epel      73 k
[ceph01.md.jp][DEBUG ] Updating for dependencies:
[ceph01.md.jp][DEBUG ]  librados2               x86_64   2:12.2.5-0.el7                 Ceph     2.9 M
[ceph01.md.jp][DEBUG ]  librbd1                 x86_64   2:12.2.5-0.el7                 Ceph     1.1 M
[ceph01.md.jp][DEBUG ] 
[ceph01.md.jp][DEBUG ] Transaction Summary
[ceph01.md.jp][DEBUG ] ================================================================================
[ceph01.md.jp][DEBUG ] Install  2 Packages (+39 Dependent packages)
[ceph01.md.jp][DEBUG ] Upgrade             (  2 Dependent packages)
[ceph01.md.jp][DEBUG ] 
[ceph01.md.jp][DEBUG ] Total download size: 60 M
[ceph01.md.jp][DEBUG ] Downloading packages:
[ceph01.md.jp][DEBUG ] No Presto metadata available for Ceph

ここで5分待たされて、以下の表示で止まる。

[ceph01.md.jp][WARNIN] No data was received after 300 seconds, disconnecting...
[ceph01.md.jp][INFO  ] Running command: ceph --version
[ceph01.md.jp][ERROR ] Traceback (most recent call last):
[ceph01.md.jp][ERROR ]   File "/usr/lib/python2.7/site-packages/ceph_deploy/lib/vendor/remoto/process.py", line 119, in run
[ceph01.md.jp][ERROR ]     reporting(conn, result, timeout)
[ceph01.md.jp][ERROR ]   File "/usr/lib/python2.7/site-packages/ceph_deploy/lib/vendor/remoto/log.py", line 13, in reporting
[ceph01.md.jp][ERROR ]     received = result.receive(timeout)
[ceph01.md.jp][ERROR ]   File "/usr/lib/python2.7/site-packages/ceph_deploy/lib/vendor/remoto/lib/vendor/execnet/gateway_base.py", line 704, in receive
[ceph01.md.jp][ERROR ]     raise self._getremoteerror() or EOFError()
[ceph01.md.jp][ERROR ] RemoteError: Traceback (most recent call last):
[ceph01.md.jp][ERROR ]   File "/usr/lib/python2.7/site-packages/ceph_deploy/lib/vendor/remoto/lib/vendor/execnet/gateway_base.py", line 1036, in executetask
[ceph01.md.jp][ERROR ]     function(channel, **kwargs)
[ceph01.md.jp][ERROR ]   File "", line 12, in _remote_run
[ceph01.md.jp][ERROR ]   File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
[ceph01.md.jp][ERROR ]     errread, errwrite)
[ceph01.md.jp][ERROR ]   File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
[ceph01.md.jp][ERROR ]     raise child_exception
[ceph01.md.jp][ERROR ] OSError: [Errno 2] No such file or directory
[ceph01.md.jp][ERROR ] 
[ceph01.md.jp][ERROR ] 
[ceph_deploy][ERROR ] RuntimeError: Failed to execute command: ceph --version

よくよく動きを観察していると、ceph-radosgwやceph-osdのDLが遅すぎてタイムアウトするような状態となっている事象でした。一台目のノードで引っ掛かると、他のノードにおいても同様に上記の箇所で都度停止してしまいます。
このため、少々ダサい方法ですが各ノードに対して手動でインストールします。

5-1.各ノードでインストールの実行

各ノード(ceph01,ceph02,ceph03)にsshでログインしてください。

ceph01

yumが動作したままになっている可能性が高いのでKillしてください。
# ps -aux | grep yum
root       2038  0.7  7.2 1020036 135832 pts/0  S    12:51   0:02 /usr/bin/python /usr/bin/yum -y install ceph ceph-radosgw
root       2109  0.0  0.0 112704   972 pts/0    R+   12:57   0:00 grep --color=auto yum

# kill -9 2038

再度、Yum実行
# yum -y install ceph ceph-radosgw

さらに、以下のように停止する場合があるため、再々度、Yum実行
Trying other mirror.

Error downloading packages:
  2:ceph-osd-12.2.5-0.el7.x86_64: [Errno 256] No more mirrors to try.

# yum -y install ceph-osd

最初に抜粋した箇所で止まった場合、ceph02やceph03は、まだceph-deploy installが行われていません。このため、一度個別にceph-deploy installを実行し、エラーは吐かせた後で、ceph01と同様の対処を行います。この作業はceph02とceph03で並行して行っても構いません。

ceph02

# ceph-deploy install --release mimic ceph02.md.jp

# ps -aux | grep yum
# kill -9 {PID}

# yum -y install ceph ceph-radosgw

ceph03

# ceph-deploy install --release mimic ceph03.md.jp

# ps -aux | grep yum
# kill -9 {PID}

# yum -y install ceph ceph-radosgw

ceph01

# ceph-deploy install --release mimic ceph01.md.jp ceph02.md.jp ceph03.md.jp

~略~
[ceph01.md.jp][DEBUG ] Complete!
[ceph01.md.jp][INFO  ] Running command: ceph --version
[ceph01.md.jp][DEBUG ] ceph version 13.2.0 (79a10589f1f80dfe21e8f9794365ed98143071c4) mimic (stable)
~略~
[ceph02.md.jp][DEBUG ] Complete!
[ceph02.md.jp][INFO  ] Running command: ceph --version
[ceph02.md.jp][DEBUG ] ceph version 13.2.0 (79a10589f1f80dfe21e8f9794365ed98143071c4) mimic (stable)
~略~
[ceph03.md.jp][DEBUG ] Complete!
[ceph03.md.jp][INFO  ] Running command: ceph --version
[ceph03.md.jp][DEBUG ] ceph version 13.2.0 (79a10589f1f80dfe21e8f9794365ed98143071c4) mimic (stable)

最後にceph01にて再度同じコマンドを実行します。
正常に完了すると、上記の通り各ノードごとにComplete!のメッセージが表示されます。

以上です。

6.最後に

以下のサイトを参考にさせて頂きました。
Ceph(luminous)のインストール方法
删除pool error的解决方法 - sisimi_2017 - 博客园
Protecting your Ceph pools against removal or property changes – Widodh

今回はCephをブロックデバイスとして使う場合の構築方法でしたが、これ以外にもオブジェクトストレージやファイルシステムとして使う場合の構築方法もあるため、一つのストレージシステムで全てをまかなえるのが良いなと思っています。
というのもありますが、一番の理由としてCephはspdkのTargetとして使えるためです。

CentOS7 + SPDKでiSCSI target構築

CentOS7上でSPDKをビルドして、iSCSI targetを構築しました。
なお、CentOS7はDL360上で稼働させた場合と、Windows版VMWareWorkstation12上で稼働させた場合の両方で構築することができました。

1.環境

1-1.DL360
筐体                             : ProLiant DL360p Gen8
System ROM                       : P71 01/22/2018
CPU                           : Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz 
OS                               : CentOS7.5(1804)
Kernel                           : 3.10.0-862.el7.x86_64
Installed Environment Groups     : Minimal Install
SPDK                         : v18.07-pre
DPDK                             : v18.02.0
1-2.VMWare
筐体                             : 自作PC
CPU                           : Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
VMWare              : VMware(R) Workstation 12 Pro 12.5.9 build-7535481  
OS                               : CentOS7.5(1804)
Kernel                           : 3.10.0-862.el7.x86_64
Installed Environment Groups     : Minimal Install
SPDK                         : v18.07-pre
DPDK                             : v18.02.0

WinおよびVMWare環境は以下の画像で確認してもらった方が良いかもしれません。
Win環境
f:id:metonymical:20180529200243j:plain
VMWare環境
f:id:metonymical:20180527224812j:plain
HugePageを使うためメモリは多めで。
SPDKはDPDKのPMDを使うためCPUのコア数も多めで。
さらに、
 Intel VT-x/EPT またはAMD-V-RVIを仮想化
 CPUパフォーマンスカウンタを仮想化
にもチェックを入れました。
50GBのOS用とは別に200GBのiSCSI Target用のHDDを追加しています。

1-3.全体の流れ

事前準備
SPDKのビルド
SPDKのiscsi.conf設定

2.事前準備

2-1.セキュリティ設定の無効化

firewalldとSELinuxを無効化します。

systemctl disable firewalld

vi /etc/selinux/config
で開いて
SELINUX=disabled
にして保存。
2-2.grubの設定

grubにHugePageの設定追加

vi /etc/default/grub

GRUB_CMDLINE_LINUX=の行末に追加
default_hugepagesz=1G hugepagesz=1G hugepages=4

保存後、grubに反映
grub2-mkconfig -o /etc/grub2.cfg
2-3.numactl-develのインストール

dpdkがnumactl-develを必要とするようなので念のためインストール。

yum -y install numactl-devel
yum -y install openssl-devel #2018/7/20追記 *1

reboot

再起動後にHugePageを確認。
# cat /proc/meminfo | grep ^Huge
HugePages_Total:       4
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:    1048576 kB

3.SPDKのビルド

spdkはdpdkと違い至れり尽くせりでpkgdep.shを実行することにより、spdkのビルドに必要なパッケージなどを自動でインストールし依存関係を解消してくれます。

3-1.gitインストールからspdkのビルドまで

少々乱暴ですが、以下を流し込んでしまって問題ありません。

yum -y install git && \
cd /usr/src && \
git clone https://github.com/spdk/spdk && \
cd spdk && \
git submodule update --init && \
scripts/pkgdep.sh && \
./configure && \
make

gitインストール
/usr/srcにcd
spdkのソースをgitから取得
/usr/src/spdkにcd*2
アップデート
必要なパッケージのインストール
makeファイル生成
ビルド

ちなみに、make前に

./configure --help

とすると、追加オプションを表示できます。
例えば、

./configure --with-rdma

とすることで、RDMAにも対応してくれるようです。

3-2.unittest.shの実行

ビルドが完了したら、最後に各モジュールのテストを実施してみてください。

./test/unit/unittest.sh

 出力結果省略

=====================
All unit tests passed
=====================
WARN: lcov not installed or SPDK built without coverage!
WARN: neither valgrind nor ASAN is enabled!

多数の出力結果が表示されますが、最後に「All unit tests passed」と表示されればOKです。
Warringが2件表示されてますが、気にせず先に進んでください。

4.spdkのiscsi.confファイル設定

4-1.設定ファイルの作成
# cd /usr/src/spdk/app/iscsi_tgt
# vi iscsi.conf

[global]
 ReactorMask 0x1
 LogFacility "local7"

[iSCSI]
 NodeBase "iqn.2016-06.io.spdk"
 AuthFile /usr/local/etc/spdk/auth.conf
 MinConnectionsPerCore 1
 MinConnectionIdleInterval 5000
 Timeout 30
 DiscoveryAuthMethod Auto
 DefaultTime2Wait 2
 DefaultTime2Retain 60
 ImmediateData Yes
 ErrorRecoveryLevel 0

[Rpc]                  #AIO(Asynchronous I/O)が生成されなかったためRPCを有効化しています。
 Enable Yes
 Listen 127.0.0.1

[AIO]
 AIO /dev/sdb AIO0 512          #追加した200GBのHDDを指定しています。   

[PortalGroup1]
 Portal DA1 192.168.11.208:3260     #自身のIPアドレス or 0.0.0.0:3260でも大丈夫です。

[InitiatorGroup1]
 InitiatorName ANY
 Netmask 192.168.11.0/24         #アクセス許可するNWアドレスを指定します。

[TargetNode1]
 TargetName disk1
 TargetAlias "Data Disk1"
 Mapping PortalGroup1 InitiatorGroup1
 AuthMethod Auto
 AuthGroup AuthGroup1
 UseDigest Auto
 LUN0 AIO0                #AIO0をLUN0としてTargetNodeを起動します。
 QueueDepth 128
4-2.Targetプログラムの実行

ファイルの保存が完了したら、先ほどcdした /usr/src/spdk/app/iscsi_tgt のパス上で以下を実行。

./iscsi_tgt -c iscsi.conf

以下、出力結果。
# ./iscsi_tgt -c iscsi.conf
Starting SPDK v18.07-pre / DPDK 18.02.0 initialization...
[ DPDK EAL parameters: iscsi -c 0x1 --file-prefix=spdk_pid22562 ]
EAL: Detected 4 lcore(s)
EAL: Multi-process socket /var/run/.spdk_pid22562_unix
EAL: Probing VFIO support...
app.c: 521:spdk_app_start: *NOTICE*: Total cores available: 1
reactor.c: 669:spdk_reactors_init: *NOTICE*: Occupied cpu socket mask is 0x1
reactor.c: 453:_spdk_reactor_run: *NOTICE*: Reactor started on core 0 on socket 0

iscsi_tgtのデフォルト動作ではフォアグラウンドで稼働してしまうため、上記出力でプロンプトが停止したように見えますが、iSCSI targetは正常に起動できています。
ちなみに、上記はVMWareの場合で、DL360の場合は EAL: NUMA socket 0~ といった表示が複数行出力されますが、iSCSI targetは正常に起動できています。*3
バックグラウンドで動作させたい場合には、-bを付けてください。

./iscsi_tgt -b -c iscsi.conf
4-3.Initiatorからのアクセス

Initiatorのインストール

yum -y install iscsi-initiator-utils

Discovery実施

# iscsiadm -m discovery -t sendtargets -p 192.168.11.208
192.168.11.208:3260,1 iqn.2016-06.io.spdk:disk1

Discovery時のTarget側出力*4

conn.c: 324:spdk_iscsi_conn_construct: *NOTICE*: Launching connection on acceptor thread
iscsi.c:2090:spdk_iscsi_op_login_notify_session_info: *NOTICE*: Login(discovery) from iqn.1994-05.com.redhat:a2f790913987 (192.168.11.209) on (192.168.11.208:3260,1), ISID=23d000000, TSIH=1, CID=0, HeaderDigest=off, DataDigest=off
conn.c: 741:spdk_iscsi_conn_read_data: *ERROR*: spdk_sock_recv() failed, errno 104: Connection reset by peer
conn.c: 456:spdk_iscsi_remove_conn: *NOTICE*: Terminating connections(tsih 1): 0

ログイン実施

# iscsiadm -m node --login
Logging in to [iface: default, target: iqn.2016-06.io.spdk:disk1, portal: 192.168.11.208,3260] (multiple)
Login to [iface: default, target: iqn.2016-06.io.spdk:disk1, portal: 192.168.11.208,3260] successful.

ログイン時のTarget側出力

conn.c: 324:spdk_iscsi_conn_construct: *NOTICE*: Launching connection on acceptor thread
iscsi.c:2078:spdk_iscsi_op_login_notify_session_info: *NOTICE*: Login from iqn.1994-05.com.redhat:a2f790913987 (192.168.11.209) on iqn.2016-06.io.spdk:disk1 tgt_node1 (192.168.11.208:3260,1), ISID=23d000003, TSIH=2, CID=0, HeaderDigest=off, DataDigest=off

Session確認

# iscsiadm -m session
tcp: [1] 192.168.11.208:3260,1 iqn.2016-06.io.spdk:disk1 (non-flash)

bdevとして認識されていることを確認

# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0   50G  0 disk
tqsda1            8:1    0    1G  0 part /boot
mqsda2            8:2    0   49G  0 part
  tqcentos-root 253:0    0   47G  0 lvm  /
  mqcentos-swap 253:1    0    2G  0 lvm  [SWAP]
sdb               8:16   0  200G  0 disk
sr0              11:0    1 1024M  0 rom

ログアウト

# iscsiadm -m node --logout
Logging out of session [sid: 1, target: iqn.2016-06.io.spdk:disk1, portal: 192.168.11.208,3260]
Logout of [sid: 1, target: iqn.2016-06.io.spdk:disk1, portal: 192.168.11.208,3260] successful.

ログアウト時のTarget側出力

iscsi.c:2601:spdk_iscsi_op_logout: *NOTICE*: Logout from iqn.1994-05.com.redhat:a2f790913987 (192.168.11.209) on iqn.2016-06.io.spdk:disk1 tgt_node1 (192.168.11.208:3260,1), ISID=23d000003, TSIH=2, CID=0, HeaderDigest=off, DataDigest=off
conn.c: 456:spdk_iscsi_remove_conn: *NOTICE*: Terminating connections(tsih 2): 0

あとは、通常のiSCSI Targetと同様に動作しますので、Initiator側でmkfsするなり、fioで速度測定するなりご自由にどうぞ。

以上です。

5.最後に

以下のサイトを参考にさせて頂きました。
SPDK: Getting Started
https://www.starwindsoftware.com/blog/intel-spdk-nvme-of-target-performance-tuning-part-2-preparing-testing-environment
CentOS7下编译安装SPDK iSCSI Target - 程序园

SPDKに関する日本語サイトが皆無に等しいのは覚悟の上だったのですが、英語サイトでも出力結果などの詳細解説を記載したサイトが無かったため、ちょっとしんどかったです。3番目の中国サイトがとても助かりました。ありがとうございます。

DPDKに引き続き、取り急ぎSPDKを動作させるところまでは何とかできました。これをベースにNVMe-oFなどにも挑戦したいなと思っています。RoCEv2などにも興味があるのですが、こちらは現在情報収集中です。私は元々ネットワークエンジニアなので、近い将来、主記憶装置も補助記憶装置もすべてがネットワーク上で抽象化orプール化されていくことをイメージしながら、その(大容量)トラフィックをどのように捌いて制御しようか?なんてことを考えつつ、最適なネットワーク設計を模索し続けています。

*1:この後にmakeした際、以下のエラーでコンパイルが停止するため追記しました。/usr/src/spdk/lib/iscsi/md5.h:40:25: fatal error: openssl/md5.h: No such file or directory

*2:このパスがspdkの基点になります。今回紹介した内容以外にも開発用の色々なツールが含まれていますので、興味があればディレクトリを漁ってみるのもいいかもしれません。

*3:このとき、Minimal Installだと、netstatが叩けなかったため、ss -naptで確認したところ、TCP3260のポートが開いていないように見える事象を確認しました。しかし、正常起動している可能性が高いので、試しにinitiator側からDiscoveryしてみてください。私はこの事象で1週間悩み続けました、幻を見ていたのかもしれませんが。。。

*4:エラーが出ていますが気にせず先に進めてください

CentOS7 + pktgen with DPDKでパケットジェネレータ作成

CentOS7上に3台の仮想マシン(CentOS)を稼働させつつDPDKとpktgenをインストールして10Gワイヤーレートが出るパケットジェネレータを作成しました。

1.環境

1-1.母体(ホストOS)
筐体                             : ProLiant DL360p Gen8
System ROM                       : P71 01/22/2018
CPU                           : Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz 
NIC                              : Intel X520-SR2(82599ES)
OS                               : CentOS7.4(1708)
Kernel                           : kernel-3.10.0-693.el7.x86_64
Installed Environment Groups     : Server with GUI
Add-Ons for Selected Environment : Virtualization Client, Virtualization Hypervisor, Virtualization Tools
1-2.仮想マシン(ゲストOS)
筐体                             : 下記参照
System ROM                       : 下記参照
CPU                           : 下記参照 
NIC                              : Intel X520-SR2(82599ES)
OS                               : CentOS7.4(1708)
Kernel                           : kernel-3.10.0-693.el7.x86_64
Installed Environment Groups     : Server with GUI
Add-Ons for Selected Environment : Virtualization Client, Virtualization Hypervisor, Virtualization Tools , Development Tools

筐体、System ROMはホストOSにインストールされているqemu-kvmをそのまま使用。
yum updateやupgradeは未実施。
CPUはNestedKVMを有効化しているため、ホストOSと同一 。
ゲストOSはDPDKやpktgenのビルドが必須なため、Development Toolsを加えています。

1-3.全体の流れ

ホストOSでNestedKVM, SR-IOV, VFIOの設定
ゲストOSでHugePage & IOMMU, VFIOの設定
ゲストOSでDPDKのインストール, igb_uioの設定
ゲストOSでpktgenのインストール
ゲストOS×3台使った負荷試験

2.ホストOSの設定

2-1.NestedKVMの設定

ゲストOS3台の名前はc741, c742, c743とします。

ファイルを新規作成
vi /etc/modprobe.d/kvm-nested.conf
以下を追記して保存。
options kvm_intel nested=1

再読み込み
modprobe -r kvm_intel
modprobe kvm_intel

ゲストOS作成後、以下のようにvirshにて設定
virsh edit c741
<cpu mode='custom' match='exact'>
の行を
<cpu mode='host-passthrough'>
に変更して保存。
2-2.SR-IOVの設定*1

grubにiommuの設定追加

vi /etc/default/grub

GRUB_CMDLINE_LINUX=の行末に追加
intel_iommu=on iommu=pt pci=realloc

保存後、grubに反映
grub2-mkconfig -o /etc/grub2.cfg

起動時にVFが作成されるようrc.localの設定

vi /etc/rc.local

最下行に追加
echo 4 > /sys/class/net/ens1f0/device/sriov_numvfs
echo 4 > /sys/class/net/ens1f1/device/sriov_numvfs
sleep 1
ip link set ens1f0 vf 0 mac 00:11:22:33:44:50
ip link set ens1f0 vf 1 mac 00:11:22:33:44:51
ip link set ens1f0 vf 2 mac 00:11:22:33:44:52
ip link set ens1f0 vf 3 mac 00:11:22:33:44:53
ip link set ens1f1 vf 0 mac 00:11:22:33:44:60
ip link set ens1f1 vf 1 mac 00:11:22:33:44:61
ip link set ens1f1 vf 2 mac 00:11:22:33:44:62
ip link set ens1f1 vf 3 mac 00:11:22:33:44:63
sleep 1
ip link set ens1f0 vf 0 spoofchk off
ip link set ens1f0 vf 1 spoofchk off
ip link set ens1f0 vf 2 spoofchk off
ip link set ens1f0 vf 3 spoofchk off
ip link set ens1f1 vf 0 spoofchk off
ip link set ens1f1 vf 1 spoofchk off
ip link set ens1f1 vf 2 spoofchk off
ip link set ens1f1 vf 3 spoofchk off
exit 0

保存後、実行権限を付与
chmod +x /etc/rc.d/rc.local

VFがホストOSに読み込まれないよう設定

vi /lib/modprobe.d/dist-blacklist.conf

最下行に追加
# ixgbevf driver
blacklist ixgbevf
2-3.VFIOの設定*2
ファイルを新規作成
vi /etc/modprobe.d/vfio_pci.conf
以下を追記して保存
options vfio_pci ids=8086:10ed

こちらも追記
echo 'vfio_pci' > /etc/modules-load.d/vfio_pci.conf

一旦再起動
reboot

8086:10edはlspciで表示されるVFのBus,Slot,Function番号(筐体ごとに異なる)から、lspci -n -s 0008:10.2のようにコマンドを入力することでPCIバイスのベンダID(8086)とデバイスID(10ed)を確認し、ベンダID(8086)とデバイスID(10ed)をVFIO-PCI driverに登録します。

3.ゲストOSの設定

ゲストOSの設定の前にVirt-Managerなどで仮想マシンを作成してください。
その際、CPUは4コア、Memは8GB以上が理想です。また、管理用IP以外にPCI Host Deviceとして、VFを2つ追加してください。
VF追加は、こんな感じのイメージです。*3
f:id:metonymical:20180429101259j:plain

3-1.HugePageとIOMMUの設定
vi /etc/default/grub
GRUB_CMDLINE_LINUX=行の最後に以下を追記。
default_hugepagesz=1G hugepagesz=1G hugepages=8 intel_iommu=on iommu=pt

grub2-mkconfig -o /boot/grub2/grub.cfg
3-2.VFIOの設定
ホストOSと同様です。
ファイルを新規作成
vi /etc/modprobe.d/vfio_pci.conf
以下を追記して保存
options vfio_pci ids=8086:10ed

こちらも追記
echo 'vfio_pci' > /etc/modules-load.d/vfio_pci.conf

一旦シャットダウン
shutdown -h now
3-3.ホストパススルーの設定

ホストOS上でゲストOSに対しネストします。
3台とも実施してください。

virsh edit c741

<cpu mode='custom' match='exact'>
を
<cpu mode='host-passthrough'>
に変更して保存

virsh start c741
ゲストOS起動後、sshログインし、以下のコマンドにて動作確認。
dmesg | grep -i vfio
cat /proc/meminfo | grep ^Huge

4.DPDKのインストール

4-1.ソースのDLとビルド
ソースをDLします。
cd /usr/src
wget http://fast.dpdk.org/rel/dpdk-17.11.1.tar.gz
tar zxvf dpdk-17.11.1.tar.gz
cd dpdk-stable-17.11.1

展開したディレクトリでビルドを実施
make install T=x86_64-native-linuxapp-gcc DESTDIR=/usr/local EXTRA_CFLAGS="-O3"
4-2.igb_uioの設定
ファイルを新規作成
vi /etc/sysconfig/modules/igb_uio.modules

#!/bin/sh

modprobe uio
export KERNEL_VERSION=`uname -r`
insmod /usr/local/lib/modules/${KERNEL_VERSION}/extra/dpdk/igb_uio.ko

保存後に実行権限を付与
chmod +x /etc/sysconfig/modules/igb_uio.modules

一旦再起動
reboot

5.pktgenのインストール

5-1.ソースのDLとビルド
ソースをDLします。
cd /usr/src
wget http://www.dpdk.org/browse/apps/pktgen-dpdk/snapshot/pktgen-3.5.0.tar.gz
tar zxvf pktgen-3.5.0.tar.gz

一旦パスを通す
export RTE_SDK=/usr/src/dpdk-stable-17.11.1
export RTE_TARGET=x86_64-native-linuxapp-gcc

展開したディレクトリでビルドを実施
cd pktgen-3.5.0
make 

6.負荷試験

6-1.DPDKにバインド

SR-IOVでパススルーされたVFをゲストOSのKernelからDPDK管理下におくためにバインドします。

dpdk-devbind --status

Network devices using DPDK-compatible driver
============================================


Network devices using kernel driver
===================================
0000:00:07.0 '82599 Ethernet Controller Virtual Function' if=ins2f0 drv=ixgbevf unused=igb_uio,vfio-pci
0000:00:08.0 '82599 Ethernet Controller Virtual Function' if=ins2f1 drv=ixgbevf unused=igb_uio,vfio-pci

~略~

dpdk-devbind -b igb_uio 0000:00:07.0 0000:00:08.0
dpdk-devbind --status

上記バインドを実施することにより、ゲストOS上のカーネルドライバで動作していたVFがDPDKドライバで動作するようになります。バインド後、ゲストOS上でip link showなどを実施しても、ゲストOS上からVFが認識されなくなります(DPDK管理下におかれます)。

6-2.pktgenの起動
ビルドしたディレクトリに移動*4
cd /usr/src/pktgen-3.5.0

移動後のディレクトリ上で、pktgenの起動
app/x86_64-native-linuxapp-gcc/pktgen -- -m "1.0,2.1"
6-3.pktgenで負荷試験実行

pktgenが起動すると以下のような画面となります。
f:id:metonymical:20180507080855j:plain

プロンプトが
Pktgen:/>となるので、
start all
と入力

これを3台のゲストOSで同時に実施し、
行 Pkts /s Max/Tx
列 TotalRate
のフィールドが5Mppsくらいになると、
ワイヤーレート(14.8Mpps)が出てそうな雰囲気になります。
実際にやるとこんな感じです。
f:id:metonymical:20180507083540j:plain
1台あたり5Mpps超えてるのがかなり怪しいですが・・・
ホストOS単体では思うようにワイヤーレートが出なかったので、この辺りはもう少しチューニングが必要だと考えています。

以上です。

7.最後に

以下のサイトを参考にさせて頂きました。
みらくるブログ — サイバートラスト株式会社
Getting Started with Pktgen — Pktgen 3.2.4 documentation

私自身もまだまだ勉強不足なため、不要な設定が入っている気がしています。具体的にはホストOSでSR-IOVしているため、ホストOS上のVFIO設定は不要なのでは?といったところです。ホストとゲスト、ユーザ空間とカーネル空間のどこで必要とされている設定なのか?など、一度整理してみないとダメだなと考えています。

*1:詳細は過去記事を参照してください。CentOS7でSR-IOV設定 - Metonymical Deflection

*2:詳細は過去記事を参照してください。CentOS7でvThunderのセットアップ - Metonymical Deflection

*3:画像はX540のものですが、X520でも同様です。

*4:cdした/usr/src/pktgen-3.5.0のディレクトリ上からでないとpktgenが起動しませんでした。make時のパスの通し方がダメな気がしています。要調査

CentOS7でvThunderのセットアップ

CentOS7でA10 vThunderのセットアップを実施したため、その手順を記載しておきます。

vthはisoファイルからインストールができるので、c1kvと同様、直観的にインストールできると思います。

以下のサイトで必要事項を入力するとisoやDocがDL可能です。
Get a Trial VThunder Appliance

vthの足回りとしては、virtioとSR-IOVの両方で構成可能ですが、今回はSR-IOVの構成で記載します。
また、インストールした後から諸々変更できるので助かります。
但し、公式Docにはインストール時に設定せよと記載されていますが。。

1.環境

筐体                             : ProLiant DL360e Gen8
System ROM                       : P73 01/22/2018
NIC                              : Intel X540-AT2
OS                               : CentOS7.4(1708)
Kernel                           : kernel-3.10.0-693.21.1.el7.x86_64
Installed Environment Groups     : Server with GUI
Add-Ons for Selected Environment : Virtualization Client, Virtualization Hypervisor, Virtualization Tools 

2.vThunderのインストール

公式Docを読む限り、virt-managerによるGUIでのインストール方法のみとなるようです。
IPMIなどが無ければ、tigervncなどを起動させておきましょう。*1

2-1.事前準備

SR-IOVの設定方法は過去の記事を参照ください。

ここではSR-IOVの設定後、VFIOについて記載します。
公式Docを読む限り、vthではVFIO-PCI Driverを設定せよと記載があります。VFIOとは、IOMMUベースのデバイスに依存しないドライバで、IOMMUに保護された環境で、ユーザ空間への直接デバイスアクセスが可能になるそうです。

以下のRedHatのスライドに説明が記載されています。
https://www.linux-kvm.org/images/b/b4/2012-forum-VFIO.pdf

以下に設定方法を記載します。

[root@ ~]# lspci |grep 540
08:00.0 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
08:00.1 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
08:10.0 Ethernet controller: Intel Corporation X540 Ethernet Controller Virtual Function (rev 01)
08:10.1 Ethernet controller: Intel Corporation X540 Ethernet Controller Virtual Function (rev 01)
08:10.2 Ethernet controller: Intel Corporation X540 Ethernet Controller Virtual Function (rev 01)
08:10.3 Ethernet controller: Intel Corporation X540 Ethernet Controller Virtual Function (rev 01)
[root@ ~]# lspci -n -s 08:10.0
08:10.0 0200: 8086:1515 (rev 01)
[root@ ~]# modprobe vfio_pci
[root@ ~]# echo 8086 1515 > /sys/bus/pci/drivers/vfio-pci/new_id

lspciでVFのBus,Slot,Function番号を表示させる
lspci -n -s でPCIバイスのベンダID(8086)とデバイスID(1515)を確認
ベンダID(8086)とデバイスID(1515)をVFIO-PCI driverに登録

[root@ ~]# ls -Fal /dev/vfio/
total 0
drwxr-xr-x  2 root root      140 Apr 29 12:51 ./
drwxr-xr-x 21 root root     3460 Apr 29 09:28 ../
crw-------  1 root root 241,   0 Apr 29 12:51 56
crw-------  1 root root 241,   1 Apr 29 12:51 57
crw-------  1 root root 241,   2 Apr 29 12:51 58
crw-------  1 root root 241,   3 Apr 29 12:51 59
crw-rw-rw-  1 root root  10, 196 Apr 29 09:27 vfio

/dev/vfio/配下に56~59として登録されていることが確認できます。

余談ですが、0~55はどうなっているのか?を確認したい場合には、以下のようにdmesでgrepをかけてください。ここでは0~5まで表示させましたが、実際は55までズラッと表示されます。

[root@ ~]# dmesg |grep iommu
[    0.000000] Command line: BOOT_IMAGE=/vmlinuz-3.10.0-693.21.1.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet intel_iommu=on iommu=pt pci=realloc
[    0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-3.10.0-693.21.1.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet intel_iommu=on iommu=pt pci=realloc
[    1.270002] iommu: Adding device 0000:00:00.0 to group 0
[    1.270038] iommu: Adding device 0000:00:01.0 to group 1
[    1.270071] iommu: Adding device 0000:00:01.1 to group 2
[    1.270099] iommu: Adding device 0000:00:03.0 to group 3
[    1.270129] iommu: Adding device 0000:00:03.1 to group 4
[    1.270165] iommu: Adding device 0000:00:03.2 to group 5
2-2.virt-managerによるインストール

まずはisoファイルを/var/lib/libvirt/images/直下にコピー

cp ACOS_vThunder_4_1_1-P5_20.iso /var/lib/libvirt/images/

File>New Virtual Machineを選択
f:id:metonymical:20180428192118j:plain

Local install mediaを選択して、Forwardをクリック
f:id:metonymical:20180429100035j:plain

前項でコピーしたACOS_vThunder_4_1_1-P5_20.isoを選択して、Choose Volumeをクリック
f:id:metonymical:20180429162353j:plain

下図の通りであることを確認して、Forwardをクリック
f:id:metonymical:20180429162426j:plain

下図の通りであることを確認して、Forwardをクリック
最低3GBで起動しますが、ACOSver4.x系は4GB必要です。
CPUsは1で起動します
f:id:metonymical:20180429100349j:plain
下図の通りであることを確認して、Forwardをクリック
公式Docを読む限り16GBでOKみたいです。
f:id:metonymical:20180429162603j:plain
Nameに任意の名前を入力
Customize configuration before installにチェック(必須)
Network selectionは任意のインターフェースを選択(mgt用なので後で変更可)
f:id:metonymical:20180429162630j:plain

Device modelにe1000を選択(必須)*2
Applyをクリック
f:id:metonymical:20180429162708j:plain

SR-IOVのVFを追加していきます。
画面左下のAdd Hardwareをクリック
PCI Host Deviceを選択
任意のVirtualFunctionを選択
Finishをクリック
f:id:metonymical:20180429101259j:plain

Begin Installationをクリックするとisoファイルから起動が開始されます。
以下の画面で一旦停止しますので、ユーザ名/パスワードとYesSと入力するとインストールが進みます。

  • 1行目:install
  • 2行目:password
  • 最終行:YesS

f:id:metonymical:20180429163047j:plain

その後、自動的に再起動して以下の画面でしばらく待たされます。
f:id:metonymical:20180429163320j:plain
起動が完了すると、以下の画面が表示されますので、ユーザ名/パスワードを入力するとログインできます。
ログイン後のenableパスワードは無いため、そのままEnterでOKです。

  • 1行目:admin
  • 2行目:a10

f:id:metonymical:20180429163420j:plain

2-3.諸注意

私が検証した結果、上記ログイン画面にて、admin/a10を何度入力しても同じ画面に戻ってしまう事象を確認しました。

この場合の対処方法は、一旦仮想マシンをForce offなどで停止してから再度起動し、改めてユーザ名/パスワードを入力してみてください。

3.起動後の確認

3-1.telnet接続方法

Virtual Console(VGA)出力で頑張るのはしんどいので、mgtにtelnetアクセスできるようにします。ほぼほぼCiscoライクに設定できます。

vThunder(NOLICENSE)#conf t
vThunder(config)(NOLICENSE)#enable-management service telnet
vThunder(config-enable-management telnet)(NOLICENSE)#management
vThunder(NOLICENSE)#show interfaces brief
Port  Link  Dupl  Speed Trunk Vlan MAC             IP Address          IPs  Name
------------------------------------------------------------------------------------
mgmt  Up    Full  1000  N/A   N/A  5254.0005.45bf  192.168.122.87/24     1
1     Disb  None  None  None  1    5254.009d.9f90  0.0.0.0/0             0
2     Disb  None  None  None  1    5254.00ac.2319  0.0.0.0/0             0
3     Disb  None  None  None  1    1236.991c.1e03  0.0.0.0/0             0
4     Disb  None  None  None  1    1236.991c.1e04  0.0.0.0/0             0
5     Disb  None  None  None  1    1236.991c.1e05  0.0.0.0/0             0

configモードに移動
telnetサービスを有効化
telnetサービスへのアクセスインターフェースをmgtに設定
mgtインターフェースのIPを確認

上記設定およびIP確認後、mgtインターフェースにtelnet接続が可能となります。ちなみに、KVMのDefaultNAT(virbr0)が192.168.122.1/24を持っているハズなので、上記IP(192.168.122.87→DHCPで動的アサイン)にそのままtelnet可能です。
ホストOS上でifconfigにて確認してみてください。

3-2.SR-IOV NICの確認

mgt以外の各インターフェースをenable化(Ciscoでいうno shut)すると、以下のようにLinkUpします。

vThunder(NOLICENSE)#show interfaces brief
Port  Link  Dupl  Speed Trunk Vlan MAC             IP Address          IPs  Name
------------------------------------------------------------------------------------
mgmt  Up    Full  1000  N/A   N/A  5254.0005.45bf  192.168.122.87/24     1
1     Up    Full  10000 None  1    5254.009d.9f90  0.0.0.0/0             0
2     Up    Full  10000 None  1    5254.00ac.2319  0.0.0.0/0             0
3     Up    Full  10000 None  1    1236.991c.1e03  0.0.0.0/0             0
4     Up    Full  10000 None  1    1236.991c.1e04  0.0.0.0/0             0
5     Up    Full  10000 None  1    1236.991c.1e05  0.0.0.0/0             0
vThunder(NOLICENSE)#

5254から始まるMACアドレスはvirtioで設定したNICで、1236から始まるMACアドレスはSR-IOVで設定したNICです。但し、SR-IOV NICMACアドレスをどこで生成しているのか?が掴めていないので、継続調査したいと思っています。

以上です。

4.最後に

VFIOについて少し記載しましたが、他の仮想ルータなどには無いのかな?と確認したところ、vMXをインストールする際に生成されるvfconfig-generated.shでは、VFIOではないもののpci-stub(パススルー)の設定が入っているようです。

[root@ images]# cat vmx/build/vmx01/xml/vfconfig-generated.sh
#Handling interface ens1f0
ifconfig ens1f0 up
sleep 2
ifconfig ens1f0 promisc
ifconfig ens1f0 allmulti
ifconfig ens1f0 mtu 9198
echo 8086 1515 > /sys/bus/pci/drivers/pci-stub/new_id
sleep 2
echo 0000:08:10.0 > /sys/bus/pci/devices/0000:08:10.0/driver/unbind
echo 0000:08:10.0 >> /sys/bus/pci/drivers/pci-stub/bind
ip link set ens1f0 vf 0 spoofchk off
ip link set ens1f0 vf 0 rate 10000
ip link set ens1f0 vf 0 mac 02:06:0A:0E:FF:E3
bridge link set dev ens1f0 hwmode vepa

こういった点におけるJuniperの作り込みレベルの高さは流石だなと思いますし、とても好感が持てます。
上記コマンドが一体何をやっているのか?なぜその設定が必要なのか?ということを調べていると、すごく勉強になります。

*1:VNCサーバのインストール方法について、ここではあえて触れません、あしからず。

*2:公式DocではACOSver411-P2以降、e1000が無い場合、virtioで起動すると記載があります。

CentOS7でCSR1000vのセットアップ

CentOS7でCisco CSR1000vのセットアップを実施したため、その手順を記載しておきます。

c1kvはisoファイルからインストール or runファイルからインタラクティブインストールができるので、vMXやn9kvよりはさらに敷居が下がると思います。

以下の公式Docに沿って記載したいと思います。
Cisco CSR 1000v Series Cloud Services Router Software Configuration Guide - Installing the Cisco CSR 1000v in KVM Environments [Cisco Cloud Services Router 1000V Series] - Cisco


また、c1kvの足回りとしては、virtioとSR-IOVの両方で構成可能です。
また、インストールした後から諸々変更できるので助かります。

1.環境

筐体                             : ProLiant DL360e Gen8
System ROM                       : P73 01/22/2018
NIC                              : Intel X540-AT2
OS                               : CentOS7.4(1708)
Kernel                           : kernel-3.10.0-693.21.1.el7.x86_64
Installed Environment Groups     : Server with GUI
Add-Ons for Selected Environment : Virtualization Client, Virtualization Hypervisor, Virtualization Tools 

2.CSR1000vのインストール

公式Docを読む限り、isoファイルの場合とrunファイルの場合が記載されていますが、今回はvirt-managerによるGUIでのインストール方法をご紹介します。
IPMIなどが無ければ、tigervncなどを起動させておきましょう。*1

まずはisoファイルを/var/lib/libvirt/images/直下にコピー

cp csr1000v-universalk9.16.08.01a.iso /var/lib/libvirt/images/
2-1.virt-managerによるインストール

File>New Virtual Machineを選択
f:id:metonymical:20180428192118j:plain

Local install mediaを選択して、Forwardをクリック
f:id:metonymical:20180429100035j:plain

前項でコピーしたcsr1000v-universalk9.16.08.01a.isoを選択して、Choose Volumeをクリック
f:id:metonymical:20180429100252j:plain

下図の通りであることを確認して、Forwardをクリック
f:id:metonymical:20180429100233j:plain

下図の通りであることを確認して、Forwardをクリック
最低4GBで起動します。
CPUsは1で起動します
f:id:metonymical:20180429100349j:plain
下図の通りであることを確認して、Forwardをクリック
公式Docを読む限り8GBでOKみたいです。
f:id:metonymical:20180429100429j:plain
Nameに任意の名前を入力
Customize configuration before installにチェック(必須)
Network selectionは任意のインターフェースを選択(mgt用なので後で変更可)
f:id:metonymical:20180429100527j:plain

Device modelにvirtioを選択(必須)*2
Applyをクリック
f:id:metonymical:20180429100801j:plain


c1kvではインストール時およびインストール後にConsole出力をVirtualかSerialかで設定や変更が可能ですが、ここではひとまずSerialからConsole出力できるように設定しておきます。

画面左下のAdd Hardwareをクリック
Serialを選択
Device TypeにTCPを選択
Hostに0.0.0.0を入力*3
Portに8888など任意のポート番号を入力
ModeにServer mode(bind)を選択
Use Telnetにチェック
Finishをクリック
f:id:metonymical:20180429100643j:plain

c1kvでは現在のタイミングおよびインストール後にもNICの追加が可能ですが、ここではひとまずSR-IOVのVFを追加しておきます。

画面左下のAdd Hardwareをクリック
PCI Host Deviceを選択
任意のVirtualFunctionを選択*4
Finishをクリック
f:id:metonymical:20180429101259j:plain

Begin Installationをクリックすると、以下の画面でConsole出力方法を選択できます。
VirtualとSerialが選択できますが、ここではSerialを選択して進めます。
ちなみに、Virtualを選択した場合、この画面のままインストールが進みます。
f:id:metonymical:20180429104335j:plain
Serialを選択すると、以下の画面で止まったように見えるため、後はホストOS上からtelnetすることになります。
f:id:metonymical:20180429113936j:plain

2-2.SerialConsoleの出力画面

ホストOS上からTelnetします。
telnet localhost 8889 でも接続可能です。

[root@ ~]# telnet 192.168.12.130 8889
Trying 192.168.12.130...
Connected to 192.168.12.130.
Escape character is '^]'.
%IOSXEBOOT-4-WAIT_FOR_DEVICES: (local/local): Partition "/dev/bootflash1" missing at 20180429013632 Continuing to initialization
%IOSXEBOOT-4-PART_INVALID: (local/local): /dev/bootflash has an invalid partition table that must be repaired.
%IOSXEBOOT-4-PART_REPAIR: (local/local): The system will repair /dev/bootflash now.

この後、自動的にインストールが開始され、一旦c1kvが再起動されます。
再起動と共にtelnetセッションが切断されるため、再度telnet接続します。

%IOSXEBOOT-4-BOOT_SRC: (rp/0): CD-ROM Boot
%IOSXEBOOT-4-BOOT_CDROM: (rp/0): Using Serial console
%IOSXEBOOT-4-BOOT_CDROM: (rp/0): Installing GRUB to /dev/bootflash
%IOSXEBOOT-4-BOOT_CDROM: (rp/0): Copying image to /boot
%IOSXEBOOT-4-BOOT_CDROM: (rp/0): Copying image to /bootflash
%IOSXEBOOT-4-BOOT_CDROM: (rp/0): Creating /boot/grub/menu.lst
%IOSXEBOOT-4-BOOT_CDROM: (rp/0): Ejecting CD-ROM tray
%IOSXEBOOT-4-BOOT_CDROM: (rp/0): CD-ROM Installation finished
%IOSXEBOOT-4-BOOT_CDROM: (rp/0): Rebooting from HD

Connection closed by foreign host.
[root@ ~]# telnet 192.168.12.130 8890
Trying 192.168.12.130...
Connected to 192.168.12.130.
Escape character is '^]'.
The highlighted entry will be booted automatically in 3 seconds.    The highlighted entry will be booted automatically in 2 seconds.    The highlighted entry will be booted automatically in 1 seconds.      Booting 'CSR1000v - packages.conf'

root (hd0,0)
 Filesystem type is ext2fs, partition type 0x83
kernel /packages.conf rw quiet root=/dev/ram console= max_loop=64 HARDWARE=virt
ual SR_BOOT=bootflash:packages.conf
Calculating SHA-1 hash...done
SHA-1 hash:
        calculated   ef2043b5:caad0265:2a268887:a7004ba8:fcfe6506
        expected     ef2043b5:caad0265:2a268887:a7004ba8:fcfe6506
package header rev 3 structure detected
Calculating SHA-1 hash...done
SHA-1 hash:
        calculated   e674e45a:1da6da5e:2e3d73a7:7cf8b076:631b84d8
        expected     e674e45a:1da6da5e:2e3d73a7:7cf8b076:631b84d8
Package type:0x7531, flags:0x0
   [Linux-bzImage, setup=0x3c00, size=0x4c5e00]
   [isord @ 0x7e032000, 0x1fbded6 bytes]

%IOSXEBOOT-4-BOOT_SRC: (rp/0): Checking grub versions 1.0 vs 1.0
%IOSXEBOOT-4-BOOT_SRC: (rp/0): No need for bootloader upgrade.

上記の「%IOSXEBOOT-4-BOOT~」が出力されて、そこそこの時間待たされた後、以下の画面が出力されます。

              Restricted Rights Legend

Use, duplication, or disclosure by the Government is
subject to restrictions as set forth in subparagraph
(c) of the Commercial Computer Software - Restricted
Rights clause at FAR sec. 52.227-19 and subparagraph
(c) (1) (ii) of the Rights in Technical Data and Computer
Software clause at DFARS sec. 252.227-7013.

           Cisco Systems, Inc.
           170 West Tasman Drive
           San Jose, California 95134-1706

Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.8.1a, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2018 by Cisco Systems, Inc.
Compiled Tue 03-Apr-18 18:43 by mcpre

PLEASE READ THE FOLLOWING TERMS CAREFULLY. INSTALLING THE LICENSE OR
LICENSE KEY PROVIDED FOR ANY CISCO SOFTWARE PRODUCT, PRODUCT FEATURE,
AND/OR SUBSEQUENTLY PROVIDED SOFTWARE FEATURES (COLLECTIVELY, THE
"SOFTWARE"), AND/OR USING SUCH SOFTWARE CONSTITUTES YOUR FULL
ACCEPTANCE OF THE FOLLOWING TERMS. YOU MUST NOT PROCEED FURTHER IF YOU
ARE NOT WILLING TO BE BOUND BY ALL THE TERMS SET FORTH HEREIN.

Your use of the Software is subject to the Cisco End User License Agreement
(EULA) and any relevant supplemental terms (SEULA) found at
http://www.cisco.com/c/en/us/about/legal/cloud-and-software/software-terms.html.

You hereby acknowledge and agree that certain Software and/or features are
licensed for a particular term, that the license to such Software and/or
features is valid only for the applicable term and that such Software and/or
features may be shut down or otherwise terminated by Cisco after expiration
of the applicable license term (e.g., 90-day trial period). Cisco reserves
the right to terminate any such Software feature electronically or by any
other means available. While Cisco may provide alerts, it is your sole
responsibility to monitor your usage of any such term Software feature to
ensure that your systems and networks are prepared for a shutdown of the
Software feature.

% Failed to initialize nvram
cisco CSR1000V (VXE) processor (revision VXE) with 2186344K/3075K bytes of memory.
Processor board ID 9MJXF16X1D5
1 Gigabit Ethernet interface
32768K bytes of non-volatile configuration memory.
3985000K bytes of physical memory.
20357119K bytes of virtual hard disk at bootflash:.
0K bytes of WebUI ODM Files at webui:.

%INIT: waited 0 seconds for NVRAM to be available
PARSER-ERROR: (3) unexpected stale csb (0)


Press RETURN to get started!

Telnet接続したSerialConsoleに出力されるBootLogを貼り付けておきます。
c1kvのBootLog

3.c1kvへのログインとその他諸々

3-1.n9kvへのログイン

c1kvへのログインはパスワード無しでログイン可能ですので、あとは通常のCiscoIOSライクに扱ってください。

3-2.tftp config取得サービスの停止

起動直後に以下の出力でちょいちょい止まる場合がありますが、

%Error opening tftp://192.168.122.1/Router-confg (Timed out)
%Error opening tftp://192.168.122.1/Router-confg (Timed out)

以下のコマンドで停止することが可能です。

Router#conf t
Router(config)#no service config
3-3.Console出力の変更方法

Console出力ですが、以下のコマンドでSerial or Virtualの変更が可能です。
autoがどのような挙動になるかは未検証なので実際にやってみてください。

Router(config)#platform console ?
  auto     Autodetect console (Serial,VGA) for IOS output
  serial   Use Serial console for IOS output
  virtual  Use VM (VGA) console for IOS output
       
3-4.SR-IOVの確認

インストール時にアサインした2つ目以降のNICはSR-IOVのVFを指定しましたが、正常に認識されているかはshow interfacesで確認可能です。

Router#sh int g2
GigabitEthernet2 is administratively down, line protocol is down 
  Hardware is CSR vNIC, address is 0011.2233.4455 (bia 0011.2233.4455)
  MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, 
     reliability 255/255, txload 1/255, rxload 1/255
  Encapsulation ARPA, loopback not set
  Keepalive set (10 sec)
  Full Duplex, 1000Mbps, link type is auto, media type is Virtual
  output flow-control is unsupported, input flow-control is unsupported
  ARP type: ARPA, ARP Timeout 04:00:00
  Last input never, output never, output hang never
  Last clearing of "show interface" counters never
  Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0
  Queueing strategy: fifo
  Output queue: 0/40 (size/max)

ポイントはホストOS上のip link showで表示されるVFのMACアドレスと同一か?という点です。

[root@ ~]# ip link show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eno1:  mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000
    link/ether ac:16:2d:bb:9e:c0 brd ff:ff:ff:ff:ff:ff
3: eno2:  mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000
    link/ether ac:16:2d:bb:9e:c1 brd ff:ff:ff:ff:ff:ff
4: ens1f0:  mtu 9198 qdisc mq state UP mode DEFAULT qlen 1000
    link/ether a0:36:9f:3e:6d:68 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 00:11:22:33:44:55, spoof checking off, link-state auto, trust off, query_rss off
    vf 1 MAC 00:11:22:33:44:56, spoof checking off, link-state auto, trust off, query_rss off
5: eno3:  mtu 1500 qdisc mq state DOWN mode DEFAULT qlen 1000
    link/ether ac:16:2d:bb:9e:c2 brd ff:ff:ff:ff:ff:ff
6: eno4:  mtu 1500 qdisc mq state DOWN mode DEFAULT qlen 1000
    link/ether ac:16:2d:bb:9e:c3 brd ff:ff:ff:ff:ff:ff
7: ens1f1:  mtu 9198 qdisc mq state UP mode DEFAULT qlen 1000
    link/ether a0:36:9f:3e:6d:6a brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 00:11:22:33:44:57, spoof checking off, link-state auto, trust off, query_rss off
    vf 1 MAC 00:11:22:33:44:58, spoof checking off, link-state auto, trust off, query_rss off

以上です。

4.最後に

仮想マシンのインストールはいくつかのパターンがあるので、実際にインストールしてみて&壊してを繰り返していくうちにフィーリングがわかってくると思います。ただ、一度も成功したことがないと、今の状態は正常なのか?といった判断がつかないと思うので、何度か試してみることをお勧めします。

*1:VNCサーバのインストール方法について、ここではあえて触れません、あしからず。

*2:公式Docに従ってvirtioにしています。e1000では未検証です。

*3:ホストOS自身に設定されたIPであれば127.0.0.1でも192.168~でも可。0.0.0.0は自身のどのIPからでも要求を受け付けるために設定しています。

*4:SR-IOVの設定は事前に行っておいてください。 metonymical.hatenablog.com