今回は61回で紹介したubuntu-vm-builderで構成した仮想マシンを,「ターミナル内で」動作させる方法を紹介します。
サーバーにおけるビデオカードの必然性(仮想マシンに限らない話)
仮想マシンを「ターミナルで」動作させる前に,少しだけ「ビデオカードの存在しないマシン」の話について触れてみましょう。
一般的なPCの利用形態では,ビデオカード(もしくはノースブリッジ等に内蔵されたビデオチップ機能)の存在は欠かせません。モニタに画面を表示するためにはこれらのチップを用いてアナログ,ないしはデジタルで出力する必要があります。
しかし,ほとんどのサーバーはネットワーク越しに利用されるものですし,管理者が行うべき作業のほとんどもSSH越しに操作できますから,なんらかの緊急時や,初期セットアップ時といったネットワークが利用できない時にのみモニタが必要になります。
逆にいえば,初期セットアップさえ済ませれば,緊急時以外はモニタは不要になるはずです。多くのUnix/Linuxではこうした考えのもとに,モニタ機能を使用せず,RS-232C(シリアル)接続など(注1)で最低限のコンソールを確保し,ディスプレイを使わない,といった運用が行われることがあります。こうした構成は「ヘッドレス」と呼ばれます。
設定方法さえ把握しておけば,サーバー装置に電源ケーブルとネットワークケーブルだけ(注2)を接続した状態で利用することができるでしょう(注3)。
これは仮想化にどう関係するのでしょうか? 答えは単純で,“仮想化環境であっても,実際のハードウェアと同じように,「ヘッドレス」状態で動作させることができる”ということです。ubuntu-vm-builderで構成したKVM仮想マシンは,起動するとQEMUが提供するコンソール画面が表示されていたはずです。が,サーバーとして利用するのであれば,ほとんどの場合GUIは利用しませんから,あのようなウインドウは不要で,マシンを実行したターミナルでそのまま動作してくれれば便利なはずです。なにより,ああしたウインドウはX環境でしか利用できませんし,SSHから接続した場合はX転送を行わなければ起動できません。これは十分な帯域がなければ利用できませんし,レスポンスも悪く,あまり快適とは言い難いはずです(その一方で,SSHのようにコマンドラインベースの環境であれば,帯域もほとんど要りませんし,比較的快適に利用できます)。
今回は「仮想マシンをヘッドレスで」起動し,ターミナルだけで仮想マシンを利用するレシピを紹介します。
- 注1
- 現在の多くのサーバーではIPMIなどの遠隔管理機能を内蔵しているため,IP接続で利用可能なKVM機能を使うことがほとんどです。さらに,IPMIの機能を使うことで「内部でRS-232Cに接続し,そのセッションをIP越しに接続できるようにする(SoL; Serial over LANと呼ばれます)」こともできます。
- 注2
- モニタがなければキーボードやマウスによる操作は不可能ですので,これらも通常は接続しません。
- 注3
- ヘッドレス構成にするための設定さえ済ませてしまえば,必要な時にRS-232Cで接続することでコンソールを取得することができます。また,前出のSoLや「ターミナルサーバー」と呼ばれるタイプの機器を使うことで,ローカルなシリアルケーブルによる接続ではなく,ネットワーク経由でこのコンソールに接続することもできます。
Ubuntuをヘッドレスで運用する
……ということで,仮想マシンをヘッドレス構成にする前に,Ubuntuをヘッドレス構成にする手順を見ていきましょう。
Ubuntuをヘッドレス構成にし,シリアルポート(RS-232C)を用いてログインできるようにするには,次の3つの設定が必要です。
- GRUBの出力デバイスをシリアルポートにする。
- カーネルのコンソール出力をシリアルポートに向ける。
- シリアルポートからログインできるようにする。
順番に見ていきましょう。
GRUBの出力デバイスをシリアルポートに設定する
最初に,GRUBが出力するブートスプラッシュをシリアルコンソールに出力するように変更します。/boot/grub/menu.lstに以下のように,「serial」と「terminal」の2行を追加します。
# password --md5 $1$gLhU0/$aW78kHK1QfV3P2b2znUoe/
# password topsecret
--unit=0 --speed=115200 --word=8 --parity=no --stop=1
terminal --timeout=5 console serial
#
# examples
#
これにより,GRUBのカウントダウンや,起動時スプラッシュ(図1)がシリアルポートに出力されるようになります。
カーネルのコンソール出力をシリアルポートに設定する
次に,カーネルの起動オプションを変更し,コンソールをシリアルポートに設定します。これもGRUBの設定ファイルである/boot/grub/menu.lstから設定します。
/boot/grub/menu.lstに存在する,「kopt」行に,「console=tty0 console=ttyS0,115200n8」を追加します。
# kopt=root=UUID=4ead8965-89b4-43da-8849-3e8fee00c1c2 ro console=tty0 console=ttyS0,115200n8
このままでは既存のカーネルの起動オプションが修正されませんので,以下のようにupdate-grubを実行して起動オプションに反映します。
$ sudo update-grub
update-grub実行後,menu.lstの下部にある各kernel行に指定したオプションが追加されたことを確認してください。
title Ubuntu 8.10, kernel 2.6.27-11-server
uuid 4b42d9eb-8925-4a8f-ac79-d24e8fa88309
kernel /boot/vmlinuz-2.6.27-11-server root=UUID=4b42d9eb-8925-4a8f-ac79-d24e8fa88309 ro console=tty0 console=ttyS0,115200n8 quiet splash
initrd /boot/initrd.img-2.6.27-11-server
これにより,Kernelの起動メッセージ(Ubuntuの起動時に表示される各種メッセージ)がシリアルポートに出力されるようになります。
シリアルポートからログインできるように設定する
さらに,シリアルポートにログインのためのインターフェースを設ける必要があります。ここまでで行った設定により,GRUBの起動縲弑buntuの起動完了までのメッセージがシリアルポートに出力されるようになりましたが,このままではシリアルポートからログインすることができないためです。
古典的なLinuxでは,シリアルポートからログインできるようにするための設定は,/etc/inittabで行いますが。が,UbuntuではinitデーモンとしてUpstartを利用しているため,inittabで設定すべきではありません(注4)。
Upstartに即した設定を行うため,/etc/event.d/tty1を以下のように書き換えてください。
# tty1 - getty
#
# This service maintains a getty on tty1 from the point the system is
# started until it is shut down again.
start on stopped rc2
start on stopped rc3
start on stopped rc4
start on stopped rc5
stop on runlevel 0
stop on runlevel 1
stop on runlevel 6
respawn
exec /sbin/getty -L ttyS0 115200 vt100
このように設定することで,そのマシンのシリアルポートにクロスケーブルを接続すれば,シリアル経由でログインすることができるようになるはずです。
今回はシリアル接続で操作することが主眼ではないので軽く触れるだけに留めますが,接続するマシンがWindowsであればTeraTermやPuTTYで,UbuntuからであればGNU Screenを利用し,screen /dev/ttyS0 115200などとすればログインプロンプトが表示されるでしょう。
- 注4
- /etc/inittabに対する互換性も維持されていますので,inittab経由の設定も可能です。が,これはあくまで後方互換性として維持されているだけなので,遠い将来には無効になるはずです(なぜ遠い将来なのかといえば,まだまだ当分の間こうした設定が生き残るからです。少なくとも数年間といった単位では有効なままでしょう)。

