文書の過去の版を表示しています。
FreeBSD 11でjail環境を作る
用語
- jail [監獄]
- FreeBSDのjail機能そのものを指したり、同機能を用いて構築された(仮想)システム[=hosted/prisoner]を指したりする。要はサンドボックス。
- hosted
- jailシステムで隔離されたシステム、プロセス、サービスを表す。
- host
- jailシステムが動いているシステム、プロセス、サービスを表す。名前の通りの意味。
- prisoner [囚人]
- hostedに同じ
- jailer [看守]
- hostに同じ
試した環境
- FreeBSD 10.1-RELEASE
- FreeBSD 11.1-RELEASE
種jailの準備
jailの有効化
お馴染rc.confでjailを有効にする。
- /etc/rc.conf
jail_enable="YES"
jailのインストール
ZFSでjail用のFSを作り/jailにマウントする。もちろん、パスは任意でおk。
# zfs create zdata/ROOT/jail -o mountpoint=/jail # cd /jails
jailディレクトリに展開されたシステムファイル群でしかないので、他のjailの種となるjailを1個用意しておけば、ただのディレクトリコピーで簡単にjailを増やすことができるのだ。ZFSのsnapshotなどと組み合わせれば、言わずもがな超高速かつ無駄を省いたjail環境を作ることも可能となる。
というわけで、種jailを作る。
bsdinstallでjail環境をインストールする。第二引数でインストールする場所≒jail名を指定するが、jail名にハイフンは含めないこと(詳しくは後述)。
# bsdinstall jail _seed
これまたお馴染みのFreeBSD Installerの画面が出てくる。lib32だけ入れとけば問題ないと思う。portsはnullfsでjailerのツリーを共用すれば容量の節約になる。packagesしか使わねーぜ!!ってんならportsすら不要。その他設定は以下のとおりだが、種jailなのでなるべくクリーンな状態の方針で。
- rootのパスワード
- 何でもいいので取り敢えず設定。コピーjailを作った時に変更する。
- System Configuration
- チェックを全部外す(デフォでは何のデーモンも起動させない。)
- ユーザー追加
- 誰も追加しない。
jailの追加と動作確認
試しに、作成した種jailにjailerと同じIPアドレスを割り当て、監獄の中から通信できるか試してみる。
/etc/jail.confに設定を書く。
- /etc/jail.conf
exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.clean; mount.devfs; path = "/jail/$name"; host.hostname = $name; _seed { ip4.addr = ホストのIPアドレス; allow.chflags; allow.raw_sockets; }
jail環境を起動。
# service jail start _seed Starting jails: _seed.
ip4.addrを処理する所でコケるようで、ハイフンは使えないっぽい?
/etc/rc.d/jail: WARNING: jail_extract_address: type not identified expr: illegal option -- 2 expr: usage: expr [-e] expression
無事起動したら中に入ってみる。必要なのはjexecの行だけ。unameはjailerとprisonerの区別の為に入れてみたが、結果が似すぎてて分からん罠w
$ uname -a FreeBSD jail.example.com 10.1-RELEASE-p10 FreeBSD 10.1-RELEASE-p10 #0: Wed May 13 06:54:13 UTC 2015 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 # jexec _seed /bin/sh # uname -a FreeBSD _seed 10.1-RELEASE-p10 FreeBSD 10.1-RELEASE-p10 #0: Wed May 13 06:54:13 UTC 2015 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64
pingを打ってみる。
# ping decomo.info PING decomo.info (59.106.13.158): 56 data bytes 64 bytes from 59.106.13.158: icmp_seq=0 ttl=56 time=17.167 ms 64 bytes from 59.106.13.158: icmp_seq=1 ttl=56 time=17.236 ms 64 bytes from 59.106.13.158: icmp_seq=2 ttl=56 time=17.215 ms 64 bytes from 59.106.13.158: icmp_seq=3 ttl=56 time=17.151 ms ^C --- decomo.info ping statistics --- 4 packets transmitted, 4 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 17.151/17.192/17.236/0.035 ms
jailから抜けてjailを止める
# exit # service jail stop _seed Stopping jails: _seed.
portsツリーの共有設定
各jailでportsツリーを持つのは無駄なので、jail外に共有portsツリーを作りnullfsでマウントするようにする。
共有リソース用のFSを作る
# zfs create -o compression=gzip-5 zdata/R/jail/_share
共有portsツリーを展開
$ cd /jail/_share # mkdir ports # portsnap -p ports fetch # portsnap -p ports extract # portsnap -p ports update
jail起動時に共有portsツリーのマウント、終了時にアンマウントするようにjail.confを修正。
exec.prestart += "mount -t nullfs -o ro /jail/_share/ports /jail/${name}/usr/ports";
exec.prestart += "mount -t nullfs -o rw /jail/_share/distfiles /jail/${name}/var/ports/distfiles";
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.poststop += "umount /jail/${name}/var/ports/distfiles";
exec.poststop += "umount /jail/${name}/usr/ports";
exec.clean;
mount.devfs;
path = "/jail/$name";
host.hostname = $name;
_seed {
ip4.addr = 218.251.112.107;
allow.chflags;
allow.raw_sockets;
}
portsの作業ディレクトリの設定
# mkdir /jail/_seed/usr/ports # mkdir -p /jail/_seed/var/ports/distfiles # mkdir -p /jail/_seed/var/ports/packages
make.confに作業ディレクトリの指定を追加。ついでに、Xなどの使わないであろう機能のビルドオプションをデフォルトオフにしておく。 /jail/_seed/etc/make.conf
WRKDIRPREFIX = /var/ports/ DISTDIR = /var/ports/distfiles/ PACKAGES = /var/ports/packages/ OPTIONS_UNSET=CUPS DEBUG DOCS FONTCONFIG NLS X11 WITHOUT_MODULES=sound ntfs linux WITHOUT_X11=yes
種jailの設定
再び種jailの中に入り、諸々設定する。
freebsd-updateをしておく。srcは更新対象から外しておく(src込みでインストールしたならこの限りではない)。
- /etc/freebsd-update.conf
Components world kernel # srcを消す
# freebsd-update fetch # freebsd-update install
どのprisonerでもportmaster/pkgは使うことになると思うので、種に仕込んでおく。
# pkg The package management tool is not yet installed on your system. Do you want to fetch and install it now? [y/N]: y Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/freebsd:10:x86:64/latest, please wait... (略) # pkg install portmaster
他に同様のパッケージがあれば、この段階でインストールしておくと便利。参考までに自分が仕込んだのは以下の通り:autoconf automake bash emacs-nox gmake m4 perl texinfo
一応、hostとjailでUID, GIDが被らないように設定。といっても、システムが自動で作るユーザー/グループ(rootとかwwwとかmysqlとか)には無力だし、ユーザー追加時に手動でいくらでも好きな数値が指定できるので、あんまり神経質なっても仕方がないと思う。jail間の被りも避けたいなら、maxuid/maxgidも使っていい感じの値を設定してくだしあ。
- /etc/pw.conf
minuid 30000 mingid 30000
種jailから本番jailを生やす
ZFSのスナップショット&クローンを活用すれば、一瞬で種jailから本番jail環境を複製する事ができる。
まずはスナップショットを作る。
# zfs snapshot zdata/R/jail/_seed@20180831
スナップショットは読み込み専用なので、cloneしてFSを作る。
# zfs clone zdata/R/jail/_seed@20180831 zdata/R/jail/www
こんな感じで本番jail環境が出来上がる。
$ zfs list zfs list NAME USED AVAIL REFER MOUNTPOINT zdata 1.97G 36.5G 96K legacy zdata/R 1.96G 36.5G 96K legacy zdata/R/home 5.19M 36.5G 5.19M /usr/home zdata/R/jail 1.96G 36.5G 104K /jail zdata/R/jail/_seed 1.20G 36.5G 1.20G /jail/_seed zdata/R/jail/_share 773M 36.5G 773M /jail/_share zdata/R/jail/www 8K 36.5G 1.20G /jail/www
あとは/etc/jail.confに作成したjailの記述を追加する。
