トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

技術的雑談-iSCSIお試し

技術的雑談-iSCSIお試し


 環境

  • CentOS5.2
    • uname -a → Linux hogehoge 2.6.18-92.1.6.el5.centos.plusxen #1 SMP Thu Jun 26 13:43:14 EDT 2008 i686 i686 i386 GNU/Linux

 目的・範囲

  • iSCSIのtargetとinitiatorをセットアップし、iSCSIのデバイスを公開して使ってみる。
  • マルチパスとかはやらない
  • ファイルシステム自体はext3にしたので、同時マウントには対応しない。(多分ファイルシステムがブッ壊れる。)

 前提


SCSIの世界では

target
:SCSIによってコントロールされるもの(例:HDDとか)
initiator
:SCSIで命令する側(例:OS)
SCSIバス
:SCSIは(概念的には)バス構成なので、1本のヒモにつかまって複数のデバイスがぶら下がって通信する。そのヒモのこと。(ただし、iSCSIはネットワーク経由なのでヒモじゃないっていえばヒモじゃない…。昔の名残です。)
デバイス
:SCSIバスに接続されているもの。targetもinitiatorもデバイスの一つ。target/initiatorは単に「呼びかけを始める人」「呼びかけられる人」という役割でしかない。ただし、一般的にDiskがPCに呼びかけることは無いので事実上は半固定的。かも。

と、いう。

また、targetには「target ID(tid)」という番号が振られる。これは単一SCSIバス内でユニーク(じゃないとマズい)。また、今回使用するiSCSI実装ではtarget:0は指定できないらしい。(なんでだろ?initiatorがtid:0って事なのかな?イミフ)
古き良きケーブル接続SCSI外付けHDDとか使ったことがある場合、本体後ろにあるダイアルとかで設定していた「番号」がtidです。

さらに、「単一デバイス内に複数の論理ボリュームがある」とされていて、それのことを「Logical unit」といい、それに番号を振って「Logical unit unmber = lun」という。
lunは0から始まる。
lunはそれの属するtarget内でユニーク。(当然)

なので、単一SCSIバス上ではtidとlunが指定されるとユニークな領域が特定される。

iSCSIはファイルシステムよりも下のレイヤーのものなので、ファイルシステムとかLVMとかは関係ない。
外付けSCSIディスクのケーブルがネットワークケーブルになっただけ。
(NFSとかFTPとかとは違うので注意。)

  target側の設定


まずはtarget(ディスク側)の設定。

Install


yumを使いました。

# yum install scsi-target-utils.i386

で、インストールされたファイル一覧。

/etc/rc.d/init.d/tgtd
/usr/sbin/tgtadm
/usr/sbin/tgtd
/usr/share/doc/scsi-target-utils-0.0
/usr/share/doc/scsi-target-utils-0.0/README
/usr/share/doc/scsi-target-utils-0.0/README.iscsi
/usr/share/man/man8/tgtadm.8.gz

サービス有効化


iSCSIのターゲットを稼動させるには「tgtd」というデーモンが動いている必要がある。

# chkconfig --add tgtd
# chkconfig --list tgtd
	tgtd            0:off   1:off   2:off   3:off   4:off   5:off   6:off
# chkconfig tgtd on
# chkconfig --list tgtd
	tgtd            0:off   1:off   2:on    3:on    4:on    5:on    6:off
# service tgtd start
Starting SCSI target daemon:                               [  OK  ]

サービスの稼動確認


ターゲットの操作はターゲットが稼動しているマシン上で「tgtadm」コマンドで行います。

# tgtadm --lld iscsi --mode target --op show
# (→何も表示されないのが正解)

tgtdが起動していない場合はエラーが出る。

tgtadm: can't connect to the tgt daemon, Connection refused
tgtadm: can't send the request to the tgt daemon, Transport endpoint is not connected

ターゲット・バックエンドの作成


iSCSI経由で公開するDiskを作ります。
NFSとかFTPとかとの違いを明確にする為にあえてファイルシステムを作成しない(mkfsしない)でターゲットを公開してみます。

ここでは公開するディスク(バックエンド)を仮想ディスク(loop device)として作成してみます。
→参照:Linuxでのディスクイメージファイルのマウント

# mkdir -p /var/loop
# dd if=/dev/zero of=/var/loop/loop0.img bs=1048576 count=100
  (とりあえず100Mbyteのディスクイメージ)
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.367437 seconds, 285 MB/s
# losetup /dev/loop0 /var/loop/loop0.img
# ls -la /dev/loop0
brw-r----- 1 root disk 7, 0  7月  9 10:08 /dev/loop0

これで/dev/loop0として仮想デバイスができた。
(もちろん、mkfs -t ext3 /dev/loop0 とかやると/var/loop/loop0.imgファイルの中身でext3fsができあがる。)

※これをやった後にバックエンドは別に「/dev/*」じゃなくても平ファイルでもいけることが発覚。その場合はlosetup以降を省略して、tgtadmに/var/loop/loop0.imgを直接指定する。

SCSIターゲットの登録


今作った/dev/loop0を外部にiSCSIターゲットとして公開する。

まずは--helpを一覧。

# tgtadm --help
	Usage: tgtadm [OPTION]
	Linux SCSI Target Framework Administration Utility.

	  --lld [driver] --mode target --op new --tid=[id] --targetname [name]
	                        add a new target with [id] and [name]. [id] must not be zero.
	  --lld [driver] --mode target --op delete --tid=[id]
	                        delete the specific target with [id]. The target must
	                        have no activity.
	  --lld [driver] --mode target --op show
	                        show all the targets.
	  --lld [driver] --mode target --op show --tid=[id]
	                        show the specific target's parameters.
	  --lld [driver] --mode target --op update --tid=[id] --name=[param] --value=[value]
	                        change the target parameters of the specific
	                        target with [id].
	  --lld [driver] --mode target --op bind --tid=[id] --initiator-address=[src]
	                        enable the target to accept the specific initiators.
	  --lld [driver] --mode target --op unbind --tid=[id] --initiator-address=[src]
	                        disable the specific permitted initiators.
	  --lld [driver] --mode logicalunit --op new --tid=[id] --lun=[lun] --backing-store=[path]
	                        add a new logical unit with [lun] to the specific
	                        target with [id]. The logical unit is offered
	                        to the initiators. [path] must be block device files
	                        (including LVM and RAID devices) or regular files.
	  --lld [driver] --mode logicalunit --op delete --tid=[id] --lun=[lun]
	                        delete the specific logical unit with [lun] that
	                        the target with [id] has.
	  --lld [driver] --mode account --op new --user=[name] --password=[pass]
	                        add a new account with [name] and [pass].
	  --lld [driver] --mode account --op delete --user=[name]
	                        delete the specific account having [name].
	  --lld [driver] --mode account --op bind --tid=[id] --user=[name] [--outgoing]
	                        add the specific account having [name] to
	                        the specific target with [id].
	                        [user] could be [IncomingUser] or [OutgoingUser].
	                        If you use --outgoing option, the account will
	                        be added as an outgoing account.
	  --lld [driver] --mode account --op unbind --tid=[id] --user=[name]
	                        delete the specific account having [name] from specific
	                        target.
	  --help                display this help and exit

	Report bugs to <stgt-devel@lists.berlios.de>.

まずtarget(tid)を作成する。

# tgtadm --lld iscsi --op new --mode=target --tid=1 --targetname testtarget1
	→ tid(target ID)=1、target name = testtarget1としてtargetを作成する。

確認。

# tgtadm --lld iscsi --op show --mode=target
	Target 1: testtarget1
	    System information:
	        Driver: iscsi
	        Status: running
	    I_T nexus information:
	    LUN information:
	        LUN: 0
	            Type: controller
	            SCSI ID: deadbeaf1:0
	            SCSI SN: beaf10
	            Size: 0
	            Backing store: No backing store
	    Account information:
	    ACL information:

勝手にlun 0が作られるらしい。(Type : controler)なんだろ?

続けて先ほどの/dev/loop0をlun:1として登録する。

# tgtadm --lld iscsi --op new --mode=logicalunit --tid=1 --lun=1 -b /dev/loop0

確認。

# tgtadm --lld iscsi --op show --mode=target
	Target 1: testtarget1
	    System information:
	        Driver: iscsi
	        Status: running
	    I_T nexus information:
	    LUN information:
	        LUN: 0
	            Type: controller
	            SCSI ID: deadbeaf1:0
	            SCSI SN: beaf10
	            Size: 0
	            Backing store: No backing store
	        LUN: 1
	            Type: disk
	            SCSI ID: deadbeaf1:1
	            SCSI SN: beaf11
	            Size: 100M
	            Backing store: /dev/loop0
	    Account information:
	    ACL information:


このままだと接続が許されたAccountがない。
まずはアカウントの作成。

# tgtadm --lld iscsi --op new --mode account --user user1 --password 12345678

ちなみに、当然ながらこのuserIDとpasswordはUnix的なuser/passwordとは一切関係が無い。
後でイニシエータ側からtargetへ接続しに来るときに必要なのでuser/passwordは忘れないこと。

確認。

# tgtadm --lld iscsi --op show --mode=account
	Account list:
	    user1

このアカウントをtid1に関連付ける。

# tgtadm --lld iscsi --op bind --mode account --tid=1 --user=user1

確認。

# tgtadm --lld iscsi --op show --mode=target
	Target 1: testtarget1
	    System information:
	        Driver: iscsi
	        Status: running
	    I_T nexus information:
	    LUN information:
	        LUN: 0
	            Type: controller
	            SCSI ID: deadbeaf1:0
	            SCSI SN: beaf10
	            Size: 0
	            Backing store: No backing store
	        LUN: 1
	            Type: disk
	            SCSI ID: deadbeaf1:1
	            SCSI SN: beaf11
	            Size: 100M
	            Backing store: /dev/loop0
	    Account information:
	        user1
	    ACL information:

tid1にuser1が関連付けられていることがわかる。

次にこのユーザがこのtargetに対してできることを割り当てる。
今回はベタで「全ての権限」を付与している。

# tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL

確認。

# tgtadm --lld iscsi --op show --mode=target
	Target 1: testtarget1
	    System information:
	        Driver: iscsi
	        Status: running
	    I_T nexus information:
	    LUN information:
	        LUN: 0
	            Type: controller
	            SCSI ID: deadbeaf1:0
	            SCSI SN: beaf10
	            Size: 0
	            Backing store: No backing store
	        LUN: 1
	            Type: disk
	            SCSI ID: deadbeaf1:1
	            SCSI SN: beaf11
	            Size: 100M
	            Backing store: /dev/loop0
	    Account information:
	        user1
	    ACL information:
	        ALL

ACL informationに「ALL」が記述されているのがわかる。
(逆に「どんな権限があるのか」はmanにもinfoにも--helpにも記載なし…。困った…。)

で、http://ken-etsu-tech.blogspot.com/2008/03/rhcs-iscsi-dm-mp-clvm-and-gfs3iscsi.htmlによると、これらのtgtadmで行った設定はリブートすると消えるそうだ(!!マジデ!!)
なので、これらの動作をshellか何かにして起動時に実行させる必要がある。
(今回はメンドイので省略…。ちなみに/etc/init.d/tgtdの中身を見ても「起動時に/etc/xxx/xxxにtgtadmに食わせるscript置いておくと自動実行されるよ〜」なんてものは無かった…orz)

これで一応ネットワーク上にiSCSIのtargetデバイスが公開されたはず。

  イニシエータ側の設定


参照:http://ken-etsu-tech.blogspot.com/2008/03/rhcs-iscsi-dm-mp-clvm-and-gfs4iscsi.html

必要物のインストール


今回はtargetとイニシエータは別マシンで行っている。
以降の操作は基本的にイニシエータのマシン上で行うこと。
なので、イニシエータ用のパッケージが必要。

CentOS5.2の場合、インストール時に「iSCSI」を含めておくか、後から「yum install iscsi-initiator-util」でイニシエータに必要なソフトをインストールしておく。
(今回はインストール時に含めたから何もしてないけど、後からyumとかで入れた場合はmodprobeとかinsmodとかでカーネルモジュールをロードしないとダメかも。わからなければrebootでも多分OK。)

イニシエータの設定


イニシエータ名として重複しない名前を設定する必要がある。

# cp /etc/iscsi/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi.org
# vi /etc/iscsi/initiatorname.iscsi
InitiatorName=iqn.1994-05.com.redhat:4be3de93ab84

そのままでも何かのUIDみたいなものが設定されていてユニークっぽいが…。

今回はとりあえずhost名に変えておいてみる。(いいのか?)

アクセスするユーザ名/パスワードを設定する。

# cp /etc/iscsi/iscsid.conf /etc/iscsi/iscsid.conf.org
# vi /etc/iscsi/iscsid.conf
node.session.auth.authmethod = CHAP を追加
node.session.auth.username = user1 を追加
node.session.auth.password = 12345678 を追加

usernameとpasswordは先にtarget側で設定したものに合わせること(当然)。

接続設定はiscsiadmコマンドを使って行う。

# iscsiadm --help
	iscsiadm -m discovery [ -hV ] [ -d debug_level ] [-P printlevel] [ -t type -p ip:port -I ifaceN ... [ -l ] ] | [ -p ip:port ] [ -o operation ] [ -n name ] [ -v value ]
	iscsiadm -m node [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -L all,manual,automatic ] [ -U all,manual,automatic ] [ -S ] [ [ -T targetname -p ip:port -I ifaceN ] [ -l | -u | -R | -s] ] [ [ -o  operation  ] [ -n name ] [ -v value ] ]
	iscsiadm -m session [ -hV ] [ -d debug_level ] [ -P  printlevel] [ -r sessionid | sysfsdir [ -R | -u | -s ] [ -o operation ] [ -n name ] [ -v value ] ]
	iscsiadm -m iface [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -I ifacename ] [ [ -o  operation  ] [ -n name ] [ -v value ] ]
	iscsiadm -m fw [ -l ]
	iscsiadm -k priority

(これもmanも--helpもinfoも情報少ない…。)

ディスカバリー


まずはtargetデバイスを発見してやる必要がある。

# iscsiadm --mode=discovery --type=sendtargets -p 192.168.0.1
192.168.0.1:3260,1 testtarget1
↑ 先ほど設定したものが発見できること

この時点で/var/lib/iscsi以下にゴチャゴチャとファイルが作成される。
それらのファイルはiscsiadmコマンドで操作できるので基本的にはいじらない。

ファイルに書かれているって事は、イニシエータが発見したtarget情報は揮発しない。(rebootしても残る)
……target設定はrebootしたらきれいさっぱり忘れるくせに…(--#)

当然、target側の構成を変えたりtargetやlunを追加したときはディスカバーをやり直す必要がある。
(今回は試していないけど。)

ログイン


iSCSIはSCSIと違ってネットワーク上のものなので、旧SCSIで言えばケーブルのコネクタの所に鍵がかかっている。
ログイン操作をすることによってそのtargetに対してイニシエータはアクセスが可能になる。

(先ほどのターゲットは192.168.0.1だったとする。)
# iscsiadm --mode=node --login
Logging in to [iface: default, target: testtarget1, portal: 192.168.0.1,3260]
Login to [iface: default, target: testtarget1, portal: 192.168.0.1,3260]: successful
↑ ログインできたっぽい

成功すると/dev/sd*というデバイスができる。(*はa,b,c,d…)

# ls -l /dev/sd*
brw-r----- 1 root disk 8, 0  7?  9 13:33 /dev/sda

iSCSIのセッションが張られていることを確認する。

# iscsiadm -m session
tcp: [1] 192.168.20.52:3260,1 testtarget1

/var/lib/iscsi/以下にtargetの情報が登録されている。

# tree -aps /var/lib/iscsi/*
/var/lib/iscsi/ifaces
/var/lib/iscsi/isns
/var/lib/iscsi/nodes
`-- [drw-------      4096]  testtarget1
    `-- [drw-------      4096]  192.168.0.1,3260,1
        `-- [-rw-------      1611]  default
/var/lib/iscsi/send_targets
`-- [drw-------      4096]  192.168.0.1,3260
    |-- [-rw-------       420]  st_config
    `-- [lrwxrwxrwx        53]  testtarget1,192.168.0.1,3260,1,default -> /var/lib/iscsi/nodes/testtarget1/192.168.0.1,3260,1
/var/lib/iscsi/slp
/var/lib/iscsi/static

4 directories, 2 files

# cat /var/lib/iscsi/nodes/testtarget1/192.168.0.1,3260,1/default
node.name = testtarget1
node.tpgt = 1
node.startup = automatic
iface.hwaddress = default
iface.iscsi_ifacename = default
iface.net_ifacename = default
iface.transport_name = tcp
node.discovery_address = 192.168.0.1
node.discovery_port = 3260
node.discovery_type = send_targets
node.session.initial_cmdsn = 0
node.session.initial_login_retry_max = 4
node.session.cmds_max = 128
node.session.queue_depth = 32
node.session.auth.authmethod = CHAP
node.session.auth.username = user1
node.session.auth.password = 12345678
node.session.timeo.replacement_timeout = 120
node.session.err_timeo.abort_timeout = 15
node.session.err_timeo.lu_reset_timeout = 30
node.session.err_timeo.host_reset_timeout = 60
node.session.iscsi.FastAbort = Yes
node.session.iscsi.InitialR2T = No
node.session.iscsi.ImmediateData = Yes
node.session.iscsi.FirstBurstLength = 262144
node.session.iscsi.MaxBurstLength = 16776192
node.session.iscsi.DefaultTime2Retain = 0
node.session.iscsi.DefaultTime2Wait = 2
node.session.iscsi.MaxConnections = 1
node.session.iscsi.MaxOutstandingR2T = 1
node.session.iscsi.ERL = 0
node.conn[0].address = 192.168.0.1
node.conn[0].port = 3260
node.conn[0].startup = manual
node.conn[0].tcp.window_size = 524288
node.conn[0].tcp.type_of_service = 0
node.conn[0].timeo.logout_timeout = 15
node.conn[0].timeo.login_timeout = 15
node.conn[0].timeo.auth_timeout = 45
node.conn[0].timeo.noop_out_interval = 5
node.conn[0].timeo.noop_out_timeout = 5
node.conn[0].iscsi.MaxRecvDataSegmentLength = 131072
node.conn[0].iscsi.HeaderDigest = None,CRC32C
node.conn[0].iscsi.IFMarker = No
node.conn[0].iscsi.OFMarker = No

iSCSIデバイスの使用


後は普通のdiskと同じように使える。
使用例としてイニシエータ側からtarget(内のlun)にmkfsしてファイルシステムを作ってマウントしてみる。

# mkfs -V -t ext3 /dev/sda
mkfs (util-linux 2.13-pre7)
mkfs.ext3 /dev/sda
mke2fs 1.39 (29-May-2006)
/dev/sda is entire device, not just one partition!
Proceed anyway? (y,n) y
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
25688 inodes, 102400 blocks
5120 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
13 block groups
8192 blocks per group, 8192 fragments per group
1976 inodes per group
Superblock backups stored on blocks:
 8193, 24577, 40961, 57345, 73729

Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 23 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

# mount /dev/sda /mnt
# mount /mnt
mount: /dev/sda は マウント済か /mnt が使用中です
mount: mtab によると、/dev/sda は /mnt にマウント済です

OKっぽい。
この状態で/mnt以下にファイルやディレクトリを作成すると、それはネットワーク経由でtargetマシンに保存される。

ちなみにtarget側から接続状況を確認するとこうなっている。

(これは先のtargetマシン上で実行する。)
# tgtadm --lld iscsi --mode target --op show
Target 1: testtarget1
    System information:
        Driver: iscsi
        Status: running
    I_T nexus information:
        I_T nexus: 1
            Initiator: hogehoge.initiator01
            Connection: 0
                IP Address: 192.168.0.2  ← このへん
    LUN information:
        LUN: 0
            Type: controller
            SCSI ID: deadbeaf1:0
            SCSI SN: beaf10
            Size: 0
            Backing store: No backing store
        LUN: 1
            Type: disk
            SCSI ID: deadbeaf1:1
            SCSI SN: beaf11
            Size: 100M
            Backing store: /dev/loop0
    Account information:
        user1
    ACL information:
        ALL

  後始末


誰かがiSCSI targetを使用中だとtargetのtgtdは普通にshutdownできないので、イニシエータは後始末をしてターゲットを手放す必要がある。
(いきなりイニシエータ側をrebootしたときの弊害については下記参照。)

まずイニシエータ側でumountする。

# umount /mnt
# iscsiadm -m session --op show
tcp: [1] 192.168.0.1:3260,1 testtarget1 ← まだiSCSIとしてのSessionは張られたまま
# iscsiadm -m session -r 1 --logout ← 先の「tcp: [1]」の「1」がSession ID(らしい)
Logging out of session [sid: 1, target: testtarget1, portal: 192.168.0.1,3260]
Logout of [sid: 1, target: testtarget1, portal: 192.168.0.1,3260]: successful

確認。

# iscsiadm -m session --op show
iscsiadm: No active sessions. ← Sessionがなくなった

  イニシエータ側の再起動に関する注意


どうも、そのままではイニシエータ側でOSを再起動した場合、OS再起動時にiSCSI SessionをLogoutしないようになっている為、再起動後に同じtargetに対してiSCSI Sessionが張れなくなるという問題があるらしい。(/etc/init.d/iscsiにわざわざそのようなロジックが作りこんである。バグというわけではなさそうだ。)

OSのブートディスクでiSCSIによるRAIDなどが使われる可能性もあるので、init.dが完了した後にカーネルから強制KILLされるのを待つようにしてあるらしい。まあ、正しいか…。
そのかわり、iSCSIのターゲットを使った場合、rebootかshutdownする前にiscsiadm logoutする必要がある。メンドイ…気もする。

回避する為にはイニシエータ側の/etc/init.d/iscsiとiscsidを書き換える必要があるらしい。
中に「if [ "$RUNLEVEL" = "6"云々」と書いてあるif節があるので、そこを全てコメントアウトする。
ただし、これをしてしまうとブートデバイスにiSCSIを使用していると問題が発生すると思われる。トレードオフ。(未検証。)

# でも、iscsiadmで「autostart」とか指定すると/etc/init.d/iscsiの中で勝手にloginしてくれちゃうんだよなぁ…それって設計思想矛盾してない?

  考察


負荷試験とか障害試験などはナシで「とりあえずお試し」なのでなんとも言えませんが、仮想環境(XenとかVMWare)でクラスタ環境を作る場合にはいいかもしれないですね。
(参考にさせていただいたサイトでも大体そのような使い方しているし。)

Xenの場合はDom0の平ファイルとかデバイスファイルとかでは共有ディスク作れないし、VMWareの場合はできるっぽいんだけどマルチパスとかは当然できないわけで、クラスタ乗っけようとするとわけわかめになって挫折した事ありなので、ブロックデバイスレベルで論理結線可能なiSCSIは試験環境構築では非常に魅力的ではないでしょうか。

  参照させていただいたサイト


http://docs.sun.com/app/docs/doc/819-0386/fmvcd?a=view
LinuxじゃないけどiSCSI全体がちゃんと説明されている
http://www.atmarkit.co.jp/flinux/rensai/xen202/xen202a.html
open-iscsiってCentOSのiSCSIと同じものなのかな?CLVMの使い方も書いてある。
http://ken-etsu-tech.blogspot.com/2008/02/red-hat-cluster-centos-51rhcs1.html
RHCS環境を作っています。スゴイです。内容的にはほとんど丸パクリさせていただきました。m(_ _)m(ちゃんと手前側でも実機検証してますよ^^;)

 履歴

2008/07/09 -- 初版
2010/04/06 -- 追試。現段階でも記述内容で問題なくお試しできる事を確認済み。CentOS5.4。

技術的雑談へ戻る

 突っ込み


name   comment  
URL (入力するとす ぱ むとみなします!)


技術的雑談へ戻る

最終更新日時:最終更新時間:2010年06月03日 05時25分23秒
トップページに戻る