Posted on Sun Jan 09 15:56:18 +0900 2011 by nabeken
RAID0で構築していたXen 3.0 w/Debian GNU Linux (lenny)をXen 4.0w/Debian GNU/Linux (squeeze) + ZFS上のiSCSI boot/rootで再構築しました。iSCSI boot/rootでハマったポイントを記します。
dom0は精々10GBあれば十分なため、RAID1/5を用意するのは非常に無駄が大きいです。 そこで、ZFS上のディスクをiSCSI経由で使うことを考えました。
ネットワークブート(diskless boot)にあたり、DHCPは使用せず、静的設定でのブートを目指します。 Debianは一旦仮想環境で通常インストールし、ddなどを使いブートローダー含めてiSCSIターゲットへコピーします。
起動の流れは以下のようになります。
BIOS -> USBメモリ -> gPXE -> sanboot over iscsi on FreeBSD + istgtg w/ZFS -> grub2 -> Xen 4.0 w/Debian squeeze
各段階ごとに説明します。
gPXE はオープンソースのPXEおよびその拡張実装です。PXEブートもちろん、iSCSI, http, AoEやさらにたくさんの方法で起動することが可能です。 最近はgPXEとの開発方針(?)の違いから iPXE というフォークのほうが開発は活発のようです。ただし、iPXEは私が試した時点(2010/12/28)時点のGit版はビルドができませんでした。
まずはROMのビルドの下準備。
今回はgPXE_のGit版からUSBメモリ向けにビルドします。まずはGitリポジトリをcloneします。
$ git clone git://git.etherboot.org/scm/gpxe.git
まずgPXEのTCP/IPスタックを一部修正します。 最初に試した際、なぜかFreeBSDホスト宛てのiSCSIやhttp通信が急にRSTされてしまう現象に見舞われました。 パケットキャプチャするとgPXE側で RFC1323 で定義されているTCPオプション(TCP timestamps)を正しく扱えていませんでした(echo replyが常に0)。そのためFreeBSD側のTCP/IPスタックが通信を拒否したと考えています。 以下のパッチを当てるとgPXE側でTCP timestampsを使わないようすることができます。このパッチを当てることでFreeBSD側のiSCSI targetに接続することができました。
次にUSBメモリからgPXEが起動したあと自動でiSCSI bootするようなスクリプトを作成します。 スクリプトの詳細はgPXEの Wiki を参照してください。
#!gpxe ifopen set net0/ip X.X.X.X set net0/netmask 255.255.255.0 sanboot iscsi:Y.Y.Y.Y::::iqn.2010-12.org.example:iscsi-root
まず、1つ目のNICのIPアドレスをX.X.X.X、サブネットマスク255.255.255.0に設定します。次に sanbootコマンドでiscsiブートするtargetを指定します。 以後は内蔵ハードディスクと同様にgrubが起動します。
スクリプトが用意できればROMを生成します。
$ cd src $ make EMBEDDED_IMAGE=path/to/your/scripts.gpxe bin/gpxe.usb
スクリプトを埋め込んだUSBメモリ向けのROMが生成されました。最後に焼きます。
# dd if=bin/gpxe.usb of=/dev/your-usb-memory
これで起動時に手動設定した内容で自動起動する特製のUSBメモリができました。
grubからOSへ制御が移るため、最後にLinux側でiSCSIをルートファイルシステムとしてmountする必要があります。 そのため通常のネットワーク設定の前にネットワーク設定投入する必要があります。
DebianではiSCSIのターゲット情報をブートローダ経由で渡すことができます (/usr/share/doc/open-iscsi/README.Debian参照)。 必ず/etc/iscsi/iscsi.initramfsをtouchしておきます。
ネットワーク設定はカーネル側のNFSROOTの設定を流用して設定します。具体的には Mounting the root filesystem via NFS (nfsroot) のipパラメータを設定します。
両方の設定を投入したgrub.cfgの設定例を以下に示します。
### BEGIN /etc/grub.d/20_linux_xen ### menuentry 'Debian GNU/Linux, with Linux 2.6.32-5-xen-amd64 and XEN 4.0-amd64' --class debian --class gnu-linux --class gnu --class os --class xen { insmod part_msdos insmod ext2 set root='(/dev/sdc,msdos1)' search --no-floppy --fs-uuid --set 31f34c24-c568-47f9-ae20-32df8b7dfc3c echo 'Loading Linux 2.6.32-5-xen-amd64 ...' multiboot /boot/xen-4.0-amd64.gz placeholder module /boot/vmlinuz-2.6.32-5-xen-amd64 placeholder root=UUID=31f34c24-c568-47f9-ae20-32df8b7dfc3c ro quiet ISCSI_INITIATOR=iqn.2010-12.org.etherboot:example ISCSI_TARGET_NAME=iqn.2010-12.org.example:iscsi-root ISCSI_TARGET_IP=Y.Y.Y.Y ISCSI_TARGET_PORT=3260 ip=X.X.X.X:Y.Y.Y.Y::255.255.255.0:xen.example.org:eth1:static echo 'Loading initial ramdisk ...' module /boot/initrd.img-2.6.32-5-xen-amd64 }
grub2の設定は自動生成のため/boot/grub/grub.cfgを編集するのではなく、/etc/grub.d/以下のファイルを編集します。差分は以下のような感じです。
--- 20_linux_xen.orig 2011-01-06 23:31:56.956841123 +0900 +++ 20_linux_xen 2011-01-06 23:28:59.375271276 +0900 @@ -35,6 +35,12 @@ CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr '[A-Z]' '[a-z]' | cut -d' ' -f1) ${CLASS}" fi +ISCSI_INITIATOR="iqn.2010-12.org.etherboot:example" +ISCSI_TARGET_NAME="iqn.2010-12.org.example:iscsi-root" +ISCSI_TARGET_IP="Y.Y.Y.Y" +ISCSI_TARGET_PORT=3260 +IPADDR="10.0.40.12:10.0.40.10::255.255.255.0:dom0.example.org:eth1:static" + # loop-AES arranges things so that /dev/loop/X can be our root device, but # the initrds that Linux uses don't like that. case ${GRUB_DEVICE} in @@ -131,7 +137,13 @@ fi linux_entry "${OS}" "${version}" "${xen_version}" false \ - "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" "${GRUB_CMDLINE_XEN} ${GRUB_CMDLINE_XEN_DEFAULT}" + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} \ + ${GRUB_CMDLINE_XEN} ${GRUB_CMDLINE_XEN_DEFAULT} \ + ISCSI_INITIATOR=${ISCSI_INITIATOR} \ + ISCSI_TARGET_NAME=${ISCSI_TARGET_NAME} \ + ISCSI_TARGET_IP=${ISCSI_TARGET_IP} \ + ISCSI_TARGET_PORT=${ISCSI_TARGET_PORT} \ + ip=${IPADDR}" if [ "x${GRUB_DISABLE_LINUX_RECOVERY}" != "xtrue" ]; then linux_entry "${OS}" "${version}" "${xen_version}" true \ "single ${GRUB_CMDLINE_LINUX}" "${GRUB_CMDLINE_XEN}"
また、Lennyとは異なりXenカーネルがデフォルトで選択されませんので自身でdefaultエントリーを選択する必要があります (/etc/default/grubのGRUB_DEFAULT変数)。
修正を施したらかならず update-grub コマンドを実行して/boot/grub/grub.cfgを更新してください。
Open-iSCSI README - 8.2 iSCSI settings for iSCSI root ではiSCSIディスクをrootにする際、timeoutを長くする設定例が載っています。必要に応じて設定します。
iSCSI rootな環境で何も設定せずにshutdown(poweroff)コマンドやreboot(shutdown -r)コマンドを実行するときちんとシャットダウン/再起動ができない問題があります。
シャットダウンについては /etc/default/halt で NETDOWN=no にすることで正しくシャットダウンすることができます。
(NOTE: NETDOWN=noにするとshutdownコマンドの引数として-iが渡されなくなります。-iは停止直前にNICを切断)
残念ながらrebootコマンドは正しく動作しません。現在調査中です。