かなり長いことInfinibandを使っていますが、Infinibandで試そうと思いつつ全く試していなかったことがあります。それがNFS over RDMAです。ESXiでIB+NFSoRDMAに対応していれば試していたのですが、これが非対応だったこととSRPが速すぎてそれ以上追求するモチベーションがわかなかったことが理由でした。しかし、最近PVEを検証する機会があり、その中でどうもIB+NFS+RDMAがいけそうだというのがわかったものの、ほかを探しても一切の情報がないので検証してみました。
PVEに行く前にそもそもNFSoRDMAってどう使うの?という疑問があり色々ググりましたが、NFSサーバ側には svcrdmaモジュールが必要で、クライアント側にはxprtrdmaが必要になるみたいですが、Debian12ではrpcrdma.koのエイリアスとしてすでにInboxでドライバをもっていました。
https://enterprise-support.nvidia.com/s/article/howto-configure-nfs-over-rdma--roce-x
root@debian:~# modinfo svcrdma
filename: /lib/modules/6.1.0-28-amd64/kernel/net/sunrpc/xprtrdma/rpcrdma.ko
alias: rpcrdma6
alias: xprtrdma
alias: svcrdma
license: Dual BSD/GPL
description: RPC/RDMA Transport
author: Open Grid Computing and Network Appliance, Inc.
depends: sunrpc,ib_core,rdma_cm
retpoline: Y
intree: Y
name: rpcrdma
vermagic: 6.1.0-28-amd64 SMP preempt mod_unload modversions
sig_id: PKCS#7
signer: Debian Secure Boot CA
sig_key: 32:A0:28:7F:84:1A:03:6F:A3:93:C1:E0:65:C4:3A:E6:B2:42:26:43
sig_hashalgo: sha256
signature: 15:83:F8:C8:E4:FE:CB:21:AA:92:43:39:E8:FC:5F:61:0C:D9:3E:F9:
28:1D:9A:1C:35:25:58:08:0C:DB:8E:D5:07:36:CD:E4:D5:1E:30:2A:
61:FE:20:AB:DF:98:C0:55:C5:F6:6E:B8:8B:32:42:D4:D5:9A:58:44:
E5:EB:5A:FB:B6:06:E9:1E:B2:0A:F6:D1:FC:64:B1:F9:68:DF:55:06:
D3:70:DB:13:35:99:FF:2B:6C:42:8C:D0:1D:C7:D6:3A:BC:55:04:08:
0A:7D:1D:6A:EF:D6:70:32:BB:A4:B5:D3:2A:62:2E:1A:1C:F9:D4:B4:
B6:87:4E:FF:F8:C3:96:3E:09:2A:86:4C:41:F3:2B:9E:AA:AE:07:0D:
98:A4:EA:D4:5F:5F:E3:CC:DF:42:1F:79:FF:F7:B6:77:DF:09:BF:38:
74:6F:1B:18:D0:48:BF:61:02:DC:25:7A:CE:6D:91:79:06:4B:A2:02:
28:85:A4:D3:7A:21:79:80:31:6C:98:B9:6F:E2:94:BA:CB:AB:A9:03:
6A:A8:17:3F:26:4B:91:42:E0:5C:53:6E:B2:D3:99:63:24:04:FD:32:
3A:FF:2D:48:A5:B5:D4:89:B9:DD:D5:FC:FA:15:5E:1D:35:06:C0:46:
F6:C7:CE:0F:B7:4E:1F:38:F2:5E:A5:46:8E:1C:7C:9C
root@debian:~# modinfo xprtrdma
filename: /lib/modules/6.1.0-28-amd64/kernel/net/sunrpc/xprtrdma/rpcrdma.ko
alias: rpcrdma6
alias: xprtrdma
alias: svcrdma
license: Dual BSD/GPL
description: RPC/RDMA Transport
author: Open Grid Computing and Network Appliance, Inc.
depends: sunrpc,ib_core,rdma_cm
retpoline: Y
intree: Y
name: rpcrdma
vermagic: 6.1.0-28-amd64 SMP preempt mod_unload modversions
sig_id: PKCS#7
signer: Debian Secure Boot CA
sig_key: 32:A0:28:7F:84:1A:03:6F:A3:93:C1:E0:65:C4:3A:E6:B2:42:26:43
sig_hashalgo: sha256
signature: 15:83:F8:C8:E4:FE:CB:21:AA:92:43:39:E8:FC:5F:61:0C:D9:3E:F9:
28:1D:9A:1C:35:25:58:08:0C:DB:8E:D5:07:36:CD:E4:D5:1E:30:2A:
61:FE:20:AB:DF:98:C0:55:C5:F6:6E:B8:8B:32:42:D4:D5:9A:58:44:
E5:EB:5A:FB:B6:06:E9:1E:B2:0A:F6:D1:FC:64:B1:F9:68:DF:55:06:
D3:70:DB:13:35:99:FF:2B:6C:42:8C:D0:1D:C7:D6:3A:BC:55:04:08:
0A:7D:1D:6A:EF:D6:70:32:BB:A4:B5:D3:2A:62:2E:1A:1C:F9:D4:B4:
B6:87:4E:FF:F8:C3:96:3E:09:2A:86:4C:41:F3:2B:9E:AA:AE:07:0D:
98:A4:EA:D4:5F:5F:E3:CC:DF:42:1F:79:FF:F7:B6:77:DF:09:BF:38:
74:6F:1B:18:D0:48:BF:61:02:DC:25:7A:CE:6D:91:79:06:4B:A2:02:
28:85:A4:D3:7A:21:79:80:31:6C:98:B9:6F:E2:94:BA:CB:AB:A9:03:
6A:A8:17:3F:26:4B:91:42:E0:5C:53:6E:B2:D3:99:63:24:04:FD:32:
3A:FF:2D:48:A5:B5:D4:89:B9:DD:D5:FC:FA:15:5E:1D:35:06:C0:46:
F6:C7:CE:0F:B7:4E:1F:38:F2:5E:A5:46:8E:1C:7C:9C[
もう一つNFS関連で試そうと思って試していなかったこととしてNFSのセッショントランク/マルチパス(pNFSと勘違いしていた)もあったので、どうせならこれも試してみようと思い今回以下のものを試してみました。
・IPoIB NFS
・IPoIB NFS マルチパス
・NFSoRDMAマルチパス
検証環境について
今回の検証環境は以下となります
NFSサーバ
OS周り
root@debian:~# uname -a
Linux debian 6.1.0-28-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.119-1 (2024-11-22) x86_64 GNU/Linux
root@debian:~# lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 12 (bookworm)
Release: 12
Codename: bookworm
ハードウェア周り
X11SPW-TF
CPU:Intel(R) Xeon(R) Gold 6138 CPU @ 2.00GHz 1ソケット
RAM:DDR4 2400 64GB LRDIMM *4 (256GB)
IB HCA;MCX354A-QCBT (QDR Dual port IB HCA@PCIE 3.0 x8)
PVE01/02
OS周り
root@pve01:~# uname -a
Linux pve01 6.8.12-4-pve #1 SMP PREEMPT_DYNAMIC PMX 6.8.12-4 (2024-11-06T15:04Z) x86_64 GNU/Linux
root@pve01:~# pveversion
pve-manager/8.3.1/fb48e850ef9dde27 (running kernel: 6.8.12-4-pve)
ハードウェア周り
JGINYUE B650I NIGHT DEVIL
CPU:16 x AMD Ryzen 7 7700 8-Core Processor (1 Socket)
PVE01 RAM:DDR5 4800 16GB*2 (32GB)
PVE02 RAM:DDR5 4800 8GB*2 (16GB)
IB HCA:MCB194A-FCAT (Connect-IB FDR Dual port HCA@PCIE 3.0x16)
スイッチ
Mellanox SX6036
今回はIBの最大性能を見たいため、NFSサーバはtmpfsなどのオンメモリなファイルシステムを使っても余裕のあるマシンということでLRDIMMが使えるマシンにしました。シングルスレッドの性能的に若干不安がありますが、RDMAが有効ならCPUの性能がなくても十分な性能を発揮するはずです。HCAについては本来はこちらも MCB194A-FCATを使いたかったのですが、拡張スロットにx16がない(エッジレスx8スロットもない)のとそもそも在庫がないのでCX354Aを使っています。
QDRが40Gbpsの8b/10b税を払うと32Gbpsとなり、2ポート合計の実効が64GbpsなのでPCIE3.0 x8の帯域ぴったりになりますが、オーバーヘッドを考えると若干足りてない気がします。そのため、とりあえず効果があるかを確認するためにシングルポートQDR以上の帯域が出れば良いことにします。
ちなみにFDRでリンクしたい場合、ケーブルもFDR対応のものを使わないとQDRになってしまうようです。手持ちのケーブルだと直結してもFDRにはなりませんでした。以前無駄にハマりました。
そこに接続するマシンはシングルスレッドの性能がほしいため、デスクトップ向けのCPUを搭載したマシンを使っています。今回はAliExpressで何故か安く出ていて買ってしまったRyzen 7 7700を搭載したマシンを2台用意しています。マザボも同じくAliで安く出ていた JGINYUE B650I NIGHT DEVIL というITXの板を利用しています。2台とも石、板、箱がAE調達というAEビルドマシンです。板のメーカーについては全く未知ですが、なにげにあとから9000系の対応BIOSを出しているなど、ある程度やる気はあるようで、今のところ素直に動いています。
前提条件
OSのインストールなどが終わり普通に使える状態で、どこかでOpenSMなどのサブネットマネージャが動いていて、リンクが上がっていることとします
root@pve01:~# apt install ibutils
root@pve01:~# ibstat
CA 'mlx5_0'
CA type: MT4113
Number of ports: 2
Firmware version: 10.14.2066
Hardware version: 0
Node GUID: 0x5849560e5cbc0401
System image GUID: 0x5849560e5cbc0401
Port 1:
State: Active
Physical state: LinkUp
Rate: 40
Base lid: 19
LMC: 0
SM lid: 1
Capability mask: 0x26516848
Port GUID: 0x5849560e5cbc0401
Link layer: InfiniBand
Port 2:
State: Active
Physical state: LinkUp
Rate: 40
Base lid: 20
LMC: 0
SM lid: 1
Capability mask: 0x26516848
Port GUID: 0x5849560e5cbc0409
Link layer: InfiniBand
NFSサーバの準備
そのままではipoibが使えないので、ib_ipoibモジュールを読み込みibp~というリンクが生えていることを確認します。検証環境のためIP体系が変ですが、通常は192.168.1.0/24、192.168.2.0/24~とかで大丈夫です。
root@debian:~# ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether ac:1f:6b:bd:03:30 brd ff:ff:ff:ff:ff:ff
altname enp25s0f0
3: eno2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether ac:1f:6b:bd:03:31 brd ff:ff:ff:ff:ff:ff
altname enp25s0f1
root@debian:~# modprobe ib_ipoib
root@debian:~# ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether ac:1f:6b:bd:03:30 brd ff:ff:ff:ff:ff:ff
altname enp25s0f0
3: eno2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether ac:1f:6b:bd:03:31 brd ff:ff:ff:ff:ff:ff
altname enp25s0f1
4: ibp179s0: <BROADCAST,MULTICAST> mtu 4092 qdisc noop state DOWN mode DEFAULT group default qlen 256
link/infiniband 80:00:02:08:fe:80:00:00:00:00:00:00:e4:1d:2d:03:00:49:2c:61 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
5: ibp179s0d1: <BROADCAST,MULTICAST> mtu 4092 qdisc noop state DOWN mode DEFAULT group default qlen 256
link/infiniband 80:00:02:09:fe:80:00:00:00:00:00:00:e4:1d:2d:03:00:49:2c:62 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
まずNFSサーバ側に生えたIFにIPを割り振ります。例として 10.111.1.200/24と 10.111.2.200/24を割り振ります。IBはVLANなどの概念はないので同一スイッチの同一サブネット上に2つのIP系ができることになります。IBにもPartitionというものがあるものの、あくまでマルチパスを貼るための都合上の2つのIP体系なので問題ないです。
root@debian:~# ip a add dev ibp179s0 10.111.1.200/24
root@debian:~# ip a add dev ibp179s0d1 10.111.2.200/24
root@debian:~# ip l se up ibp179s0
root@debian:~# ip l se up ibp179s0d1
次にtmpfsでNFSベンチマーク用のオンメモリディレクトリを作成します。今回はRAM領域を240GB作成しています。
root@debian:~# mkdir /exports
root@debian:~# mount -t tmpfs -o size=240G tmpfs /exports/
root@debian:~# mount|grep exports
tmpfs on /exports type tmpfs (rw,relatime,size=251658240k,inode64)
RAM上のFIOベンチマーク
NFSでマウントされる前に、まずはサーバ上での上限を確認します。
root@debian:~# cd /exports/
root@debian:/exports# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randread --bs=8k --size=1G --numjobs=1 --group_reporting
bw ( MiB/s): min= 3063, max= 3208, per=100.00%, avg=3187.67, stdev=31.30, samples=19
iops : min=392128, max=410708, avg=408021.58, stdev=4006.29, samples=19
root@debian:/exports# fio --name=fiotest --ioengine=io_uring --iodepth=8 --time_based --runtime=10 --rw=randread --bs=8k --size=1G --numjobs=8 --group_reporting
bw ( MiB/s): min=18787, max=22317, per=100.00%, avg=22060.57, stdev=119.99, samples=152
iops : min=2404778, max=2856698, avg=2823753.89, stdev=15358.64, samples=152
root@debian:/exports# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randwrite --bs=8k --size=1G --numjobs=1 --group_reporting
bw ( MiB/s): min= 1726, max= 3838, per=100.00%, avg=2622.56, stdev=1016.40, samples=19
iops : min=221000, max=491292, avg=335687.05, stdev=130099.60, samples=19
root@debian:/exports# fio --name=fiotest --ioengine=io_uring --iodepth=8 --time_based --runtime=10 --rw=randwrite --bs=8k --size=1G --numjobs=8 --group_reporting
bw ( MiB/s): min=11517, max=16850, per=100.00%, avg=14898.87, stdev=168.53, samples=152
iops : min=1474194, max=2156870, avg=1907055.58, stdev=21572.48, samples=152
RAM上ではO_DIRECTがないので(当然)direct=1を外していますが、Q1T1だとRandRead408K IOPS、RandWrite335K IOPSで、Q8T8だとRandRead2.8M IOPS、RandWrite1.9M IOPSでした。
exportsの設定
作成した/exportをNFSの領域に設定します。検証なので*で雑に設定しています。マルチパスを使いたいのでNFS4のオプションである fsid=0にて、/exportsの下をNFSクライアントから見た/(ルートディレクトリ)とします。その下にNFSクライアントからみた/nfs1となるnfs1ディレクトリを作成します。
root@debian:~# echo '/exports *(fsid=0,rw,insecure,no_root_squash,no_subtree_check)' >> /etc/exports
root@debian:~# mkdir /exports/nfs1
root@debian:~# exportfs -avr
exporting *:/exports
PVE側のNFSの設定
ipoibを読み込ませる以外は普通と同じです。ipoibを読み込ませるとNICがリンク一覧に出てくるので、そこからIPを設定します。ipコマンドから同じように設定することもできますが、ipコマンドの設定だとWebUIから設定を変更したタイミングで揮発するのでWebUIを正としたほうが無難です。再起動時にipoibを読み込ませたい場合は/etc/modulesに追記しておきます
root@pve01:~# modprobe ib_ipoib
root@pve01:~# echo ib_ipoib>>/etc/modules
IFが生えたらIPとサブネットだけ設定します。
その後、NFSの設定をします。ただのNFSであればvers=3でよいですが、このあとマルチパスを使いたいので4.2を指定します。PVE特有の話ではなくLinuxでの話になりますが、fsid=0を指定するとNFS3と4でルートディレクトリの始まりが変わるので注意が必要です。(ちなみに上記設定でv3を使う場合は/export/nfs1になります。)
IPoIB上のNFSのベンチマーク
VMを経由せず、まずはマウントしたクライアントから直接fioを実行して性能を確認します
# read
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randread --bs=8k --size=1G --numjobs=1 --group_reporting
bw ( KiB/s): min=69104, max=89968, per=100.00%, avg=84469.05, stdev=3966.55, samples=19
iops : min= 8638, max=11246, avg=10558.63, stdev=495.82, samples=19
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=8 --time_based --runtime=10 --rw=randread --bs=8k --size=1G --numjobs=8 --group_reporting
bw ( KiB/s): min=135712, max=190992, per=100.00%, avg=165444.00, stdev=1502.60, samples=160
iops : min=16964, max=23874, avg=20680.50, stdev=187.83, samples=160
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=8 --time_based --runtime=10 --rw=randread --bs=1M --size=1G --numjobs=8 --group_reporting
bw ( KiB/s): min=305152, max=432128, per=100.00%, avg=371507.20, stdev=3970.09, samples=160
iops : min= 298, max= 422, avg=362.80, stdev= 3.88, samples=160
#write
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randwrite --bs=8k --size=1G --numjobs=1 --group_reporting
bw ( KiB/s): min= 16, max=1170816, per=100.00%, avg=559240.53, stdev=486898.18, samples=15
iops : min= 2, max=146352, avg=69905.07, stdev=60862.27, samples=15
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=8 --time_based --runtime=10 --rw=randwrite --bs=8k --size=1G --numjobs=8 --group_reporting
bw ( MiB/s): min= 82, max=13513, per=95.40%, avg=3327.49, stdev=630.16, samples=155
iops : min=10592, max=1729712, avg=425919.08, stdev=80659.95, samples=155
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=8 --time_based --runtime=10 --rw=randwrite --bs=1M --size=1G --numjobs=8 --group_reporting
bw ( MiB/s): min= 316, max=16376, per=95.07%, avg=3116.83, stdev=768.83, samples=156
iops : min= 316, max=16376, avg=3116.83, stdev=768.83, samples=156
表にまとめると以下です。
IOPS avg | BW avg (MiByte/s) | BW avg in Gbps | |
IPoIB single randreadQ1T1 8k | 10558 | 80.5 | 0.675283105 |
IPoIB single randreadQ8T8 8k | 20680 | 161.5 | 1.354760515 |
IPoIB single randreadQ8T8 1M | 362 | 354.3 | 2.972084523 |
IPoIB single randwriteQ1T1 8k | 69905 | 546.1 | 4.581019921 |
IPoIB single randwriteQ8T8 8k | 425919 | 3327.4 | 27.91226091 |
IPoIB single randwriteQ8T8 1M | 3116 | 3116.8 | 26.14561965 |
Readに対してWriteおかしくない?????????と思いましたが、何回試してもこの数字でした。atopの通信帯域を見ていましたが、こちらはなぜか16Gbps以上カウントされませんでした。async writeみたいな動きをしていますが、それならreadももっと上がってもいいような気がします。thinking_faceみたいになりながら色々見ましたが何もわからん…IPoIB特有の動きでしょうか…
マルチパスを試す
NFSのマルチパスについて探し方が悪いのかLinuxでの情報がほんとに見つかりませんでしたが、動きを見ているとmax_connectを指定したあと違うIPの同じExportsを違うディレクトリにマウントすると有効化されるようでした。
https://thinksystem.lenovofiles.com/storage/help/index.jsp?topic=%2Fontap_nfs-trunking%2Fclient-mount-task.html&cp=1_14_3_5_3_1_3
NFSサーバ側で/export/nfs1と/export/nfs2を作り、PVEからマウントします。先程と同様/exportにfsid0が指定されているのでPVEの設定に落とすと以下になります。ストレージの設定をWebUIから変えてもoptions以下の内容は変更されないので、contentをISOやContainerなどに変更しても都度optionsの書き直しは不要でした。
nfs: rdma
export /nfs1
path /mnt/pve/rdma
server 10.111.1.200
content images
options vers=4.2,max_connect=2
prune-backups keep-all=1
nfs: rdma2
export /nfs1
path /mnt/pve/rdma2
server 10.111.2.200
content images
options vers=4.2,max_connect=2
prune-backups keep-all=1
その後、データストアを無効化し、アンマウントしたあとに再度有効化すると新しい設定が入るようでした。すぐに入らないので少し待つ必要がありました
root@pve01:~# pvesm set rdma2 --disable 1
root@pve01:~# pvesm set rdma --disable 1
root@pve01:~# umount /mnt/pve/rdma
root@pve01:~# umount /mnt/pve/rdma2
root@pve01:~# pvesm set rdma2 --disable 0
root@pve01:~# pvesm set rdma --disable 0
成功すると違うマウントを指定したはずなのに同じIPでマウントされます。この状態が本当にあっているのかわかりませんが、少なくともatopなどでNICの利用状況を見ていると一つのディレクトリに対する操作を行ったときにそれぞれのNICで通信が発生していました。なんか…違う気がする…
root@pve01:~# mount|grep nfs
10.111.2.200:/nfs1 on /mnt/pve/rdma2 type nfs4 (rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,max_connect=2,timeo=600,retrans=2,sec=sys,clientaddr=10.111.2.201,local_lock=none,addr=10.111.2.200)
10.111.2.200:/nfs1 on /mnt/pve/rdma type nfs4 (rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,max_connect=2,timeo=600,retrans=2,sec=sys,clientaddr=10.111.2.201,local_lock=none,addr=10.111.2.200
とりあえずベンチを回して差が出たか確認します。
### nfs multipath
# read
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randread --bs=8k --size=1G --numjobs=1 --group_reporting
bw ( KiB/s): min=70656, max=86496, per=100.00%, avg=82204.63, stdev=3661.31, samples=19
iops : min= 8832, max=10812, avg=10275.58, stdev=457.66, samples=19
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=8 --time_based --runtime=10 --rw=randread --bs=8k --size=1G --numjobs=8 --group_reporting
bw ( KiB/s): min=249520, max=474544, per=99.54%, avg=393720.42, stdev=5737.21, samples=152
iops : min=31190, max=59318, avg=49215.05, stdev=717.15, samples=152
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randread --bs=1M --size=1G --numjobs=8 --group_reporting
bw ( KiB/s): min=550912, max=1323008, per=100.00%, avg=808895.33, stdev=20944.35, samples=158
iops : min= 538, max= 1292, avg=789.94, stdev=20.45, samples=158
#write
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randwrite --bs=8k --size=1G --numjobs=1 --group_reporting
bw ( KiB/s): min= 32, max=1161296, per=100.00%, avg=616809.41, stdev=469939.92, samples=17
iops : min= 4, max=145162, avg=77101.18, stdev=58742.49, samples=17
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=8 --time_based --runtime=10 --rw=randwrite --bs=8k --size=1G --numjobs=8 --group_reporting
bw ( MiB/s): min= 256, max=12827, per=100.00%, avg=4207.57, stdev=578.61, samples=149
iops : min=32824, max=1641910, avg=538569.22, stdev=74061.61, samples=149
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randwrite --bs=1M --size=1G --numjobs=8 --group_reporting
bw ( MiB/s): min= 484, max=19754, per=98.44%, avg=4232.42, stdev=820.85, samples=156
iops : min= 484, max=19754, avg=4232.42, stdev=820.85, samples=156
シングルとの差分を表にまとめるとこうなります
IOPS avg | BW avg (MiByte/s) | BW avg in Gbps | Multipath_efficiency (%) | |
IPoIB single randreadQ1T1 8k | 10558 | 80.5 | 0.675283105 | |
IPoIB con=2 randreadQ1T1 8k | 10275 | 80.3 | 0.673605383 | 99.7515528 |
IPoIB single randreadQ8T8 8k | 20680 | 161.5 | 1.354760515 | |
IPoIB con=2 randreadQ8T8 8k | 49215 | 384.5 | 3.225420545 | 238.0804954 |
IPoIB single randreadQ8T8 1M | 362 | 354.3 | 2.972084523 | |
IPoIB con=2 randreadQ8T8 1M | 789 | 789.9 | 6.626163039 | 222.9466554 |
IPoIB single randwriteQ1T1 8k | 69905 | 546.1 | 4.581019921 | |
IPoIB con=2 randwriteQ1T1 8k | 77101 | 602.3 | 5.052459803 | 110.2911555 |
IPoIB single randwriteQ8T8 8k | 425919 | 3327.4 | 27.91226091 | |
IPoIB con=2 randwriteQ8T8 8k | 538569 | 4207.6 | 35.29591544 | 126.4530865 |
IPoIB single randwriteQ8T8 1M | 3116 | 3116.8 | 26.14561965 | |
IPoIB con=2 randwriteQ8T8 1M | 4232 | 4232.4 | 35.50395296 | 135.7931211 |
相変わらず書き込みの速度だけはぶっ壊れていますが、パスが増えたことによって複数スレッドでの読み込みの速度の増加が確認できたので、マルチパスの効果はあるようです。しかしそれ以上にやはりIPoIBはなにかある気がします。もともと大して期待はしていませんでしたが、それにしても読み込みが合計80Gbpsに対して実測6Gbpsというのは悲しいです。
ただ、効果があるのは確かなので、イーサネットの場合には意味があると思います。
NFSoRDMAを検証する
IPoIBの挙動が謎すぎて時間を取られてしまいましたがようやくメインディッシュです。サーバ側に svcrdmaを、クライアント側に xprtrdmaを読み込ませ、RDMAを有効化していきます。
root@debian:~# modprobe svcrdma
root@debian:~# systemctl restart nfs-kernel-server
このままだとproto=rdmaを指定してRDMAで接続をしようとしたときに接続拒否されるので、portlistにrdmaの標準ポートである20049を追加します。
root@debian:~# cat /proc/fs/nfsd/portlist
tcp 2049
tcp 2049
root@debian:~# echo rdma 20049 > /proc/fs/nfsd/portlist
root@debian:~# cat /proc/fs/nfsd/portlist
rdma 20049
rdma 20049
tcp 2049
tcp 2049
オンザフライでの変更ではなく、設定ファイルで変更する場合は/etc/nfs.confにてrdma=yを有効にしたあとにサービスの再起動が必要になります。
# /etc/nfs.conf
[nfsd]
# debug=0
# threads=8
# host=
# port=0
# grace-time=90
# lease-time=90
# udp=n
# tcp=y
# vers3=y
# vers4=y
# vers4.0=y
# vers4.1=y
# vers4.2=y
rdma=y
rdma-port=20049
root@debian:~# systemctl restart nfs-kernel-server
root@debian:~# cat /proc/fs/nfsd/portlist
rdma 20049
rdma 20049
tcp 2049
tcp 2049
次に、PVE側の設定を行います。事前にコマンドラインからmountコマンドでproto=rdmaで接続できることは確認したので、sotrage.confに合う設定を入れます。今回はRDMAの最大速度を見たいのでいきなりマルチパスで行います
#/etc/pve/storage.cfg
nfs: rdma
export /nfs1
path /mnt/pve/rdma
server 10.111.1.200
content images
options vers=4.2,max_connect=2,proto=rdma
prune-backups keep-all=1
nfs: rdma2
export /nfs1
path /mnt/pve/rdma2
server 10.111.2.200
content images
options vers=4.2,max_connect=2,proto=rdma
prune-backups keep-all=1
root@pve01:~# modprobe xprtrdma
root@pve01:~# echo "xprtrdma" >> /etc/modules
root@pve01:~# pvesm set rdma2 --disable 1
root@pve01:~# pvesm set rdma --disable 1
root@pve01:~# umount /mnt/pve/rdma
root@pve01:~# umount /mnt/pve/rdma2
root@pve01:~# pvesm set rdma2 --disable 0
root@pve01:~# pvesm set rdma --disable 0
しばらく待ち、NFSのマウントオプションにproto=rdmaがある状態でNFSがマウントされたかを確認します。
root@pve01:~# mount|grep rdma
10.111.1.200:/nfs1 on /mnt/pve/rdma type nfs4 (rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=rdma,max_connect=2,port=20049,timeo=600,retrans=2,sec=sys,clientaddr=10.111.1.201,local_lock=none,addr=10.111.1.200)
10.111.1.200:/nfs1 on /mnt/pve/rdma2 type nfs4 (rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=rdma,max_connect=2,port=20049,timeo=600,retrans=2,sec=sys,clientaddr=10.111.1.201,local_lock=none,addr=10.111.1.200)
まずはPVE01で直接IOを発行してベンチマークをかけます
### nfs over RDMA
#read
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randread --bs=8k --size=1G --numjobs=1 --group_reporting
bw ( KiB/s): min=106624, max=131440, per=99.95%, avg=128103.58, stdev=5284.67, samples=19
iops : min=13328, max=16430, avg=16012.95, stdev=660.58, samples=19
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=8 --time_based --runtime=10 --rw=randread --bs=8k --size=1G --numjobs=8 --group_reporting
bw ( MiB/s): min= 1092, max= 1991, per=99.85%, avg=1828.98, stdev=30.13, samples=152
iops : min=139790, max=254956, avg=234109.58, stdev=3856.49, samples=152
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randread --bs=1M --size=1G --numjobs=8 --group_reporting
bw ( MiB/s): min= 2964, max= 3824, per=99.77%, avg=3633.37, stdev=33.98, samples=152
iops : min= 2964, max= 3824, avg=3633.37, stdev=33.98, samples=152
#write
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randwrite --bs=8k --size=1G --numjobs=1 --group_reporting
bw ( KiB/s): min=245120, max=1139216, per=98.00%, avg=782675.37, stdev=331891.63, samples=19
iops : min=30640, max=142402, avg=97834.42, stdev=41486.45, samples=19
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=8 --time_based --runtime=10 --rw=randwrite --bs=8k --size=1G --numjobs=8 --group_reporting
bw ( MiB/s): min= 903, max=13740, per=100.00%, avg=5349.23, stdev=563.43, samples=158
iops : min=115650, max=1758800, avg=684700.85, stdev=72119.49, samples=158
root@pve01:/mnt/pve/rdma# fio --name=fiotest --ioengine=io_uring --iodepth=1 --time_based --runtime=10 --rw=randwrite --bs=1M --size=1G --numjobs=8 --group_reporting
bw ( MiB/s): min= 2088, max=16382, per=100.00%, avg=6476.16, stdev=562.35, samples=158
iops : min= 2088, max=16382, avg=6476.16, stdev=562.35, samples=158
IPoIBマルチパスとの比較を表にまとめます
IOPS avg | BW avg (MiByte/s) | BW avg in Gbps | RDMA_efficiency (%) | |
IPoIB single randreadQ1T1 8k | 10558 | 80.5 | 0.675283105 | |
IPoIB con=2 randreadQ1T1 8k | 10275 | 80.3 | 0.673605383 | |
RDMA con=2 randwriteQ1T1 8k | 16012 | 128.103 | 1.074606107 | 159.5305106 |
IPoIB single randreadQ8T8 8k | 20680 | 161.5 | 1.354760515 | |
IPoIB con=2 randreadQ8T8 8k | 49215 | 384.5 | 3.225420545 | |
RDMA con=2 randwriteQ8T8 8k | 234109 | 1828.98 | 15.34259992 | 475.6775033 |
IPoIB single randreadQ8T8 1M | 362 | 354.3 | 2.972084523 | |
IPoIB con=2 randreadQ8T8 1M | 789 | 789.9 | 6.626163039 | |
RDMA con=2 randwriteQ8T8 1M | 3633 | 3633.3 | 30.47833671 | 459.9696164 |
IPoIB single randwriteQ1T1 8k | 69905 | 546.1 | 4.581019921 | |
IPoIB con=2 randwriteQ1T1 8k | 77101 | 602.3 | 5.052459803 | |
RDMA con=2 randreadQ1T1 8k | 97834 | 782.675 | 6.565555332 | 129.9477005 |
IPoIB single randwriteQ8T8 8k | 425919 | 3327.4 | 27.91226091 | |
IPoIB con=2 randwriteQ8T8 8k | 538569 | 4207.6 | 35.29591544 | |
RDMA con=2 randreadQ8T8 8k | 684700 | 5349.23 | 44.87260427 | 127.1325696 |
IPoIB single randwriteQ8T8 1M | 3116 | 3116.8 | 26.14561965 | |
IPoIB con=2 randwriteQ8T8 1M | 4232 | 4232.4 | 35.50395296 | |
RDMA con=2 randreadQ8T8 1M | 6476 | 6476 | 54.32463836 | 153.0101125 |
ReadQ1T1がもう一声欲しいですが、サーバ側のatopを見ていると1コアのCPU使用率が張り付くことがあり、1セッションのIOはシングルスレッドの性能に依存するようで、サーバ側の限界かもしれません。それ以外は圧倒的に速いです。特に弱かったReadが増強され、Q8T8においては200k IOPSを達成できました。Writeの速度に関しては54Gbpsを記録しました。NFSでこれだけの性能が出たら十分すぎます。
VMを立てて検証してみる
RDMAなストレージが十分に速いことが確認できたら、その上でWindowsVMを立てて実際に速いのか試してみます。Windowsのセットアップの注意点としては、VirtIOを使わないと性能が出ないためSCSIコントローラにVirtIO SCSI Singleを選択する必要があります。また、それに伴いOSインストール時にドライバの読み込みが必要になるので、virtio-driverの入ったISOをマウントするために2つ目のCDROMが必要になります。SATAでセットアップしてから後でVirtIOに変更することもできますが、トラブルを防ぐため正攻法でセットアップしました。
上記の設定をしてインストールを進めていく中で、まず速度の差を実感しました。Win11のセットアップは時間がかかりますが、明らかに速いです。もっとも、これはRyzen 7 7700が速いという気もしますが、IOがネックになっていないというのも大きいと思います。
なんやかんやしてWindowsのセットアップが終わったら、いつものCDMをまわします。以下がその結果で、それぞれMiB/sとIOPSです。
Q1T1については4kで12k IOPSが出ているのでfioのテスト結果と一致しますが、fioで8Q8Tを実行したときには234k IOPSが出ているのに対してVM上では174k IOPSと、いい線いっていますがもう少し出てもいいかと思いました。
帯域についてはQDRの理論上限値32Gbpsで、MB/sに直すと4000MB/sとなり、マルチパスがうまく使えてない気もします。ただ、perfqueryやatopのIBリンクの情報を見ていると、両ポートでパケットの送受信は行われているようです。複数ディスクでのIOが発生したらまた違うのかもしれません。
Writeについては値がぶっ壊れることもなかったので、fioのテスト方法が正しくなかったか、上記のマルチパスがうまく使えていないという問題がある気がします。
virtioの上限についてはPVEホストにtmpfsを作成してVMからRAM上に作成したドライブにベンチマークをした限りはもっと高い値が出たので、何かしらチューニングがあるのかもしれないですが、ぱっと検証した限りはUnsafe WBを使う以外の方法ではこれが限界でした。
ちなみに今回初めてRyzen 7 7700をVMホストとして使いましたが、やっぱりレスポンスがいいので PassMark PerformanceTest をまわしてシングルスレッドの性能を見てみましたが、VMでも4k超えとかなり調子が良いことがわかりました。
ちなみにPassmarkのシングルスレッドの数値と個人的なWindowsを使う感覚としては
~700 なにするのもつらい
1000~1500 もたつくがIOが十分に速ければコア数によってはなんとか使える
1500~2400 IOが速ければそれなりに使える
2400~3000 はやい
3000~4000 目に見えて速い
4000~ 新世界
という感じです。
AMDのCPUの場合、95度に張り付くまでカツカツを攻めるという動きをするので、ついているCPUクーラーと外気温によって大きくスコアが変わるのですが、同じ状態でWindowsをベアインストールして試していたときは4100-4200くらいだったと思います。
なので、多少の仮想化税はありますが、それでも十分速いと思います。ちなみにこのITXの筐体にはAXP90-X47 FULLというFull copperなクーラーを使っています。もともと先に組んだPVE02の筐体に組み込もうとしたのですがクーラーの高さが僅かに高く、箱に入り切らずSHURIKEN 3を買うことに…。
マイグレーションを試してみる
もう一つ気になることとして、PVEでライブマイグレーションをするために正しく共有ストレージとして認識されているか、RAM転送でIBを使うように設定してうまくいくのか、というのがあったので試してみました。ようやくPVE02の出番です。
基本的には01と同じ設定を行い、01側でクラスターを作成して02を参加させました。クラスターを作成するときに、裏LANがあるとそれを追加できるので、IPoIBのインターフェースも追加します。画像では0,1がIBで2がEtherですが、これは数値が高いほうが優先されるという動きになるので、これで作ったあとに間違いに気が付き10.111.1.201を20、10.111.2.201を10、172.20.1.51を1に変えました。
参加した段階でproto=rdmaが書かれたstorage.cfgが02側にも配布されるので、xprtrdmaが読み込まれていれば参加した時点でNFSのRDMAマウントができていました。
ここでハマったのが何故か1G Etherを使ってRAMの転送を行ってしまいIBが使われず困ったのですが、Datacenter→OptionsにMigration settingsという項目があり、どのIPを使うか指定する必要がありました。これをIBの裏LANアドレスを指定することにより、IPoIBですがIBが使われるようになりました。
2024-12-08 04:38:18 use dedicated network address for sending migration traffic (10.111.1.202)
2024-12-08 04:38:18 starting migration of VM 101 to node 'pve02' (10.111.1.202)
2024-12-08 04:38:18 starting VM 101 on remote node 'pve02'
2024-12-08 04:38:19 start remote tunnel
2024-12-08 04:38:20 ssh tunnel ver 1
2024-12-08 04:38:20 starting online/live migration on unix:/run/qemu-server/101.migrate
2024-12-08 04:38:20 set migration capabilities
2024-12-08 04:38:20 migration downtime limit: 100 ms
2024-12-08 04:38:20 migration cachesize: 1.0 GiB
2024-12-08 04:38:20 set migration parameters
2024-12-08 04:38:20 start migrate command to unix:/run/qemu-server/101.migrate
2024-12-08 04:38:21 migration active, transferred 656.7 MiB of 8.0 GiB VM-state, 813.8 MiB/s
2024-12-08 04:38:22 migration active, transferred 1.4 GiB of 8.0 GiB VM-state, 801.0 MiB/s
2024-12-08 04:38:23 migration active, transferred 2.1 GiB of 8.0 GiB VM-state, 803.5 MiB/s
2024-12-08 04:38:24 migration active, transferred 2.9 GiB of 8.0 GiB VM-state, 778.9 MiB/s
2024-12-08 04:38:25 migration active, transferred 3.6 GiB of 8.0 GiB VM-state, 1.0 GiB/s
2024-12-08 04:38:26 migration active, transferred 4.3 GiB of 8.0 GiB VM-state, 783.7 MiB/s
2024-12-08 04:38:27 migration active, transferred 5.2 GiB of 8.0 GiB VM-state, 856.8 MiB/s
2024-12-08 04:38:27 xbzrle: send updates to 36484 pages in 27.2 MiB encoded memory, overflow 2013
2024-12-08 04:38:27 average migration speed: 1.1 GiB/s - downtime 86 ms
2024-12-08 04:38:27 migration status: completed
2024-12-08 04:38:30 migration finished successfully (duration 00:00:12)
TASK OK
ストレージは正しく共有と認識されたので、RAMだけの転送となりました。8GBのRAMを割り当てたWindowsをマイグレしたところ大体10GbpsくらいでRAMの転送がされ、12秒で終わりました。マイグレ中もあえてリモデから色々やっていましたが、一瞬マウスカーソルにラグのようなものが出たと思ったら終わっていました。はやい。
検証した感想
NFSのMPIOやRDMAなどを初めて設定しましたが、かなり良い結果がでたとおもいます。PVE自体は触り始めて1ヶ月経っていないのでお作法的な部分がまだよくわかっていないですが、中身がDebianという15年の付き合いのあるOSなので個人的には非常に取り掛かりやすいです。
PVEはVMwareとは違ってハードウェアの対応の広さや、困ってもLinux的に色々とどうにかできるのが良いと思いました。それ以外にもHAレプリケーションやVMwareでいうVDPがより使いやすいPBSとして提供されているなど、非常によくできていると感じました。
PVE自体にvSAN的なCephもあり、今更ストレージとコンピュートノードを分けるなや!!時代はHCIやで!!! という思想も感じますが、小さいマシンだとIOスロット数の問題やOSD自体のIOコンピュートコストが馬鹿にできないこともあり、できればIOを分けてホストはVM/Containerの処理に専念させたい、ということもあります。
合計100コア以上のXeonSP/EPYCと数TBのRAMと有り余るSSDと100GbEを搭載したマシンが10台以上ある、というような構成ならともかく、家で使うときにはSPoFができることを承知で ストレージはストレージマシンにまとめ、 IBと10Gと起動用SATA DOMに相当するものを積んでおけばとりあえず快適に使える、というのは便利です。
ノードごとにNVMEストレージを揃えたくないという気持ちがあったので、IBさえ繋いでおけばSATA SSDより速い大容量な集約ストレージが使えることになり、これを解決できたのは個人的にかなり大きいです。
また、特にWindowsなどの検証をするとIOの速さが利用度の快適さに直結するので、IOの速さというのは譲れない要件でもあります。ストレージマシンが死ぬと地獄を見るというのは回避できませんが、クラスター型ストレージが死なないかと言われるとまたそれも微妙なところで、メタデータに問題が起きるとこれも地獄になります。
そういった面で問題が起きたときにシンプルさが強さになることもあります。
共有ブロックストレージ+クラスター型ファイルシステムではなく、NFSというファイルベースストレージなのもシンプルでよいです。色々トラブルを踏むとシンプルさに帰結する気がします。
代償としてNFSは細かいIOが苦手、というのがありますが、今回のRDMAの結果からすると十分実用域だと思います。
ただ、散々IBについて話してきましたが、今からお家でInfinibandをおすすめできるか、というと、微妙…むしろやめといたほうが無難、と言わざるを得ないです。
以前も書いたように、IB自体はL2で使う限りはスイッチやHCA含め、帯域に対しての消費電力がかなり低いのでいい面があるのですが、IBはIBでありイーサネットではないので、利用できる用途がかなり限られます。自分もほぼストレージ用インターフェースとしてしか使っていません。
やはり用途が限られるのとIB特有の必要な知識があまり表面に出てこないので、IBまわりは本当に需要がなく、国内外で捨て値で売られています。今回検証に使ったスイッチのSX6036なんて3000円で買っています。元が底値で買っているので、仮にこれから一から揃えるとしても、万が一手放すときには再販価値はない、という前提になります。
まあ16/32Gb FC-SANを始めたいと思うのであればそれよりも安価ですが、FC-SANはドライバさえあれば確実にブロックデバイスとして認識できるというメリットもあります。あまりにもコアなメリットですが特定のときに刺さります。
しかし、再販価値がない前提で物が底値で手に入るというのは、わかっているオタクからすると二束三文で高速IOを手に入れられるというメリットでもあります。「もうIBやめたい」と思いながらも物が安いので抜け出せず、なんだかんだ物が増えてしまいました。
その中で「一部のSASケーブルはIBのQSFPケーブルとしても使える(※ただしQDRのみ)」というしょうもない知識を手に入れたので、ケーブルなどもかなり安く手に入れられるようになりました。一度嵌ると抜け出せない沼です。
総評としては、「確かにIBとRDMAはかなり高速でこれに依存すればノードの構成が楽になるものの、これを目当てに新規でIB一式を揃えようとするのは覚悟が必要になるので手放しでお薦めはできない」でしょうか。
もう少し使ってみたうえで問題が起きたらまた記事にしようと思います。
以上!
[ コメントを書く ] ( 115 回表示 ) | このエントリーのURL | ( 2.8 / 56 ) | ツイート
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 進む> 最後へ>>