実マシン、仮想マシンにたくさん CentOS 5.1 を入れる修行

解決すべき問題

背景

過去の開発プロジェクト資産を、複数の実マシンから仮想環境に移行しようとしている。仮想環境は RedHatLinux 上の Xen 3 系の上に構築する。具体的には CentOS 5.1 と Xen 3.0 の組合せになる。

現状
  • 実マシンへの OS & Xen 環境インストールは PXE + kickstart でほぼ自動化のめどが立っている。
  • 仮想マシンについては、virt-install + kickstart + shell script(virt-install に必要な引数をつけて起動するもの。VMM マシン(実マシン)で NFS マウントして実行)でほぼ自動化のめどが立っている。
問題
  • 一つのマシンに対する設定が、さまざまな場所に分散している。
    • pxeconfig、kickstart ファイル、shell script、DHCP サーバ
  • DHCP サーバに PXE 用の設定を渡すために、通常利用しているのとは別のセグメントを作る必要がある。
    • 多くの「PXE やってみました」的ブログでは「同一ブロードキャストセグメントに DHCP サーバがあれば停止しておく」という方法が示されている。
  • 設定ファイルには各マシンごとに違う部分と同じ部分が存在する。
    • どこがそのマシンに特徴的な設定かがわかりづらい。
  • インストールのためだけに立ち上げるサービスが多数ある。
    • dhcp, tftp-server, NFS サーバ or HTTP サーバ。

問題解決時のビジョン

  • 新たなマシンをインストールする際には、一つのファイルに他と異なる部分を少しだけ書けば済むようになっている。
    • 各マシンの設定の違う部分が明確に、また簡潔にわかるように記述できる。
    • 一つのマシンの設定については、一箇所にまとめて記述できる。
  • トリガを一つ引けば全自動でインストールができる。
    • 実マシンで PXE 対応の場合、電源を ON にすればよい。
    • 仮想マシンの場合、VMM 上で virt-install を駆動する shell script を叩けばよい。
  • インストールに必要なものが one stop でインストールできる。

問題の分析

DHCP サーバとネットワーク構成

先述のとおり、「PXE やってみました」的ブログでは、「同一ブロードキャストセグメントに DHCP サーバがあれば停止しておく」という方法がほとんど。「BB ルータで DHCP サーバ機能が動いていたけど、なんかできちゃいました」というものも見た。しかし、粗く言ってしまえば、一連のブロードキャストパケットのうち、DHCPDISCOVER が目的の DHCP サーバだけに届けば、あとのシーケンスのパケット(DHCPOFFER, DHCPREQUEST, DHCPACK)は別の DHCP サーバに届いても問題ないはず。

別の考え方として、MAC アドレスによって返すネットワーク情報を変えることが挙げられる。PXE において各マシンを識別するのに MAC アドレスを利用するということは、MAC アドレスとマシンの対応表が存在することは前提なので、それを DHCP サーバで利用することも問題ない、というよりむしろ情報の一元化という意味では推奨される。DHCP サーバ側も、MAC アドレスごとに返す情報を変えられるようになっているものが多い*1ので、問題ない。すでに稼働中の DHCP サーバをコントロールできるのであれば、上述の方法を用いて DCHP サービスを継続しつつも、PXE ブートにも対応できるだろう。

この方法は、DHCP サーバ方式の検疫ネットワークと同じと考えてよいだろう。

同じブロードキャストドメインに存在する DHCP サーバに手を入れたくない場合には、稼働中のセグメント(以後、SEGs と表記)とインストール用のセグメント(以降、SEGi と表記)を Layer 2 レベルで分離する必要がある*2。その上で、SEGs と SEGi をつなぐブリッジで一工夫する必要がある。DHCP パケットを選択的に廃棄する、というのも一つの方法だし、SEGi のインストール済みの MAC アドレスからの DHCP パケットは SEGs にリレーする、という方法も考えられる。

インストール対象のマシンに送られる情報

インストール対象のマシンに送られる情報を整理してみる。

動的? 情報 プロトコル 低速可
filename DHCP
next-server DHCP
pxelinux TFTP
pxeconfig TFTP
vmlinuz TFTP
initrd TFTP
kickstart NFS/HTTP/FILE*3
shell script NFS*4
インストールイメージ NFS/HTTP/FTP ×

「動的?」の欄は、マシンごとに送る情報を変化させる場合に動的であるべきかどうかを示している。「○」は動的にする必要があるもの、「△」はこれを動的にすることでも対応可能なもの、「−」は動的にしないほうが幸せだろうというもの。
「低速可」は、スループットが必要かどうかを示している。要は、インストールイメージの転送には速度が必要だけど、それ以外はオーバヘッドの高いプロトコルでも構わないし、サーバ側をスクリプト言語で書いても構わない、という話。

プロトコル」が TFTP のものについても、TFTP のスペックを実装する必要はない。極端に言えば、GET にだけ対応していればいいし、表中のファイルを返すことさえできればよい。HTTP のものも同様で、リスンポートが 80 番でなくてもいいし、GET にだけ対応していれば十分。

問題は動的に返す必要があるものをどうするか。HTTP については CGI を利用すればいいので特に考えなくてもいいが、TFTP や NFS の項目については何か考える必要がある。統一的で簡単な方法は、ファイルシステムへのアクセスに対し、パス名や環境変数を基に動的な値ような擬似デバイスドライバを作ることではないだろうか。

*1:多いよね?

*2:SEGs と SEGi を長いケーブルで接続することで、ブロードキャストも互いに届くが、DHCPDISCOVER パケットは目的のサーバに届きやすい、というネットワークは作れるかもしれない。が、コリジョンが発生すると破綻する。はず。

*3:kickstart ファイルは initrd に組み込んでおけば、file:// スキーマで指定できる。らしい(弱っ)。

*4:ネットワークマウントして実行できればなんでもよい。FUSE を使えば HTTP でもいいわけかな。あー、いろいろできそうだが、ここを掘ると大変そうだなぁ。