~nabeken/diary/

Gentoo Linux(6年くらい)とFreeBSD(1年くらい)とOpenBSD(新参者)を使う日々。


IHANet BGP peering overview

Xen 4.0 dom0をiSCSI boot via gPXE over FreeBSD + iSCSI on ZFSで構築する

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でハマったポイントを記します。

iSCSI boot/root over ZFSにする意味

  • ストレージサーバとしてFreeBSD 8.x + ZFS (raidz)環境がすでにある
  • domUにはRAID0で高速なディスクI/Oを安価に用意したい
  • しかし、dom0のディスクは冗長構成を取り、ディスク障害の影響を極力なくしたい

dom0は精々10GBあれば十分なため、RAID1/5を用意するのは非常に無駄が大きいです。 そこで、ZFS上のディスクをiSCSI経由で使うことを考えました。

dom0環境

M/B
GIGABYTE GA-M55PLUS-S3G
CPU
Athlon64 X2 4000+
Memory
DDR2 800 2GB x2
HDD
  • domUのデータ領域としてRAID0(バックアップは別途4時間毎に取得している)
  • domUで特に冗長性が必要な場合は別途domU内でiSCSIディスクをmount
NIC
  • eth0:e1000e
  • eth1:forcedeth
iSCSI initiator (linux)
open-iscsi-
iSCSI target (FreeBSD)
istgt-20100707

ネットワークブート(diskless boot)にあたり、DHCPは使用せず、静的設定でのブートを目指します。 Debianは一旦仮想環境で通常インストールし、ddなどを使いブートローダー含めてiSCSIターゲットへコピーします。

構成

起動の流れは以下のようになります。

BIOS -> USBメモリ -> gPXE -> sanboot over iscsi on FreeBSD + istgtg w/ZFS -> grub2 -> Xen 4.0 w/Debian squeeze

各段階ごとに説明します。

BIOSからUSBメモリのgPXEを起動する

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メモリができました。

grub2からiSCSI rootなDebianを起動する

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な状態からシャットダウンする

iSCSI rootな環境で何も設定せずにshutdown(poweroff)コマンドやreboot(shutdown -r)コマンドを実行するときちんとシャットダウン/再起動ができない問題があります。

シャットダウンについては /etc/default/haltNETDOWN=no にすることで正しくシャットダウンすることができます。

(NOTE: NETDOWN=noにするとshutdownコマンドの引数として-iが渡されなくなります。-iは停止直前にNICを切断)

残念ながらrebootコマンドは正しく動作しません。現在調査中です。

更新履歴

  • 初稿 (Sun, 9 Jan 2011 15:56:18 +0900)