Amazon Linux 2 でiSCSIを使ってみる

ネットワーク経由でデータを共有する方法の一つとしてNFSやSMBなどの、ファイルシステムベースのものがある一方で、ブロックデバイスとして共有する方法もあります。 今回はSCSIをネットワーク上で使用できるようにしたiSCSIをAmazon Linux 2 で利用する方法を整理しました。
2023.03.29

iSCSIについて

SCSI (Small Computer System Interface) は、ビデオカードやストレージデバイスなどの周辺機器を接続するためのインターフェース規格です。 一方、iSCSI (Internet Small Computer System Interface) は、TCP/IPネットワークを利用して、SCSIコマンドをやりとりするためのプロトコルです。 概ね、SCSIをネットワーク上で使用できるようにしたものがiSCSIです。

SCSIはHDDやSSDなどのブロックデバイスで使用されることがあるのですが、iSCSIでも同様にネットワークを介してブロックデバイスとして認識されます。

近い技術でNFSなどのネットワークファイルシステムがあるのですが、こちらはファイルシステムとして認識されます。 一方、iSCSIではブロックデバイスとして認識されます。

iSCSIの用語解説

  • ターゲット
    • ストレージを提供する機器のことを指します。ストレージを提供するサーバーがターゲットになります。
  • イニシエーター
    • ストレージサーバーに対してアクセスするためのクライアントのことを指します。
  • バックストア
    • iSCSIのターゲットサーバーが扱うストレージ領域のことを指します。バックストアが提供されることで、プログラムがデータを読み書きできるようになります。今回は、EBSをバックストアとして利用します。
  • IQN
    • iSCSI Qualified Nameの略で、iSCSIで利用されるサーバーまたはストレージの識別子です。識別子ということなので、重複しないように気をつける必要があります。
    • 例: iqn.2023-03.com.example:storage0といった形式で表現されます。
  • LUN
    • Logical Unit Numberの略で、ストレージサーバーから提供される論理的なストレージ領域を指します。ACLを利用し権限を設定することで、複数のクライアントからのアクセスを管理することも可能です。

セットアップ

今回は以下のような構成でサーバーを構築しました。

  1. ターゲットサーバー(t3.micro) 10GiBのEBSボリュームを別途アタッチ済み
  2. イニシエーターサーバー(t3.micro)

ターゲットサーバーはTCPの3260番にアクセス可能である必要があるため、セキュリティグループを以下のように設定しておきました。

ちなみに、IQNの仕様はRFCで決まっています。 今回は完全な検証用なので適当に設定しましたが、本番で利用する際は重複やネーミングルールに気を使うと良いでしょう。

  • https://tex2e.github.io/rfc-translater/html/rfc3721.html

ターゲット側

ソフトウェアのインストール

まずはじめに、ターゲットサーバーの設定をします。 ターゲットの設定はtargecliを利用するので、そのインストールを行います。

iscsiのターゲットのセットアップ

# ブロックデバイスの確認
$ lsblk
NAME          MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0   8G  0 disk
├─nvme0n1p1   259:1    0   8G  0 part /
└─nvme0n1p128 259:2    0   1M  0 part
nvme1n1       259:3    0  10G  0 disk # <= これをバックストアとして利用する

# python-gobjectはtargetcliが依存しているためインストール
$ sudo yum install -y targetcli python-gobject.x86_64 
$ sudo systemctl start target
$ sudo systemctl enable target

ターゲットの設定

インストールが完了したのでtargetcliを利用してターゲットの設定を行っていきます。 今回はインタラクティブモードでの設定を行います。

ターゲットの設定

$ sudo targetcli
Warning: Could not load preferences file /root/.targetcli/prefs.bin.
targetcli shell version 2.1.53
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]

# バックストアの作成
/> /backstores/block create name=sample-bs dev=/dev/nvme1n1
Created block storage object sample-bs using /dev/nvme1n1.

# iSCSIのターゲットを作成
# ターゲットのIQNをここで指定する。
/> /iscsi create iqn.2023-03.sample.ec2:sample
Created target iqn.2023-03.sample.ec2:sample.
Created TPG 1.
Global pref auto_add_default_portal=true
Created default portal listening on all IPs (0.0.0.0), port 3260.

# LUNを作成。この際バックストアと関連付ける
/> /iscsi/iqn.2023-03.sample.ec2:sample/tpg1/luns create /backstores/block/sample-bs
Created LUN 0.

# Access Control Listの作成
# iqn.2023-03.sample.ec2:sample-initiatorはクライアント側のIQN
/> /iscsi/iqn.2023-03.sample.ec2:sample/tpg1/acls create iqn.2023-03.sample.ec2:sample-initiator
Created Node ACL for iqn.2023-03.sample.ec2:sample-initiator
Created mapped LUN 0.

# ここまでの設定の確認
/> ls
o- / ......................................................................................................................... [...]
  o- backstores .............................................................................................................. [...]
  | o- block .................................................................................................. [Storage Objects: 1]
  | | o- sample-bs ................................................................... [/dev/nvme1n1 (10.0GiB) write-thru activated]
  | |   o- alua ................................................................................................... [ALUA Groups: 1]
  | |     o- default_tg_pt_gp ....................................................................... [ALUA state: Active/optimized]
  | o- fileio ................................................................................................. [Storage Objects: 0]
  | o- pscsi .................................................................................................. [Storage Objects: 0]
  | o- ramdisk ................................................................................................ [Storage Objects: 0]
  o- iscsi ............................................................................................................ [Targets: 1]
  | o- iqn.2023-03.sample.ec2:sample ..................................................................................... [TPGs: 1]
  |   o- tpg1 ............................................................................................... [no-gen-acls, no-auth]
  |     o- acls .......................................................................................................... [ACLs: 1]
  |     | o- iqn.2023-03.sample.ec2:sample-initiator .............................................................. [Mapped LUNs: 1]
  |     |   o- mapped_lun0 ............................................................................. [lun0 block/sample-bs (rw)]
  |     o- luns .......................................................................................................... [LUNs: 1]
  |     | o- lun0 .............................................................. [block/sample-bs (/dev/nvme1n1) (default_tg_pt_gp)]
  |     o- portals .................................................................................................... [Portals: 1]
  |       o- 0.0.0.0:3260 ..................................................................................................... [OK]
  o- loopback ......................................................................................................... [Targets: 0]

# ユーザーの認証情報の設定
# 認証方法はCHAPが利用される
/> /iscsi/iqn.2023-03.sample.ec2:sample/tpg1/acls/iqn.2023-03.sample.ec2:sample-initiator set auth userid=sample-user
Parameter userid is now 'sample-user'.
/> /iscsi/iqn.2023-03.sample.ec2:sample/tpg1/acls/iqn.2023-03.sample.ec2:sample-initiator set auth password=supersecret
Parameter password is now 'supersecret'.

# 設定を保存し終了
/> saveconfig
Configuration saved to /etc/target/saveconfig.json
/> exit
Global pref auto_save_on_exit=true
Last 10 configs saved in /etc/target/backup/.
Configuration saved to /etc/target/saveconfig.json

イニシエーター

次にイニシエータの設定をします。

iscsiのイニシエーターのセットアップ

# イニシエーターのソフトウェアのインストール
$ sudo yum install iscsi-initiator-utils -y

# ターゲットの探索
# 成功すると利用可能なターゲットが情報が取得できる
$ sudo iscsiadm -m discovery -t st -p <ターゲットサーバーのIP>
<ターゲットサーバーのIP>,1 iqn.2023-03.sample.ec2:sample

# イニシエーターのIQNを設定
$ sudo nano /etc/iscsi/initiatorname.iscsi
# 以下に変更する
InitiatorName=iqn.2023-03.sample.ec2:sample-initiator

# イニシエーター側に認証情報を設定する
$ sudo nano /etc/iscsi/iscsid.conf
# 以下のように設定します。(設定ファイルより一部抜粋)

# *************
# CHAP Settings
# *************

# To enable CHAP authentication set node.session.auth.authmethod
# to CHAP. The default is None.
node.session.auth.authmethod = CHAP

# To set a CHAP username and password for initiator
# authentication by the target(s), uncomment the following lines:
node.session.auth.username = sample-user
node.session.auth.password = supersecret


# iscsidサービスを再起動し、設定を読み込ませる
sudo systemctl restart iscsid.service

# ログインする
$ sudo iscsiadm -m node -T iqn.2023-03.sample.ec2:sample --login
Logging in to [iface: default, target: iqn.2023-03.sample.ec2:sample, portal: <ターゲットサーバーのIP>,3260] (multiple)
Login to [iface: default, target: iqn.2023-03.sample.ec2:sample, portal: <ターゲットサーバーのIP>,3260] successful.

# ブロックデバイスの確認
$ lsblk -fs
NAME        FSTYPE LABEL UUID                                 MOUNTPOINT
sda         ext4         1f4b506d-8390-4e6a-92bc-e52f1d45f602 # <= これがiSCSIで利用できるデバイス
nvme0n1p1   xfs    /     80b3e64c-379e-4297-a6a1-356635495cfc /
└─nvme0n1
nvme0n1p128
└─nvme0n1

無事に、ブロックデバイスとしてsdaが認識されました。

せっかくなので、ext4でファイルシステムを構築し、マウントしてみます。 ここからの流れはEBSでマウントするのと同じです。

ファイルシステムの作成とマウント

# EXT4でファイルシステムを作成
$ sudo mkfs.ext4 /dev/sda
mke2fs 1.42.9 (28-Dec-2013)
/dev/sda is entire device, not just one partition!
Proceed anyway? (y,n) y # 今回はパーティションを分けていないため警告が出ているが「y」で実行する
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
655360 inodes, 2621440 blocks
131072 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=2151677952
80 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

# マウント先のディレクトリの作成
$ sudo mkdir -p /mnt/iscsi

# fstabを編集し、自動でマウントするように設定
$ sudo nano /etc/fstab

# 以下のように設定(1行目はルートファイルシステムなので変更しない
UUID=80b3e64c-379e-4297-a6a1-356635495cfc     /           xfs    defaults,noatime  1   1
UUID=1f4b506d-8390-4e6a-92bc-e52f1d45f602     /mnt/iscsi  ext4   defaults,noatime  0   2

# マウント
$ sudo mount -a
$ lsblk -fs
NAME        FSTYPE LABEL UUID                                 MOUNTPOINT
sda         ext4         1f4b506d-8390-4e6a-92bc-e52f1d45f602 /mnt/iscsi
nvme0n1p1   xfs    /     80b3e64c-379e-4297-a6a1-356635495cfc /
└─nvme0n1
nvme0n1p128
└─nvme0n1

無事にext4としてマウントされました。

終わりに

今回はiSCSIをAL2上で利用する方法について整理しました。

EBSでも複数のインスタンスにアタッチできたりするのであまり出番は無いかもしれません... ただ、既存システムからの移行などでどうしてもiSCSIを利用したい局面などでは便利なんじゃないでしょうか?

付録

今回はハイパーバイザがNitroであるt3インスタンスを利用しましたが、Xen系であるt2などでは少し挙動が変わったりします。 実は、AL2内のudevルールでは/dev/xvdaに対して/dev/sdaにシンボリックリンクが作成されます。 この関係で、イニシエーター側でXenのインスタンスを利用するとシンボリックリンクとiscsidのデバイスが衝突して上手く/dev/sdaが使えなくなります。 つまるところ、ファイルシステムの作成やマウントなどで不都合が生じます。

以下がそのルールです。

NitroのインスタンスではEBSはnvme*として認識されるので、udevのルールに引っかからず、シンボリックリンクが自動で作成されません。