VIVER CORE計画 案1
分散ファイルシステムの件が進みそうにないので、できそうなところから埋めていくのが良いと思った。そもそも分散ファイルシステムの件もVIVER COREも、最終的な目標は同じわけで。分散メタネームサーバーはRinda/RingServerで実装できそうな。(既に実装されていそうな)
と言うわけで、VIVER COREの計画を進める。WikiFormeはちょっと置いておく。(うーむ。またしても…)
VIVER COREでやること
- PCIの自動検出
- カーネルモジュールのロード
- ネットワークの起動
- ブートパラメータを解析してDHCPと静的IPをサポート
- /にtmpfsをマウント
- ブートパラメータから指定を受け付ける。指定がなければ総RAM容量から適当な割合で
- HTTP/FTP/tftpでルートファイルシステム(gzip圧縮されたcpioアーカイブ?)をダウンロードし、/に展開
- switch_rootして/sbin/initを起動
ネットワークブートマネージャとでも言うのだろうか。
debootstrapなど、ハードウェアに依存せずにルートファイルシステムだけを作るプログラムが増えてくるだろうと勝手に予想している。コンテナ系仮想化の影響。そうすると、VIVER COREの旨味が増す。仮想化用システムを作るのと同じ手順で、VIVER CORE用システム(=ネットワークブートできる)が作れる。
VIVER COREでやらないこと
- ルートファイルシステムの作成支援はしない
- しなくて良いようにする。どのように作ってもブート可能なようにVIVER COREを作る
- VIVERの方針。カスタマイズしまくればネットワークブートできるのは当然
- DHCPサーバーの自動設定はしない
- Copy-on-Writeには立ち入らない(全部tmpfs)
- USBデバイスの判別はたぶんしない。決め打ちでusb-storage
- ファイルシステム判別はたぶんしない(するかも)
- ストレージドライバは決め打ちでロードする
- ドライバのロード以上のハードウェア認識はしない
- X11は無視
- 最近のディストリビューションだったら、自動設定の方が優秀っす。悲しいっす
- X11なんて意味不明です。自動設定なんてムリです。fbdevかvesaにしておけばいいんです
- それからディストリビューション依存が多すぎ
- X11は無視
VIVERと比べてやらないことが多い!割り切りが重要。できないことはできない!
またしてもVIVER CORE単体では役に立たない。私が作っているものってそんなモンばっかりっすなぁ。うへ。
実装の方針
initramfsはuClibc環境。busyboxとrubyインタプリタを内蔵する。
プラガブル/拡張可能性は目指さない。initramfs自体はall-in-one。
ハードウェア認識
ハードウェア検出は2段階に分ける。1つはinitramfsの中。もう1つはswitch_root後。initramfsの中に入れるカーネルモジュールは最小限にし、サイズを抑える。
initramfsに入れるカーネルモジュールは以下(Linux 2.6.22の場合)
drivers/hid # usbkbdが無いといろいろ困る drivers/pcmcia # 要らない? drivers/block/loop.ko # ルートファイルシステムのダウンロード用で必要かも drivers/block/nbd.ko # ルートファイルシステムのダウンロード用で必要かも drivers/net net/packet fs/squashfs # ルートファイルシステムのダウンロード用で必要かも fs/nfs fs/nfs_common fs/smbfs # smbfsでネットワークブートをサポートか?
これで約8MB(非圧縮)
USBのNICは使えないことにする。それから無線LANではブートできないことにする。無線LAN…うーむ。まだ要らないと思う。
それからinfinibantなんて要らないよね…iSCSIは欲しいかも?(でもNBDでいいような)
IPv6はまだ必要ないと思う。IPv4はカーネル組み込みになっていることを期待。(要調査)
起動したら/procと/sysをマウントし、最初にPCIデバイスの自動検出を行う。そしてカーネルモジュールをロード。ここでロードするモジュールは以下。
ネットワークの起動
ブートパラメータの解析+コマンドの実行で。ブートパラメータの書式は以下。
# これは自動で行われる ifconfig lo 127.0.0.1 netmask 255.0.0.0 # 静的IPの場合 ifconfig eth0 192.168.0.2 route add default gw 192.168.0.1 dns 192.168.0.1 # DHCPの場合 dhcp eth0
これをサーバー側でDeflate+Base64にしてブートパラメータに渡す。(こうしないとパラメータが長くなりすぎる。どうも制限が256文字らしい。include/asm-i386/setup.h #define COMMAND_LINE_SIZE 256)
str = ARGF.read.split("\n").join(";") str = ";" + str str.gsub!(/ */, " ") str.gsub!(/; +/, ";") str.gsub!(";ifconfig", ";i") str.gsub!(";dns", ";d") str.gsub!(";route add default", ";rf") str.gsub!(";route add", ";r") str.gsub!(";route", ";o") zdata = Zlib::Deflate.deflate(str, Zlib::BEST_COMPRESSION) bootarg = Base64.encode64(zdata)
initramfs側では、これを解釈して、逐次実行していく。指定がなければdhcp eth0と判断。
ルートファイルシステムのダウンロード
まず/sysrootにtmpfsをマウントする。サイズは、ブートパラメータで指定があればそれを使う。指定がなければ、できる限りたくさん。後でremountして減らす。(tmpfsって減らせたっけ?)
ダウンロード元は、ブートパラメータで指定する。これは必須のパラメータ。指定がなければエラー。
指定方法はURL。ダウンロードにはbusybox内蔵のwget、またはtftpを使う。2つ以上指定されていたらランダムで選択する。負荷分散用。サポートするプロトコルは以下。
ファイルのフォーマットは、デフォルトはgzipされたcpioアーカイブ。wget|gzip|cpioとパイプでつないで、/sysrootに展開する。ブートパラメータで変更可能。Buxyboxでlzmaがサポートされているらしいので、ネットワークに負荷をかけたくない場合はlzmaが良いかも。
サポートするフォーマットは以下。
switch_root
/sysrootにダウンロードが完了したら、サブインタプリタをforkしてchrootし、2回目のハードウェア認識と、初期設定を行う。
- /procと/sysをマウント
- PCI検出
- モジュールをロード
- /etc/fstabと/etc/mtabの記述をHack
- /procと/sysをアンマウント
これが終わったら、switch_rootして/sbin/initを起動する。その後は/usrをNFSでマウントするなり(fstabに書いておく)、V-FIELD+squashfs+aufsで/usrをマウントする!なり、好きにしていただく。ネットワークが落ちても大丈夫なので、何をやっても可。/のファイルシステムがtmpfsなのと、/etc/fstabと/etc/mtabがhackされている以外は、通常の環境と同じ。
ツール
VIVER COREを作るツールが必要。カーネルモジュールをinitramfsに組み込み、gzip+cpioで圧縮する。たぶん簡単なシェルスクリプトで済む。
$ sudo mkinitvcore [path to kernel module /lib/modules/`uname -r`] <output file name>
それから、debootstrapなどで作ったルートファイルシステムを、gzip+cpioで圧縮するツール。これも簡単なシェルスクリプト。
$ sudo mkvcoreroot <path to root filesystem> <output file name> [-f gzip+cpio|lzma+cpio] [-e exclude path] [-e exclude path]
先のブートパラメータをDeflate+Base64するツール。
thttpd、tftpd、pxelinux、dhcpdを含む簡易ブートサーバーパッケージ。コレ1本でブートサーバになります的な。chrootして使用。uClibc環境。(glibcでいいかな)