KOBA789 です。
昨日作った Node.js ホスティング向けの Jail を既に2名のテストユーザーの方に使っていただいています。
まだ node-http-proxy の運用は開始していないので、外部からのウェブアクセスはできず、SSH しか繋がらないのですが……。
それはさておき、今回はその Jail 環境を構築したときのお話です。
発端
自分は高校でコンピュータ部の部長をしています。うちのコンピュータ部ではゲーム制作がメインなので、自分はあまり何かを作るということはないですが、他の高校1年の部員が RPG を作りたいと言うので、せっかくなら HTML5+JavaScript で作ったらどうかと勧めました。すると、どうやらマジになってくれたようなのでとても嬉しかったのですが、さらにさらに、ついでだから Git も使おうよ、と言いかけたところで、次のことに気が付きました。
- Windows で Git を使うにはよくわからん GUI ツールを入れなければならない
- そのよくわからんツールを学校のマシンにインストールすることは(セキュリティ的制限で)できない
(ノ∀`)アチャー
という経緯で「それならうちのサーバーを貸せばいいんじゃね?」と思ったわけです。
しかししかし、これにも問題があって、
- まるごと一台貸せるほど台数に余裕が無い
- koyomi サーバーなら貸せるけど非力すぎて残念
なので「では仮想マシンを立てよう」とも思ったのですが、仮想マシンはなんか RAM をバカ食いするイメージがあって嬉しくない。
そこで俺は思い出した。FreeBSD の Jail があるではないか、と。今でこそ Ubuntu Server 10.04 のサーバーが2台も動いていますが、自分が宅鯖始めた時は FreeBSD を使っていて、FreeBSD が大好きだったりします。
そして、どうせなら性能の良いマシンで贅沢環境を組みたいなぁとも思い、RAM 16GB、SSD 64GB、HDD 640GB というハードを用意しました。そしてファイルシステムは流行りの ZFS で、しかも Jail はただの Jail ではなく、ネットワークスタックを仮想化できる VIMAGE も使うことに。
SSD cached な ZFS の FreeBSD の構築はFreeBSD Install Battle をして、Root On ZFS かつ SSD Cache な環境を手に入れたときのメモ - ダイアリーはてなブログを参照にしてください。
構築
以下、完全に記憶に頼って書いているので、変な所があったらツッコミお願いします。
データセットの準備
まず、ZFS Pool に Jail 用のデータセットを作ります。
# zpool list NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT zroot 596G 6.99G 589G 1% 1.00x ONLINE - # zfs create -o 'mountpoint=/jails' zroot/jails # zfs list NAME USED AVAIL REFER MOUNTPOINT zroot 11.1G 576G 669M legacy zroot/jails 728M 576G 37K /jails zroot/swap 4.13G 580G 16K - zroot/tmp 43K 576G 43K /tmp zroot/usr 5.53G 576G 3.73G /usr zroot/usr/home 454M 576G 454M /usr/home zroot/usr/ports 1.36G 576G 1.36G /usr/ports zroot/var 88.8M 576G 88.8M /var zroot/var/tmp 32K 576G 32K /var/tmp
こんな感じ。/jails にマウントしておきます。
次にすべての Jail の元になるデータセットを作ります。ボイラープレートってやつですかね。
# zfs create zroot/jails/basejail
そして installworld と distributewoorld します。
# cd /usr/src # make installworld DESTDIR="/jails/basejail" # make distributeworld DESTDIR="/jails/basejail"
これで立ち上げる準備はできたので、とりあえずスナップショットを取っておきましょう。
# zfs snapshot zroot/jails/basejail@created
zfs では簡単にスナップショットが取れるので便利です。
さて、では実際にインスタンスを立ち上げてみましょう。まずは basejail を元にしたクローンデータセットを作ります。
# zfs clone zroot/jails/basejail@created zroot/jails/testjail
zfs ではクローンも一瞬です。クローンできたら実際に立ち上げてみましょう。
# jail -c vnet name=testjail host.hostname=testjail path=/jails/testkjail/ persist
これで立ち上がりました。jls コマンドで Jail の一覧を見てみます。
# jls JID IP Address Hostname Path 1 - testjail /jails/testjail
ネットワークの準備
さてここからはネットワークの設定です。
まず、ホスト側に epair と bridge を作成します。
# ifconfig bridge create bridge0 # ifconfig epair create epair0a
そして、ブリッジに物理インターフェースの re0(適宜読み替え) と作成した epair0a を追加、それぞれ up します。
# ifconfig bridge0 addm re0 addm epair0a ip # ifconfig epair0a up
そして、epair の逆側、epair0b を testjail に割り当てます。
# ifconfig epair0b vnet 1
こうすると、testjail 側に epair0b が出現します。Jail に入って確かめてみます。
# jexec 1 /bin/csh testjail# ifconifg lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384 options=3<RXCSUM,TXCSUM> inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 inet 127.0.0.1 netmask 0xff000000 nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL> epair0b: flags=8843<BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=8<VLAN_MTU> nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL> media: Ethernet 10Gbase-T (10Gbase-T <full-duplex>) status: active
こんな感じです。ifconfig の結果は結構適当なのでアテにしないでください。
確認できたら epair0b に IP アドレスを割り当てます。
testjail# ifconifg epair0b 192.168.11.128
ホストの IP が 192.168.11.6 なのでこんな感じにしました。適宜読み替えてください。
このままでは Jail からゲートウェイの外へ出られないのでデフォルトゲートウェイを追加します。
testjail# route add default 192.168.11.1
これで外のネットワークに接続できました。ルーティングテーブルを netstat で確認するため、/dev を testjail にマウントしましょう。
testjail# exit # mount -t devfs dev /jails/testjail/dev
マウントできたら netstat -rn で確認します。
# jexec 1 csh testjail# netstat -rn Routing tables Internet: Destination Gateway Flags Refs Use Netif Expire default 192.168.11.1 UGS 0 470 epair0 127.0.0.1 link#1 UH 0 0 lo0 192.168.11.0/24 link#2 U 0 45 epair0 192.168.11.128 link#2 UHS 0 0 lo0
良い感じです。本当はこの下に IPv6 のルーティングテーブルが表示されますが省略しています。
完成
以上で最小構成は完成(のはず)です。お疲れ様でした。
あとは sshd を立ち上げるなりなんなりと。
devfs は用途に応じて適切に mount しましょう。