BSD界隈四方山話

第3回 複数バージョンのFreeBSDをJailで共有させる方法

この記事を読むのに必要な時間:およそ 8 分

現実問題としてのバージョン固定化

管理の簡単さやセキュリティの面などいくつかの側面から,どのホストも軒並み最新版へアップグレードし続けることが望まれるわけですが,実際にはそう言う状況にはなりません。一度動き出したシステムはできるだけアップグレードを避けたがる傾向があり,複数のバージョンが混在しているというのはよく見られる光景です。

しかし,ハードウェアの耐用年数には限界がありますので,いずれは環境を新しいハードウェアへ移行させるなり,仮想環境へ移行させる必要があります。ここで問題になるのは古いカーネルのデバイスドライバです。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環境を作るには,次のように成果物をダウンロードしてきて展開すれば終了です。スーパーユーザで展開してください。

図1 Jail環境を用意する

# mkdir /path/to/j9
# cd /path/to/j9/
# fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/amd64/9.3-RELEASE/base.txz
# tar zxpf base.txz
# rm base.tgz

base.txzを展開するとルートディレクトリに展開されるいつものファイルやディレクトリがあることを確認できます。

図2 配布物を展開すればそのまま利用できる

# tree -L 1
.
├── COPYRIGHT
├── bin
├── boot
├── dev
├── etc
├── lib
├── libexec
├── media
├── mnt
├── proc
├── rescue
├── root
├── sbin
├── sys -> usr/src/sys
├── tmp
├── usr
└── var

15 directories, 2 files
# 

ここでは/Users/daichi/j9というディレクトリにファイルを展開したので,/etc/jail.confファイルを作成して次のような設定を追加してあげます。

リスト1 /etc/jail.confに追加する設定

j9 {
        jid = 9;
        name = j9;
        path =/Users/daichi/j9;
        ip4.addr = 192.168.1.252;
        host.hostname = jail9.ongs.co.jp;
        allow.raw_sockets;
        exec.start = "/bin/sh /etc/rc";
        exec.stop = "/bin/sh /etc/rc.shutdown";
        interface = bge0;
        mount.devfs;
}

意味は書いてあるとおりですが,簡単に説明すると次のようになります。

  • 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を作成したら次のようにコマンドを実行して環境を起動します。

図3 作成したJailの起動

# service jail start j9
Starting jails: j9.
# 

Jail環境はjls(8)コマンドで表示させることができます。ここでは今作成したj9というJail以外にもj1という環境が動作していることがわかります。

図4 作成したJail環境を一覧表示

# jls
   JID  IP Address      Hostname                      Path
     1  192.168.1.251   jail1.ongs.co.jp              /Users/daichi/j1
     9  192.168.1.252   jail9.ongs.co.jp              /Users/daichi/j9
# jls -v
   JID  Hostname                      Path
        Name                          State
        CPUSetID
        IP Address(es)
     1  jail1.ongs.co.jp              /Users/daichi/j1
        j1                            ACTIVE
        2
        192.168.1.251
     9  jail9.ongs.co.jp              /Users/daichi/j9
        j9                            ACTIVE
        3
        192.168.1.252
# 

コメント

コメントの記入