ストレージ実務 — RAID・スナップショット・iSCSI・fio
iSCSI LUN を接続して fio で測る
目標
同じVMの中にLIOターゲットを立ち上げてLUNを提供し、イニシエーターで、ディスカバリー・ログイン・_netdevマウント・自動ログインを構成したあと、そのディスクの上でfioを使って、キューの深さによるIOPSとレイテンシを測り、JSONから数字を取り出して報告します。
なぜ重要なのか
SANのLUNをサーバーに取り付けることは、インフラエンジニアの日常ですが、ローカルディスクと違う3つのこと(ネットワークを待つマウント、名前によるアクセス制御、複数のパス)を知らないと、再起動1回でサーバーが止まります。そして、「ディスクが遅い」という報告に答えるには、条件を固定した測定が必要です。キューの深さを1つ変えるだけで、IOPSとレイテンシが一緒に動くのを自分の目で見れば、仕様書の数字と、アプリケーションが体験する数字がなぜ違うのかを説明できるようになります。
このラボは、Ubuntu 24.04のVM上で、rootとして動きます。ターゲットとイニシエーターが同じVMの中で127.0.0.1:3260で出会うため、ネットワークストレージの手順をそのとおりたどりますが、測定した数字は、本物のSANの数字ではありません。fileioバックストアは、ターゲット側のページキャッシュを経由するため、キューの深さ1でも数万IOPSが出ます(実測)。絶対値ではなく、条件を1つ変えたときに数字がどう動くかを見るのが目的です。セッションは60分で始まり、最大180分まで延長でき、VMはセッションが終わると消えます。
ステップ
/var/lib/sto/lun0.img(512MiB)をfileioバックストアlun0として作成し、ターゲットiqn.2026-09.io.labhub:stoのtpg1にLUNとして取り付け、このVMのイニシエーター名をACLに入れたあと、targetcli saveconfigで保存してください。127.0.0.1のポータルをディスカバリー(sendtargets)し、出力を/root/sto/iscsi/discovery.txtに保存してください。- ターゲットにログインして、新しいディスクがTRAN
iscsiと見えるようにし、lsblk -o NAME,SIZE,TRAN,VENDOR,MODELの出力を/root/sto/iscsi/lsblk.txtに保存してください。 - iSCSIディスクをext4でフォーマットし、
/etc/fstabの行で/mnt/iscsiにマウントされるようにしてから、今すぐマウントしておいてください。行のデバイスの表記はUUID=、オプションに必ず入れるもの:_netdev。 - ノードレコードの
node.startupをautomaticに変えてください。 /mnt/iscsi/fio.dat(128MiB)に、4KiBのrandread、libaio、direct=1、iodepth=1、10秒で測り、JSONを/root/sto/fio/qd1.jsonに保存してください。- 同じ条件で
iodepth=32だけを変えて測り、JSONを/root/sto/fio/qd32.jsonに保存してください。 /root/sto/fio/report.txtに、qd1_iops=、qd1_p99_us=、qd32_iops=、qd32_p99_us=、qd32_little=の5行を、JSONから計算して書いてください。
参考
- ターゲット:
targetcli ls、/backstores/fileio create、/iscsi create、…/tpg1/luns create、…/tpg1/acls create、saveconfig。 - イニシエーター:
iscsiadm -m discovery -t sendtargets -p 127.0.0.1、iscsiadm -m node -T <IQN> -p 127.0.0.1 --login、iscsiadm -m session。 - fioのJSON:
jobs[0].read.iops、jobs[0].read.lat_ns.mean、jobs[0].read.clat_ns.percentile["99.000000"](ナノ秒)。 - よくある間違い1: fstabに
/dev/sdbを書いたり、_netdevを抜いたりする場合です。 - よくある間違い2:
direct=1を抜いて、ページキャッシュの速度をディスクの速度として報告してしまう場合です。
LIOターゲットでLUNを提供する
/var/lib/sto/lun0.img(512MiB)をfileioバックストアlun0として作成し、ターゲットiqn.2026-09.io.labhub:stoのtpg1にLUNとして取り付けてください。このVMのイニシエーター名(/etc/iscsi/initiatorname.iscsiのInitiatorName=の値)をACLに入れ、targetcli saveconfigで設定を保存してください。
targetcliは、パスのような形のツリーを埋めていきます。/backstores/fileio create、/iscsi create、/iscsi//tpg1/luns create、/iscsi//tpg1/acls createです。ポータル(0.0.0.0:3260)は、ターゲットを作るときに既定で作られます。
ターゲットのディスカバリー
イニシエーターで127.0.0.1のポータルをディスカバリー(sendtargets)し、その出力を/root/sto/iscsi/discovery.txtに保存してください。
iscsiadm -m discovery -t sendtargets -p <ポータル>です。ディスカバリーはセッションを確立せず、ノードレコードだけを作ります。
ログインして新しいディスクを確認する
ターゲットiqn.2026-09.io.labhub:stoにログインしてください。新しくできたディスクが、lsblkのTRAN列にiscsiと見える必要があります。lsblk -o NAME,SIZE,TRAN,VENDOR,MODELの出力を/root/sto/iscsi/lsblk.txtに保存してください。
iscsiadm -m node -T -p <ポータル> --loginです。ログインしたセッションは、iscsiadm -m sessionで見ます。
_netdevでfstabに登録する
iSCSIディスクをext4でフォーマットし、/etc/fstabの行で/mnt/iscsiにマウントされるようにしてください。行のデバイスの表記はUUID=、オプションに必ず入れるもの: _netdev。mount /mnt/iscsiのように、fstabの行で取り付けて、今マウントされている必要があります。
このディスクは、/dev/disk/by-path/ip-127.0.0.1:3260-iscsi-iqn.2026-09.io.labhub:sto-lun-0でも指せます。/dev/sdXという名前は起動ごとに変わることがあるので、fstabにはUUIDを書きます。_netdevがないと、起動時にネットワークより先にマウントを試みます。
自動ログインを有効にする
ターゲットiqn.2026-09.io.labhub:sto(ポータル127.0.0.1)のノードレコードで、node.startupをautomaticに変えてください。
iscsiadm -m node -T -p <ポータル> --op update -n node.startup -v automaticです。現在の値は、iscsiadm -m node -T -p <ポータル>の出力から見つけられます。
キューの深さ1で測る
fioで/mnt/iscsi/fio.dat(サイズ128MiB)に、4KiBのランダム読み取りをioengine=libaio、direct=1、iodepth=1で10秒間(runtime=10、time_based)測り、JSONの結果を/root/sto/fio/qd1.jsonに保存してください。
fio --name=<名前> --filename=<ファイル> --size=128M --rw=randread --bs=4k --ioengine=libaio --direct=1 --iodepth=1 --runtime=10 --time_based --output-format=json --output=<ファイル>の形です。direct=1を抜くと、ページキャッシュを測ってしまいます。
キューの深さ32で測る
ステップ6と同じファイル、同じ条件で、iodepth=32だけを変えてもう一度測り、JSONの結果を/root/sto/fio/qd32.jsonに保存してください。
条件を1つだけ変えて初めて比較になります。名前と出力ファイルとiodepthだけを変えてください。
JSONから数字を取り出すこととリトルの法則
2つのJSONから数字を取り出し、/root/sto/fio/report.txtに5行を書いてください。qd1_iops=、qd1_p99_us=、qd32_iops=、qd32_p99_us=(IOPSは四捨五入した整数、p99はclat_ns.percentileの99.000000をマイクロ秒に直して四捨五入した整数)、そしてqd32_little=(qd32のIOPS × 平均レイテンシlat_ns.meanを秒に直した値で、小数第1位まで)です。
値は手で移さず、python3でJSONを読んで計算してください。jobs[0]['read']の下にiops、lat_ns、clat_nsがあります。ナノ秒は、1,000で割るとマイクロ秒、10億で割ると秒です。qd32_littleがキューの深さに近ければ、リトルの法則が合ったことになります。