VIVER CORE Server 0.0.1 - Network Boot Toolkit

ディスクレスネットワーク基盤システム「VIVER」の中から、ネットワークブート機能だけを取り出して強化した、VIVER CORE Serverの最初のバージョンをリリースします。
VIVER COREは、一言で言えば、「ネットワークブートに対応したinitramfs」です。HTTP、FTPまたはTFTPでルートファイルシステムをダウンロードし、RAM上に展開して起動します。


VIVER CORE Server 0.0.1
viver-core-server-0.0.1.tar.gz


※2007/10/03追記: バージョン0.0.2をリリースしました。> pxe-pdhcp + VIVER CORE Server 0.0.2
VIVER CORE Server 0.0.2
viver-core-server-0.0.2.tar.gz
viver-core-server.0.0.2.src.tar.gz
debootstrapをDebian以外のディストリビューションで使う + VIVER CORE Server


VIVER COREの概要

ご存じのとおり、Linuxカーネルにはブートローダから小さなルートファイルシステム(initramfs)を渡すことができます。このinitramfsは、SCSIドライバやRAIDのカーネルモジュールなどを入れておいて、カーネルを再構築することなくそれらのストレージからシステムを起動するために使われます。VIVER COREは、このinitramfsの中でネットワークインターフェースを起動し、リモートホストからルートファイルシステムをダウンロードしてきて、それをルートファイルシステムとしてシステムを起動します。


ネットワークを起動する際にはハードウェアの自動認識を行うので、ロードするカーネルモジュールを詳しく設定しなくても良きに計らいます。ハードウェアの自動認識は先日発見した方法で行っており、とても確実です。
一方でmkinitrdに良く似た「mkviverrd」コマンドを使って、initramfs内に入れるカーネルモジュールを選別することもできます。選別することでinitramfsのサイズを減らすことができますが、デフォルトの設定でも2.5MB程度で済みます。それでもNICのドライバはだいたい含んでいるので、多くの環境でそのまま動作するはずです。


ネットワークを起動する方法は、ブートパラメータを使って細かく指定できます。細かくと言うよりも、そのままコマンドを実行するようにブートパラメータを指定できます。network=ifconfig eth0 192.168.0.2; route add default 192.168.0.1; nameserver 192.168.0.1; ... といった具合です。
コマンドは、ifconfig、route、ip、dhcp、nameserver、search(検索ドメイン)、domain(ドメイン名)、vconfig(VLAN)をサポートしています。



VIVER COREのおもしろさ

まだ最初のバージョンですので、使い勝手よりも、VIVER COREの何がおもしろいのかを紹介したいと思います。

VIVER COREの何より重要なポイントは、普通にtar.gzやtar.bz2などで固めたルートファイルシステムを、普通にHTTPサーバーに置いておくだけで、何事もなくネットワークブートができるという点です。ルートファイルシステムは、普通にLinuxディストリビューションをインストールしたもので構いません。すべてメモリ(tmpfs)上に展開するので、ルートファイルシステムはHDDから起動する場合とまったく同じように作ればOKです。
メモリ容量を圧迫するのが気になるところですが、必要最低限のパッケージだけをインストールするようにしたり、/usrはNFSでマウントしたりと、いろいろと方法はあるはず!(単純にメモリを大量に積む!という手も…)


私の環境で試したところ、debootstrapで作成したDebian etchを.tar.gzで固めただけでネットワークブートできました。



ルートファイルシステムをダウンロードするプロトコルにはHTTPをサポートしています。なんと言ってもHTTPです。いろいろできます。

  • ルータを越えてネットワークブート
  • プロキシをはさんでルートファイルシステムをキャッシュ
  • インターネット越しにブート
  • リバースプロキシで負荷分散

ルートファイルシステムのアーカイブには、今のところtar/cpio+gzip/bzip2/lzmaをサポートしています。環境構築の時には圧縮速度の速いgzipを使って時間の節約を、運用時には圧縮率の高いlzmaを使ってネットワーク負荷を軽減できます。
今後はNBD(またはiSCSI)やNFS、あるいはV-FIELDなどをサポートすることを考えています。NBDならHDDをそのままエクスポートできますし、NFSならルートファイルシステムを圧縮する手間を省いてテストを繰り返すことができます。



カーネルは、今使っているカーネルを利用できます。特殊なパッチは必要ありませんし、再構築する必要もありません。これにはmkviverrdコマンドが重要な役割を果たしています。百聞は一見にしかずと言うことで、一度試していただくのが一番良いのですが、usageを見るだけでも何ができるか分かると思います。(ところどころおかしな英語がありそうで怖い ^_^;)

usage: mkviverrd [options] <viver-core-image> <skeleton-image> <kernel-version>
options:
     [-v]                        # Verbose mode.
     [--add=<module>]            # Include module and its depending modules.
                                 #   +module   load the module regardless of hardware detection.
                                 #   -module   do not stop if we cannot find the module.
                                 #   +-module  both + and -.
     [--preload=<module>]        # Alias of --add=+module
     [--builtin=<module>]        # Act as if module is built into the kernel being  used.
     [--allow-missing]           # Do not stop if we cannot find some of the required modules.
     [--include-directory]       # Include modules in the directory without depends.
     [--no-net]                  # Disable automatic including of +-af_packet +-ipv6
     [--no-net-drivers]          # Disable automatic including of drivers/net
     [--vlan]                    # Alias of --add="+-8021q"
     [--scsi]                    # Alias of --add="+-sd_mod +-sr_mod"
     [--ata]                     # Alias of --add="+-libata +-sd_mod +-sr_mod"
     [--ide]                     # Alias of --add="+-ide-disk +-ide-cd"
     [--usb]                     # Alias of --add="+-usb-storage +-sd_mod +-sr_mod"
     [--ieee1394]                # Alias of --add="+-sbp2 +-sd_mod +-sr_mod"
     [--pcmcia]                  # Alias of --add-"+-yenta_socket"
     [--scsi-drivers]            # Alias of --include-directory="drivers/scsi"
     [--ata-drivers]             # Alias of --include-directory="drivers/ata"
     [--ide-drivers]             # Alias of --include-directory="drivers/ide"
     [--usb-drivers]             # Alias of --include-directory="drivers/usb"
     [--ieee1394-drivers]        # Alias of --include-directory="drivers/ieee1394"
     [--pcmcia-drivers]          # Alias of --include-directory="drivers/pcmcia"
     [--disable-fake-nfsroot]    # Disable mtab hack. (not implemented yet)
     [--kernel-dir=<direcotry>]  # Use the directory instead of /lib/modules/<kernel-version>
     [--tmpdir=<directory>]      # Use the directory instead of /tmp
     [--test]                    # Do finding modules only. Don't make viver-core-image.

     # --x--drivers options (e.g. --usb-drivers) imply --x options (e.g. --usb).

     example: mkviverrd tftpboot/viver-core.img skel/viver-core-skel.tar.gz 2.6.19.7-vs2.2.0.3-vcore12

必須オプションのはVIVER CORE Serverパッケージの中に入っているので、実質的には出力先ファイル名とカーネルのバージョンさえ指定すれば、標準的なVIVER COREイメージ(initramfs)ができあがります。デフォルトの設定は、/lib/modules/`uname -r`/kernel/drivers/net以下のモジュール全部と、af_packet、ipv6をinitramfsの中に入れるようになっています。とりあえずは使わなそうなモジュールも、ハードウェア自動認識を当てにしてごっそり入れておくことができます。
おなじみのmkinitrdをベースにしており、modules.depを調べてカーネルモジュールの依存関係をたどってくれます。



また、VIVER CORE ServerパッケージはTFTPサーバーやDHCPサーバー、HTTPサーバーがセットになっており、簡単にネットワークブート環境をセットアップできるようになっています。PXEの一件から、新たにDHCPサーバーを立てずにPXEを使えるようにするプログラムも作っているのですが、まだできていないので、とりあえずはDHCPサーバーが入っています。


ブートパラメータに"postboot="を指定すると、ルートファイルシステムをダウンロードした後で、で指定したファイルをダウンロードしてきて実行します。ネットワークブートしたシステムに自動でパッチを当てるのに使えます。



VIVER COREのビルド

VIVER CORE Serverのソースコードは↓ここにあります。
viver-core-0.0.1.src.tar.gz


initramfsはNASなどに似た一種のembedded的な環境であることを考えれば自然なわけですが、VIVER COREのビルドはクロスコンパイルで行います。まずbuildrootを使ってuClibcのクロスコンパイル環境を構築し、busyboxrubyをコンパイルするようになっています。glibcではなくuClibcな共有ライブラリなので、総ファイルサイズはとても小さくなります。busyboxrubyに諸々のライブラリを合わせても、1.6MB程度(圧縮すると約750KB)です。


VIVER CORE自体は特定のアーキテクチャに依存しているわけではないので、ARMやPowerPCに移植するとおもしろいかも? GLAN TANKがネットワークブートしてシンクライアント化!とかとか。PXEは使えないので、Etherbootで。


ブートパラメータHack

ネットワークの起動に関して、busyboxのおかげでVLANまで対応しているのですが、ブートパラメータでコマンドを指定するため、ブートパラメータが非常に長くなります。
しかし、Linuxのinit/main.cとinclude/asm-i386/setup.hのCOMMAND_LINE_SIZEを見ると、i386ではブートパラメータの上限が256文字になっています。ルートファイルシステムのURLなども全部ブートパラメータで指定するので、結構簡単に越えてしまいます。

そこで、よく使いそうな文字列には短縮名を割り当てることで、ブートパラメータを圧縮できるようになっています。


network="ifconfig eth0 192.168.0.2; route add default gw 192.168.0.1; nameserver 192.168.0.1" rooturl="http://192.168.0.2/image.tar.gz" postboot="tftp://192.168.0.2/postboot.sh"

は、

\N\ieth0\\\.2;\\\g\\\.1;\\\n\.1 \R\h\.2/image\p \Bt\f\.2/postboot.sh

になります。177文字が68文字に!

最初はブートパラメータをDeflateで圧縮してBase64にしようかとも考えていたのですが、逆に膨らんでしました。ネットワークの設定以外はDHCPで渡すことも考えましたが、そうすると固定IPが使えなくなる上に、DHCPサーバーの設定を変更しなければならなくなってしまいます。
うーむ。もっとスマートな方法があれば…。