PC に Infiniband HCA を搭載して、CentOS 7 で (ミニ)SANストレージを構築してみたいと思います。
HCA は、QDR 40Gb/s をサポートしている Mellanox ConnectX-2 VPI (Single Port) を使用します。
Infiniband といっても、Infiniband スイッチは入手できなかったので、下記のようにストレージへの接続元と直結することにします。
|
KVM ホストのストレージプールとして使用 |
Infiniband は上位レイヤでネットワークやストレージ関連の様々なプロトコルを使用できますが、今回は SRP (SCSI RDMA Protocol) を使用します。
ストレージ側が SRP Target、アクセス元のKVMホストが SRP Initiator となります。
以下、SRP Target の構築です。
Infiniband セットアップ
では、まず Infiniband のドライバやユーティリティ等をインストールです。これにはいくつか選択肢があります。
- rpm パッケージ
- OFED (Open Fabrics Enterprise Distribution)
- Mellanox OFED (Mellanox 版の OFED)
HCA が Mellanox 製なので Mellanox OFED を使いたいところです。しかし、この後の SRP Target の構築を LIO (Linux IO Target) で行うため、Mellanox OFED は使用できません。
LIO では kernel モジュールの設定や参照を ConfigFS (sysfs のようなメモリ上の仮想ファイルシステム。ユーザスペースから kernel モジュールの設定や参照が可能。) で行うのですが、Mellanox OFED の SRP Target モジュール (ib_srpt.ko) が ConfigFS に対応していないためです。
よって、SRP Target 側は rpm パッケージからインストールします。
(ただ、rpm には Mellanox OFED に入っている hca_self_test.ofed のようなツールはありません)
CentOS 7 のインストール時に Infiniband HCA が検出されると、anaconda により rdma がインストールされますが、その他にも必要なパッケージをインストールします。
$ sudo yum install libibverbs libibverbs-utils
$ sudo yum install opensm
$ sudo yum install libmlx4 libmlx5 libmthca
$ sudo yum install libocrdma
$ sudo yum install librdmacm librdmacm-utils ibacm
$ sudo yum install infiniband-diags ibutils
$ sudo yum install perftest qperf
$ sudo yum install dapl dapl-utils
$ sudo yum install libibcommon libibcm
Infiniband ファブリックには Subnet Manager が 1つは存在している必要があります。
今回は HCA を直結するので、ストレージ側で Subnet Manager を稼働させることにします。
1 Port の HCA 1個だけ搭載している場合は、特に設定を行わずデフォルトのままでも Subnet Manager は動作しますので、このまま opensm サービスを起動します。
$ sudo systemctl start opensm
$ sudo systemctl enable opensm
SRP Target モジュールは、デフォルトで rdma サービス起動時にロードされるようになっています。
$ more /etc/rdma/rdma.conf
# Load IPoIB
IPOIB_LOAD=yes
# Load SRP (SCSI Remote Protocol initiator support) module
SRP_LOAD=yes
# Load SRPT (SCSI Remote Protocol target support) module
SRPT_LOAD=yes
# Load iSER (iSCSI over RDMA initiator support) module
ISER_LOAD=yes
# Load iSERT (iSCSI over RDMA target support) module
ISERT_LOAD=yes
ib_srpt.ko モジュールがロードされていることを確認します。
$ lsmod | grep srp
ib_srpt 52289 0
target_core_mod 303808 11 target_core_iblock,target_core_pscsi,iscsi_target_mod,ib_srpt,target_core_file,ib_isert
ib_srp 42448 0
scsi_transport_srp 20725 1 ib_srp
scsi_tgt 20027 1 scsi_transport_srp
ib_cm 42689 5 rdma_cm,ib_srp,ib_ucm,ib_srpt,ib_ipoib
ib_sa 33950 6 rdma_cm,ib_cm,mlx4_ib,ib_srp,rdma_ucm,ib_ipoib
ib_mad 47486 5 ib_cm,ib_sa,mlx4_ib,ib_srpt,ib_umad
ib_core 88311 16 rdma_cm,ib_cm,ib_sa,iw_cm,xprtrdma,mlx4_ib,ib_mad,ib_srp,ib_ucm,ib_iser,ib_srpt,ib_umad,ib_uverbs,rdma_ucm,ib_ipoib,ib_isert
これで Infiniband のセットアップは完了です。
SRP Target 構築
続いて、LIO (Linux-IO) を使用して SRP Target を構築します。
LIO は kernel モジュール (target_core_mod.ko、iscsi_target_mod.ko 等) として Linux に標準で組み込まれている SCSI Target です。
Python ベースの targetcli (LIO Shell) を使って管理します。
LIO の設定には ConfigFS が使用されます。
ConfigFS を使うには、/sys/kernel/config が ConfigFS としてマウントされている必要がありますが、CentOS 7 では OS インストール時に Inifiniband HCA が検出されると、デフォルトで自動マウントされるようになります。
LIO モジュールのディレクトリ /sys/kernel/config/target/ が作成されており参照できると思います。
$ cat /sys/kernel/config/target/version
Target Engine Core ConfigFS Infrastructure v4.1.0-rc2-ml on Linux/x86_64 on 3.10.0-229.14.1.el7.x86_64
targetcli をインストールします。
$ sudo yum install targetcli
targetcli はシェルのような CUI のツールで、iSCSI や FC などのネットワークファブリックのセクションと、物理、論理ブロックデバイス等のセクション (Backstores) に分かれています。
$ sudo targetcli //初回起動時は以下の Warning が出る
Warning: Could not load preferences file /root/.targetcli/prefs.bin.
targetcli shell version 2.1.fb37
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.
/>
/> ls
o- / .............................................................................................. [...]
o- backstores ................................................................................... [...]
| o- block ....................................................................... [Storage Objects: 0]
| o- fileio ...................................................................... [Storage Objects: 0]
| o- pscsi ....................................................................... [Storage Objects: 0]
| o- ramdisk ..................................................................... [Storage Objects: 0]
o- iscsi ................................................................................. [Targets: 0]
o- loopback .............................................................................. [Targets: 0]
o- srpt .................................................................................. [Targets: 0]
/>
targetcli を終了すると、自動で設定情報が /etc/target/saveconfig.json に保存されます。
(グローバルパラメータの
auto_save_on_exit がデフォルトで有効になっているため)
/> exit
Global pref auto_save_on_exit=true
Last 10 configs saved in /etc/target/backup.
Configuration saved to /etc/target/saveconfig.json
ただし、 ファイルに保存しても OS を再起動すると設定はクリアされてしまいます。
target サービスを有効化しておくと、OS 起動時にファイル保存した設定がリストアされるようになります。
$ sudo systemctl start -t service target
$ sudo systemctl enable -t service target
targetcli では、まず Backstore を定義します。
この Backstore の領域(ボリューム)を LUN に割り当て、SRP Initiator からアクセスする形になります。
Backstore には以下の Storage Object があります。
- BLOCK ... ブロックデバイス
- FILEIO ... ファイルシステム上のファイル
- PSCSI ... SCSIパススルー
- RAMDISK ... メモリをブロックデバイスとして使う
BLOCK はブロックデバイスをそのまま割り当てます。Write through なので、突発的な電源断などでシステムが落ちた場合でも、データロスのリスクが低いです。
FILEIO はファイルをディスクイメージのように使用します。(ブロックデバイスを指定することも可能)
Write back に設定すればパフォーマンスが大幅に向上しますが、突発的なダウン等のおけるデータロスのリスクが高くなります。
今回は、SSD * 3台で構成した RAID5 Array (Fake RAID) を BLOCK に指定することにします。
/> backstores/block create BSBLK01 /dev/md/array0_0
Created block storage object BSBLK01 using /dev/md/array0_0.
/> ls backstores/block/
o- block ........................................................................... [Storage Objects: 1]
o- BSBLK01 ....................................... [/dev/md/array0_0 (476.9GiB) write-thru deactivated]
次に、SRP Target の設定です。
kernel モジュールの ib_srpt.ko がロードされていれば、targetcli のツリーに srpt が表示されているはずです。
また、targetcli で srpt の設定を行うと、ConfigFS の /sys/kernel/config/target/srpt/ 配下に書き込まれます。
/> srpt/ info
Fabric module name: srpt
ConfigFS path: /sys/kernel/config/target/srpt
Allowed WWN types: ib
Allowed WWNs list: ib.fe800000000000000002c903000f826d
Fabric module features: acls
Corresponding kernel module: ib_srpt
/>
SRP Target のインスタンスを作成します。
/> cd srpt
/srpt> create fe800000000000000002c903000f826d
Created target ib.fe800000000000000002c903000f826d.
/srpt> ls
o- srpt .................................................................................... [Targets: 1]
o- ib.fe800000000000000002c903000f826d .................................................. [no-gen-acls]
o- acls ................................................................................... [ACLs: 0]
o- luns ................................................................................... [LUNs: 0]
create のパラメータの WWN には、HCA の Port GUID を指定します。
Port GUID は、/sys/class/infiniband/
(HCAのデバイス名)/ports/
(ポート番号)/gids/0 で確認できます。
今回の 1 port の HCA の場合は以下を参照します。
$ cat /sys/class/infiniband/mlx4_0/ports/1/gids/0
fe80:0000:0000:0000:0002:c903:000f:826d
Backstore で定義した領域を LUN に割り当てます。
/srpt> ib.fe800000000000000002c903000f826d/luns create /backstores/block/BSBLK01
Created LUN 0.
/srpt> ls
o- srpt .................................................................................... [Targets: 1]
o- ib.fe800000000000000002c903000f826d .................................................. [no-gen-acls]
o- acls ................................................................................... [ACLs: 0]
o- luns ................................................................................... [LUNs: 1]
o- lun0 ........................................................ [block/BSBLK01 (/dev/md/array0_0)]
最後に、SRP Target インスタンスの ACL を設定します。
SRP Initiator から接続するには、ACL に WWPN として SRP Initiator の PortID が登録されていなければなりません。(iSCSI の場合は省略可能)
SRP Initiator は SRP Target に接続する時、認証要求 SRP_LOGIN_REQ で Initiator 側の PortID を送信します。
この PortID は、接続時に syslog に書かれるメッセージから確認することもできますが、SRP Initiator が Mellanox OFED の srp_daemon を使っている場合、
"SRP Target 側 Port GUID を Byte 単位で逆に並べた値 (8byte)" + "SRP Initiator の Port GUID (8byte)"
で構成されます。
今回のシステムでは、
- 接続先 SRP Target の Port GUID ... 0x0002c903000f826d
- 接続元 SRP Initiator の Port GUID ... 0x0002c903000f81e1
となっています (SRP Initiator については次回書きます) ので、
SRP_LOGIN_REQ で送信される PortID は、"6d820f0003c90200" + "0002c903000f81e1" になります。
ちなみに、実際に SRP Initiator が接続してきた時の syslog が以下です。
kernel: ib_srpt Received SRP_LOGIN_REQ with i_port_id 0x6d820f0003c90200:0x2c903000f81e1, t_port_id 0x2c903000f826c:0x2c903000f826c and it_iu_len 260 on port 1 (guid=0xfe80000000000000:0x2c903000f826d)
この PortID を ACL に登録します。
自動で LUN0 に適用されます。
/srpt> ib.fe800000000000000002c903000f826d/acls create 6d820f0003c902000002c903000f81e1
Created Node ACL for ib.6d820f0003c902000002c903000f81e1
Created mapped LUN 0.
/srpt> ls
o- srpt .................................................................................... [Targets: 1]
o- ib.fe800000000000000002c903000f826d .................................................. [no-gen-acls]
o- acls ................................................................................... [ACLs: 1]
| o- ib.6d820f0003c902000002c903000f81e1 ........................................... [Mapped LUNs: 1]
| o- mapped_lun0 ........................................................ [lun0 block/BSBLK01 (rw)]
o- luns ................................................................................... [LUNs: 1]
o- lun0 ........................................................ [block/BSBLK01 (/dev/md/array0_0)]
以上で SRP Target の準備が完了しました。
次は SRP Initiator 側のセットアップを行います。