お馴染rc.conf
でjailを有効にする。
jail_enable="YES" jail_list=" "
ZFSでjail用のFSを作り/jail
にマウントする。もちろん、パスは任意でおk。
# zfs create -o mountpoint=/jail zroot/sys/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なのでなるべくクリーンな状態の方針で。
試しに、作成した種jailにjailerと同じIPアドレスを割り当て、監獄の中から通信できるか試してみる。
/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
# 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 # exit $ 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
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を止める
# service jail stop _seed Stopping jails: _seed.
各jailでportsツリーを持つのは無駄なので、jail外に共有portsツリーを作りnullfsでマウントするようにする。
共有リソース用のFSを作る
# zfs create -o compression=gzip-5 zroot/sys/jail/_share
共有portsツリーを展開
$ cd /jail/_share # mkdir ports distfiles # portsnap -p ports fetch # portsnap -p ports extract # portsnap -p ports update
jail起動時に共有portsツリーをマウント、終了時にアンマウントするようにjail.confを修正。
exec.prestart += "mkdir -p /jail/${name}/usr/ports /jail/${name}/var/ports/distfiles" 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などの使わないであろう機能のビルドオプションをデフォルトオフにしておく。
WRKDIRPREFIX = /var/ports/ DISTDIR = /var/ports/distfiles/ PACKAGES = /var/ports/packages/ OPTIONS_UNSET=CUPS DEBUG DOCS FONTCONFIG NLS X11 WITHOUT_X11=yes FORCE_MAKE_JOBS=yes MAKE_JOBS_NUMBER=3 </code> ==== 種jailの設定 ==== 再び種jailの中に入り、諸々設定する。 ''freebsd-update''をしておく。srcは更新対象から外しておく(src込みでインストールしたならこの限りではない)。 <file conf /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 perl5 sudo texinfo
一応、hostとjailでUID, GIDが被らないように設定。といっても、システムが自動で作るユーザー/グループ(rootとかwwwとかmysqlとか)には無力だし、ユーザー追加時に手動でいくらでも好きな数値が指定できるので、あんまり神経質なっても仕方がない。jail間の被りも避けたいなら、maxuid/maxgidも使っていい感じの値を設定してくだしあ。
minuid 30000 mingid 30000
ZFSのスナップショット&クローンを活用すれば、一瞬で種jailから本番jail環境を複製する事ができる。
まずはスナップショットを作る。
# zfs snapshot zroot/sys/jail/_seed@20180831
スナップショットは読み込み専用なので、cloneしてFSを作る。
# zfs clone zroot/sys/jail/_seed@20180831 zroot/sys/jail/www
こんな感じで本番jail環境が出来上がる。
$ zfs list zfs list NAME USED AVAIL REFER MOUNTPOINT zroot 1.97G 36.5G 96K legacy zroot/sys 1.96G 36.5G 96K legacy zroot/sys/jail 1.96G 36.5G 104K /jail zroot/sys/jail/_seed 1.20G 36.5G 1.20G /jail/_seed zroot/sys/jail/_share 773M 36.5G 773M /jail/_share zroot/sys/jail/www 8K 36.5G 1.20G /jail/www
あとは/etc/jail.confに作成したjailの記述を追加する。