現実問題としてのバージョン固定化
管理の簡単さやセキュリティの面などいくつかの側面から、どのホストも軒並み最新版へアップグレードし続けることが望まれるわけですが、実際にはそう言う状況にはなりません。一度動き出したシステムはできるだけアップグレードを避けたがる傾向があり、複数のバージョンが混在しているというのはよく見られる光景です。
しかし、ハードウェアの耐用年数には限界がありますので、いずれは環境を新しいハードウェアへ移行させるなり、仮想環境へ移行させる必要があります。ここで問題になるのは古いカーネルのデバイスドライバです。Intelが2年おきに新しいハードウェアをリリースしていますので、さまざまなチップが2年おきに新しくなっています。
つまり、2年以上経過すると、ドライバをアップデートするなりバックポートするなりしないと、動作しないケースが増えます。たとえば10.1-RELEASEが出ている今の状況で6.1の環境を現在のハードウェアに持ってきても、動かないケースが多いと思います。仮想環境であればレガシーモードで古いハードウェアの設定に切り替えて使うところですが、直接ハードウェアとなると難しいものがあります。
複数のバージョンのユーザランドを混在させる
こうした場合にはいくつか対処方法がありますが、そうしたものの1つにJailを使うという方法があります。カーネルは後方互換性を保持していることが多いので、最新のカーネルを使いつつ、ユーザランドは古いものを持ってきて使う、と言った内容です。
アプリケーションによっては特定のバージョンでないといろいろ都合が悪いとか、アップデートするつもりがそもそもないといった場合には、この方法が使えます。Jailの環境内だけを別のバージョンにしてカーネルはホストの提供する最新版を使います。
この方法はXenやKVM、bhyve、VMware、VirtualBoxなどの仮想化技術を使う場合と比べて、消費するリソースがとても少ないという特徴があります。異なるカーネルや異なるオペレーティングシステムを混在させるにはハイパーバイザ系の仮想化技術を採用する必要がありますが、単一のカーネルで良い場合にはJailが最適でしょう。
Jailってなに
Jailは最初にFreeBSDに実装された区画化技術の1つで、基本的にはファイルシステムとプロセス空間をホストから切り離して独立しているかのように見せかける技術です。もともと一般ユーザにroot権限を付与する技術として考案されました。
UNIX系のオペレーティングシステムは基本的にスーパーユーザ(root)とそれ以外のユーザと言う区別しかもっておらず、rootの権限の一部を一般ユーザに付与するという機能を基本的に提供していません(setuid、setgid、sticky bitみたいな仕組みはあります)。
Jailはこれを可能にする技術で、Jail内部では一般ユーザにrootのアカウントを付与できます。一般ユーザはJail空間の中ではrootとして振る舞うことができるのですが、このrootはできることが限られていて、ホストやほかのJailに影響が出ないようになっています。
この機能を利用すれば、たとえば10.1-RELEASEの中に9.3-RELEASEのユーザランドを構築して利用すると言ったことができます。Jailが登場した当時、この機能を使うのは少々面倒でしたが、10系に入ってからは管理機能が本体に導入されたので、簡単に利用できるようになりました。
9.3-RELEASEのJailを作ってみる
9.3-RELEASEのJail環境を作るには、次のように成果物をダウンロードしてきて展開すれば終了です。スーパーユーザで展開してください。
base.txzを展開するとルートディレクトリに展開されるいつものファイルやディレクトリがあることを確認できます。
ここでは/Users/daichi/j9というディレクトリにファイルを展開したので、/etc/jail.confファイルを作成して次のような設定を追加してあげます。
意味は書いてあるとおりですが、簡単に説明すると次のようになります。
- jid:JailのID番号
- name:Jailの名前
- ip4.addr:Jailに割り当てるIPv4アドレス
- host.hostname:Jailに割り当てるホスト名
- allow.raw_sockets:ping(8)が通るようにする
- exec.start:起動時の処理
- exec.stop:終了時の処理
- interface:割り当てるホスト側のNIC
- mount.dev.fs:/dev/を生やす
いろいろな設定ができます。このあたりの設定はjail.conf(5)のオンラインマニュアルにまとまっていますので、使用する際には読んでみてください。
Jailを作成したら次のようにコマンドを実行して環境を起動します。
Jail環境はjls(8)コマンドで表示させることができます。ここでは今作成したj9というJail以外にもj1という環境が動作していることがわかります。
Jailの中へダイブ
起動したJail環境へダイブするにはjexec(8)コマンドを使う方法が簡単です。次のようにJail名を指定して、そのJail環境のどのコマンドを実行するかを指定すると、指定したJailの中でそのコマンドが実行されます。
uname(1)を実行してみましょう。9.3-RELEASEの環境なのですが、カーネルはホスト側の10.1なのでそちらの情報が出力されます。freebsd-version(1)を使うとカーネルとユーザランドのバージョンを個別にチェックできます(が、9.3-RELEASEにはまだfreebsd-version(1)が登場していませんので、その方法は使えません)。
たとえばユーザランドのファイルを見てみると、ファイルが9.3-RELEASEのものであることを確認できます。
Jail環境を微調整
この環境は配布物を展開しただけなので、少々設定が足りていません。いつもはインストーラで行っている設定をしてあげましょう。
まず、次のようにタイムゾーンを日本標準時に設定します。なにも設定しないとUTCのままなので、時刻がホストとずれて表示されているからです。
FreeBSDがcron(8)経由で定期的に実施している処理は、ゲストとしてJailで動作する場合には不要ですので(なにせホストがすでにその処理をやっていますので)、次のように/etc/crontabファイルの設定をコメントアウトして、cron(8)を再起動しておきます。
最終的にはssh(1)でログインして利用する方が便利ですので、adduser(8)コマンドでユーザを追加します。
DNSも使えるようにする必要があるので、/etc/resolv.confにDNSサーバの設定を加えます。9.3-RELEASEだとdig(1)コマンドで設定が動作しているか確認できます。10系以降はdrill(1)コマンドで動作を確認します。
sshdを有効にする設定を/etc/rc.confに追加して、次のようにservice(8)コマンドを実行してsshd(8)デーモンを起動します。
Jail環境はホストとも別のJailともプロセス空間が隔離されているので、ps(1)でプロセスを表示させるとJail環境内で動作している以外のプロセスが表示されません。カーネルスレッドなども見えませんし、ホストで動作しているプロセスも見えません。
ホストやほかのホストからsshでログイン
ちなみにホストではbge0に対して複数のIPアドレスが割り当てられているように見えます。Jail環境はホストと同じように、ほかのホストからネットワーク経由でログインできます。
ログインすると次のようになります。
バージョン番号が不確定なのが嫌ということであれば、一度だけservice motd startとコマンドを実行してみてください。これでログイン時に10.1-RELEASEと表示されるようになります。実際は9.3-RELEASEのユーザランドなので、気持ちが悪いのであれば/etc/motdファイルを直接編集して書き換えてください。
とっても簡単、Jailを活用しよう
慣れてくると、たとえば上記をすべて手動でやったとしても作業にかかる時間は5分から10分と言ったところです。こうした環境は別バージョンの動作を確認したい場合とか、クリーンな環境で動作を確認したいと言った場合にも使用できます(もちろんカーネルが違うバージョンを使うことになるので、互換性のない部分は動きませんよ)。
とくに10系からはJailの扱いが簡単になっていますので、だいぶ前にJailを使った以来使ったことがないとか、そもそも仮想化ソフトウェアは使ったことがあるけれど、Jail系の技術は使ったことがないという場合には、一度試して欲しいと思います。慣れてくるとアンダー・ザ・コントロールな機能でとても良い感じです。