FreeBSD JailsでPostgreSQLを動かす

localhostで接続できなくなるのが面倒で先延ばしにしていたが、pg_upgradeを使おうにもFreeBSDでは複数バージョンを同じ環境にインストールできない問題があるため、折角なので移行先バージョンはjail運用に移行しようという試み。

containerd早く動くようになって…😢

参考

Jailsのセットアップ

jail用rootディレクトリの準備

場所は何処でも良いが、(pgroongaをpkgからインストールするため)PostgreSQL13をインストールするので判りやすくした。 ついでにアップデートも行う。

# bsdinstall jail /var/jail/postgresql13
# freebsd-update -b /var/jail/postgresql13 fetch
# freebsd-update -b /var/jail/postgresql13 install

インストール時にはオプションが選択できるが今回は以下ようにした。

  • Distribution Select: lib32*
  • System configuration: デフォルト分も全部無効
  • Add User Accounts: No

またrootパスワードの設定も要求される。 他にユーザーを追加することもできるがpostgres用なのでNoとした。

/etc/rc.confの編集

jail_enable="YES"
ifconfig_msk0_alias0="inet 192.168.0.20 netmask 255.255.255.255"

jailに指定するIPアドレスもaliasとして用意する。IPアドレス自体はLANの都合に合わせた適当なもの。

以上は再起動後の設定用なので、現在の環境には直接指定をする。

# ifconfig msk0 inet 192.168.0.20 netmask 255.255.255.255 alias

/etc/sysctl.confの編集

それぞれjail内からの通信を許可する、共有メモリの使用を許可する設定らしい。

security.jail.allow_raw_sockets=1
security.jail.sysvipc_allowed=1

以上は再起動後の設定用なので、現在の環境には直接指定をする。

# sysctl -w security.jail.allow_raw_sockets=1
# sysctl -w security.jail.sysvipc_allowed=1

/etc/jail.confの作成とjailの設定

jail内からの通信はたぶんこの先作るjailでも指定すると思われるのでglobalで設定。共有メモリは差し当たりPostgreSQLで使えればいいのでjail固有の指定とした。

exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
mount.devfs;
allow.raw_sockets;
host.hostname = $name;

db {
    ip4.addr = 192.168.0.20;
    path = "/var/jail/postgresql13";
    allow.sysvipc;
}

jailを起動

# service jail start db

Jailsでよく使うコマンド

コマンド 概要
jls 起動中のjail一覧を表示
jexec [JID or jail name] jail内にrootでログイン

ここまでで同一subnet内であればpingが通るはず。jailの中からinternetに出るには、jail内でもいくつか設定が必要だ。

jail内で行う設定

主に2つ。

  • /etc/rc.confでのdefaultrouter
  • /etc/resolv.confでのnameserverの指定

DHCPからipアドレスなどのネットワーク情報を貰うのに慣れてしまって忘れがちだが必須である。

/etc/rc.confではdefaultrouterを指定する。今回はipv4だけしか設定していないがipv6も設定するならipv6_defaultrouterも必要だ。

defaultrouter="192.168.0.1"

/etc/resolv.confについては初期状態でhostの/etc/resolv.confがコピーされるらしく、外部のnameserverが設定されているなら特別な設定は不要かもしれないが、我が家の場合はDNSキャッシュを立てているのでそれを示すようにする必要があった。

jailからexitし、host側からjailを再起動する。

# service jail restart db

だが…

再度jailを再起動してもどういう訳かdefaultrouterが指定できていない。

root@db:/ # netstat -nr
Routing tables

Internet:
Destination        Gateway            Flags     Netif Expire
192.168.0.20       link#2             UH          lo0

コマンドで直接指定しようとすると…

root@db:/ # route add default 192.168.0.1
route: writing to routing socket: Operation not permitted

これが解決しないとjailからinternetに繋がらずpkgが使えないのだが…

root@db:/ # 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 ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-9-stable/Latest/, please wait...
pkg: Error fetching ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-9-stable/Latest//Latest/pkg.txz: Non-recoverable resolver failure
Address resolution failed for ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-9-stable/Latest/.
Consider changing PACKAGESITE.

pkg -jを使わなくてもjail内にインストールはできるらしい

数時間かけても原因が判らないため、仕方なくホスト側からchrootモードを使ってインストールする。

# pkg -c /var/jail/postgresql13 install pgroonga postgresql13-server

次にjail内でPostgreSQLを起動する。まずrootでclusterを初期化。

root@db:/ # service postgresql enable
root@db:/ # /usr/local/etc/rc.d/postgresql initdb

もし既に動いているPostgreSQLからDBを移植するなら、postgresql.confpg_hba.confの差分を確認。必要があれば移植元に合わせる。

lc_*のlocate周りは要確認。移植元DBで通貨型や日付/時刻型を使っているならlc_monetarylc_timeは合わせておかないとdumpの移植時にエラーで取り込みに失敗する。

DBユーザーに切り替えdaemonを起動する。

root@db:/ # su postgres
$ pg_ctl -D /var/db/postgres/data13 -l /var/db/postgres/logfile start

とりあえずこれで動いてはいるようだが、hostとjailでkernelのバージョンが揃ってるからかもしれない…

jailフォルダの削除

不要になったら/etc/jail.confの該当jailの設定を削除し、jailが使っていたディレクトリを削除すればよい。ただしsystemフラグが付いていてそのままでは削除できないため、chflagsでフラグを外す。

# service jail stop db
# chflags -R noschg /var/jail/postgresql13
# rm -R /var/jail/postgresql13