PXEを使ってPCもディスクレスにしよう |
YAMAMORI Takenori ●yamamori |
今度はLinuxをディスクレスクライアントにしてみましょう. そのためには,LinuxカーネルがNFS rootに対応している必要があります. しかし,各種ディストリビューションに付属の標準カーネルでは, NFS rootの機能が組み込まれずにカーネルが構築されていることが多いため, NFS root関連の機能を組み込んでカーネルを再構築する必要があります. なお,ここでは当初 Vine 2.0 を使って動作を確認しましたが,その後,Vine 2.1.5 ほかのバージョンでも動作確認しています.
カーネルの再構築のポイントは,DHCP(またはBOOTP)機能の組み込み,NFS root 機能の組み込み,NIC のデバイスドライバの静的リンクの3点です.
“make menuconfig”を用いたカーネル再構築の具体的な手順を示します.
まず最初に,“Networking options”の中の “IP: kernel level autoconfiguration”を選択して[*]状態にします. すると“BOOTP support”のオプションが現れるため,こちらも[*]にします.
●カーネルのBOOTP(またはDHCP)サポートを有効にする
次に, “Filesystems”→“Network File Systems”と画面を進め, “NFS filesystem support”が,デフォルトで<M>になっているのを <*>に変更します. すると,“Root file system on NFS”のオプションが現れるため, これを[*]にします.
●NFS rootをマウントできるようにする
さらに,使用するNICに対応したモジュールを静的に組み込む必要があります. 今回はPRO/100+を使用しているので, “Network device support”→ “Ethernet (10 or 100Mbit)” と画面を進め,この中の “EtherExpressPro/100 support”を, <M>から<*>に変更します.
●eepro100ドライバの静的組み込み
このとき,“EtherExpressPro support”という, よく似た名前の別のモジュールが,画面の上の方に少し離れて存在するため, これと少々紛らわしく,間違えやすいので注意して下さい.
以上の変更は,.configファイルの上では, 基本的に以下の4つのオプションを追加したことに相当します.
CONFIG_IP_PNP=y CONFIG_IP_PNP_BOOTP=y CONFIG_ROOT_NFS=y CONFIG_EEXPRESS_PRO100=y
ただしこれ以外にも, 関連するいくつかのオプションが“make menuconfig”によって, モジュールからカーネル組み込みに自動的に変更されています.
なお,“make menuconfig”では, ほかのオプションとの依存関係を考慮して 選択可能なオプションのみ表示するようになっているため, ある時点で選択不可能なオプションは, その選択肢さえ表示されないため注意して下さい. 今回の例では,先に“BOOTP support”を選択しておかないと, “Root file system on NFS”のオプションが出てきません.
ところで,NICのドライバをカーネルに静的には組み込まず, initrdでモジュールとしてロードすることはできないのでしょうか. 実際,SCSIハードディスクをrootとしてマウントするシステムにおいては, SCSIモジュールをinitrdでロードし,正常にブートすることができます. しかし,NFS rootの場合は,NICのドライバをカーネルに静的に組み込んでおかないと, カーネルに組み込まれたBOOTPが動作しないのです. もっとも,ネットワークブートに対応したNICの種類は現状では限られているので, ドライバを静的に組み込んだカーネルを構築したとしても, それが著しく汎用性を損ねることはないとも言えます.
出来上がったbzImageは,/tftpboot以下に, たとえばvmlinuz-nfsという名前でコピーしておきます.
ここで,Linuxカーネルのみでディスクレスクライアントをブートしてみます.
BpBatchには,Linuxのカーネルを直接ブートするための LinuxBootというコマンドがあるため,BpBatch のプロンプト上で LinuxBoot コマンドを使って,カーネルファイル名やオプションを指定して Linux をブートすることができます.
ただし,LinuxBootコマンドを使う以外にもLinuxをブートする方法がありますので, コラム「ほかにもあるLinuxのブート方法」も参照してください. また,Linuxカーネル 2.4.xでは、BpBatch の LinuxBootコマンドがうまく動作せず,Linuxカーネルを含んだ起動フロッピーディスクイメージを使う方法 (DOS のディスクレスブート と同様の方法) を使う必要がある場合があります.
LinuxBootコマンドはLILOのネットワーク対応版のようなもので, BpBatchのプロンプトに対して,以下のように入力して使います.
> linuxboot "vmlinuz-nfs" "root=/dev/nfs"
> linuxboot "vmlinuz-nfs" "root=/dev/nfs ip=dhcp"としてください。これでディスクレスブートできるはずです。
LinuxBootコマンドの引数は""で囲みます. 第1引数はカーネルファイル名,第2引数はカーネルオプション, そしてここでは使用していませんが,第3引数はinitrdのファイル名となります.
ここではroot=/dev/nfsオプションを指定し, nfsroot=オプションは省略しています. こうすると,カーネルはBOOTP(またはDHCP)でNFS rootの位置を自動的に取得します. これは前述の dhcpd.conf で,“option root-path”として指定しています.
なお,/dev/nfsはNFS rootを指定するための単なる文字列で, 実際にこの名前のデバイスファイルをアクセスするわけではありません.
BOOTPでNFS rootが取得できないような場合は, “/tftpboot/クライアントIP”というディレクトリがデフォルトで使用されます. これはあまり美しくないため,BOOTPでの取得が無理な場合は nfsroot=オプションでNFS rootを指定した方がよいでしょう.
この時点ではまだNFSサーバの設定を行なっていないので, カーネルはNFS rootをマウントできずに止まるはずですが,それでOKです.
本格的なNFS rootを用意する前に, 以下のように,静的リンクのshをinitとして用いて, ブートしてみることができます.
# cd /diskless/linux # mkdir sbin dev # cp -p /bin/ash.static sbin/init ← 静的リンクのshをinitの代わりにする # mknod dev/console c 4 0 ← /dev/consoleだけは必要 |
NFSサーバの設定については, コラム「ディスクレスクライアントのためのNFSサーバの設定」を御覧下さい.
これで再度クライアントをブートすると,今度はNFS rootのマウントが行なわれ, initの代わりのシェルが起動するはずです. 本当にシェルのみで,ほとんど何もできませんが, 「echo *」とやると,devとsbinが確かに表示されることが確認できます.
それでは本番のNFS rootをインストールしましょう.
一般に,ディスクレスクライアントが複数ある場合や, クライアントとNFSサーバのOSが同じ場合では, /usrディレクトリ以下は共有します. 一方,/etc, /var, /dev, /tmpなどや, クライアントが/usrをマウントする前にも必要な/sbinディレクトリについては 各ホスト毎に個別に持ちます. ただし,/sbinについては,NFSサーバ上では各ファイルをハードリンクして, ファイル実体を共有します. この考えは, /binや/libが,それぞれ/usr/binや/usr/libへのシンボリックリンクになっている SolarisなどのOSでは徹底されています. 一方Linuxにおいては, ディスクレスクライアント側で/usrを別途マウントして共有することについて, あまり考慮されていないフシがあるため, ここでは/usrの共有は考えず, LinuxサーバにインストールされているLinuxのファイルシステムを, 単純にまるごと/diskless/linux以下にコピーすることにします.
ファイルのコピーの際には, /diskless/linux自身もコピー元に含まれてしまうと無限ループに陥るため, 適宜コマンドを工夫して下さい. /procや/tmpも,コピー元の対象から外します. /var/log以下のログもコピーされてしまいますが,あとで消せばよいでしょう.
# cd /diskless/linux # tar cvf - -l --exclude /proc --exclude /tmp \ --exclude /diskless / | tar xvpf - # mkdir proc tmp # chmod 1777 tmp |
/diskless/linux以下にコピーされたファイルには, もとのローカルディスク用の古い記述が残ったままになっています. もちろんこのままではシステムが立ち上がりませんので, 以下の修正が最低限必要です.
まず,/etc/fstabを以下のように修正します. ここではswapはとりあえず使わないことにします.
/dev/hda1 / ext2 defaults 1 1 /dev/hda2 swap swap defaults 0 0 |
↓
server:/diskless/linux / nfs defaults 0 0 |
次に,/etc/sysconfig/network-scripts以下にある, ifcfg-eth0スクリプトを削除します. eth0はカーネル自身によって,ブート時にすでに立ち上げられています.
これでクライアントをブートしてみて下さい. rcスクリプトの細かい部分ではエラーが出るかも知れませんが, とりあえずこれで起動するはずです. このあと,各種環境設定を行なえば,ディスクレスの Linux マシンとして使用できます.