PXEでiSCSI boot
iSCSI SAN bootはHBAが高い、使用できるハードウェアが限られる等あるので
PXE経由でiSCSI BOOT出来るように頑張ってみた。
InitiatorとしてはLinux-iSCSIはもうメンテされてないし、色々面倒なので
Open-iSCSIを使用。なお、CentOS5にはiscsi-initiator-utilsとして入っている。
iSCSI Target設定
iSCSI TargetはiSCSI Enterprise Target等を使って適当にでっち上げる。
モジュールをビルド、インストールはCentOS5等だと特に問題なく可能。
最終的には専用のストレージ使うにしろテストにはこれで十分。
設定は以下の様に /etc/ietd.conf に追記。
最低限の設定はIQNとブロックデバイスの割り当てを記述するだけ。
ブロックデバイスの代わりにファイルも使えたりもする。
Target iqn.sample.target0 Lun 0 Path=/dev/sdaXX Target iqn.sample.target1 Lun 0 Path=/dev/sdaYY
で以下の通り起動、至ってシンプル。
# /etc/init.d/iscsi-target start
これでTargetは準備完了。
確認は以下の様な感じで可能。
loginした時点で/dev/sdXのブロックデバイスとして見えるはず。
# iscsid # iscsiadm -m discovery -t sendtargets -p <target ip> # iscsiadm -m node -T <target iqn> -p <target ip> --login
この領域にOSを入れる必要があるが、CentOS5はiSCSI領域に直接
標準のインストーラからインストール可能。面倒な場合は
他のホストでmountしてrestoreしたりそのままddするのも良い。
iSCSI Initiator設定
こっちがメイン。
方針としてパッケージの再コンパイル等は行わずにディストリビューション(この場合CentOS)で
配布されているバイナリだけを使用する。(sharedバイナリのまま使用)
システムは作ったら終わりというわけでは無いので、メンテナンスに掛かるコストは
少なければ少ないほど良いし。
ということで起動用initrdの準備。昔はext2だったが最近はcpioで固めた物がgzipされている。
全部最初から作るよりは、既に入っているinitrdを展開して追加、変更した後
再packするのが楽。要はmkinitrdのやっていることを代わりにやるだけ。
また、手の込んだことをやる場合はbusybox等を使っている人も居るようだが、
最近はそこまで領域の節約をする必要が無いのと、上記理由でupdateに追従
し易くするため、必要なライブラリ、バイナリを直接コピーして使うことにした。
必要なライブラリは使いたいバイナリをlddして特定。(LKMはlsmod等)
巨大なlibc.soが間違いなくinitrdに入ることになるが気にしない。
最低限必要なバイナリは以下(ライブラリは適宜必要な物を追加)。
debugしたい場合はstraceやらbashなども入れておくと便利。
ip インターフェイス操作用 dhclient IPアドレス取得用 実際にはdhclient-scriptで設定 iscsid NETLINKソケット経由でiSCSI制御用LKMと通信する。(嵌り所多いので以下にmemo) 以下のディレクトリが必要 /var/lock/iscsi /var/run /var/lib/iscsi/{ifaces,isns,nodes,send_targets,slp,static} nss関連のライブラリも必要かも(間接的に呼ばれてる) /etc/passwdが必要(rootエントリだけで良い) /etc/iscsi/{iscsid.conf,initiatorname.iscsi} も必要 iscsiadm iscsidとの通信用 LKM(Ether用) e1000.ko,e100.ko 等々使ってるEther次第(ここではe1000を使用) LKM(iSCSI用) 依存関係によってinsmodに転けるのでロードする順番に注意 sd_mod.ko scsi_mod.ko scsi_transport_iscsi.ko libiscsi.ko iscsi_tcp.ko LKM(FS用) とりあえずext3で使いたい場合は以下 jbd.ko ext3.ko
initrd内部のinitは以下のような感じ。モジュールをロードし始める所より下を
以下のスクリプトに置き換える。(echo "Loading xxxxx module"のあたり)
直接IPを記述するようにしているが、dhcpのオプションで色々なパラメータは渡せるので
適当に使わなそうな物を使ってIQNやTargetのIPを渡すと、複数のホストで共通のinitrdが使用できる。
##Network初期化 insmod /lib/e1000.ko ip -o link set dev eth0 up dhclient -lf /var/run/dhcpc.lease -pf /var/run/dhcpc.pid ##iSCSI+FS初期化 insmod /lib/jbd.ko insmod /lib/ext3.ko insmod /lib/scsi_mod.ko insmod /lib/sd_mod.ko insmod /lib/scsi_transport_iscsi.ko insmod /lib/libiscsi.ko insmod /lib/iscsi_tcp.ko iscsid iscsiadm -m discovery -t sendtargets -p <target ip> iscsiadm -m node -T <target iqn> -p <target ip> --login ##Rootマウント stabilized --hash --interval 250 /proc/scsi/scsi mkblkdevs mkrootdev -t ext3 -o defaults,ro /dev/sda1 mount /sysroot setuproot switchroot
/dev/sdaに見えてる通り以降はローカルディスクから起動したのと何ら変わりなく使用可能。
ブロックサイズの性質上大きめのパケットが流れるので、Jumbo Frameが
使える場合は有効にしておくとppsが格段に下がって良い感じになる。
DHCPとPXEの設定については色々な所で見かけるので割愛。
なおNFSROOTでのPXE BOOTも同様の方法で可能。iSCSIの代わりにNFSモジュールを
ロードしてmount.nfsでそのままmountするだけ。
カーネル組み込みのNFSROOTはあまりメンテされていないようでよく問題が
起きてるし、updateのコスト考えるとこっちの方が楽な感じ。