- 追加された行はこのように表示されます。
- 削除された行は
このように表示されます。
!!!技術的雑談-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でのディスクイメージファイルのマウント|技術的雑談-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。
[[技術的雑談]]へ戻る
!!突っ込み
{{comment}}
[[技術的雑談]]へ戻る