自分がウェブシステムを学び始めた昔にPostgreSQLはよく触っていた。当時はMySQLに比べて遥かにリッチなミドルウェアに見えていた。その後のMySQLの隆盛は言うまでもなく、すっかりPostgreSQLに触れることは減っていった。それでも幾つかのツールのバックエンドとしてPostgreSQLが採用されることがある。代表的なものとしてはChefとか。そして、私が利用し始めたMAASもバックエンドはPostgreSQLだ。その冗長化を達成するにはPostgreSQLのHA化が必須となる。
やむなく重い腰をあげて、数年振りにPostgreSQLを触ってみる。冗長化を考えるとMariaDBとかの方が運用が楽なんだけど、なぜPostgreSQLが採用されるのだろう。開発面ではPostgreSQLの方が効率よかったりするんですかね。一部分析系のツールがPostgreSQLベースで作られてたりするっていうのは聞いたことがあるけど。ぶつくさ言いながら、PostgreSQLの冗長化方法を調べる。Galera Cluster的なマルチマスターは出来ないっぽいね。HAにおいてはマルチマスターが一番楽なんだけど。
一方のレプリはPostgreSQLの標準機能で実現可能。ストリーミングレプリケーションというらしい。以前はSlony-Iとか使ってた気がするけど。データモデルの複製はもはや標準機能の範囲ということなのかね。素晴らしい時代になったものだ。冗長化はpgpool-IIを使えばいいのかな。このツールでストリーミングレプリケーションしているPostgreSQLのフェールオーバなどが出来るらしい。何はともあれ、PostgreSQLのインストールをしてユーザーを作るところから。
ssh db1
echo "deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main" | sudo tee -a /etc/apt/sources.list.d/pgdg.list
curl -s https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
apt update
apt install -y postgresql
sudo -u postgres createuser -s root
createdb root
createuser -U postgres repl -P -c 5 --replication
Enter password for new role:
Enter it again:
root用のDBアカウントを作るかどうかは好みなんだけど、毎回postgresユーザーに切り替えるのが面倒なので作っちゃいました。好みでない人はスキップしてもらっても大丈夫です。手順は適当に読み替えて進めて下さい。replユーザーの作成は必須。続いてarch用のディレクトリを用意して、レプリ用の設定をpostgresql.confに書き加える。また、別ノードから接続可能なようにpg_hba.confも修正する。具体的には以下のような作業になる。
mkdir /var/lib/postgresql/replarch
chown postgres /var/lib/postgresql/replarch
echo 'host replication repl 192.168.0.0/24 md5' >> /etc/postgresql/11/main/pg_hba.conf
vi /etc/postgresql/11/main/postgresql.conf
:
listen_addresses = '*'
wal_level = replica
archive_mode = on
archive_command = 'test ! -f /var/lib/postgresql/replarch/%f && cp %p /var/lib/postgresql/replarch/%f'
max_wal_senders = 10
hot_standby = on
systemctl restart postgresql
こちらがマスター側なんだけど、hot_standby=onの設定を予め入れちゃってます。どうせフェールオーバでどっちもスレーブになったりするので、マスターとスレーブを同じ設定にしておくため。続いて同じようにスレーブ側のPostgreSQLを構築する。pg_basebackupを使ってマスター側のデータをコピーする。設定ファイルもマスターと同じで問題ないのでコピーしてしまう。そして、スレーブ設定を入れるためのrecovery.confを作成してDBを起動する。
ssh db2
apt install -y postgresql
systemctl stop postgresql
mv /var/lib/postgresql/11/main /var/lib/postgresql/11/_main
sudo -u postgres pg_basebackup -h db1 -D /var/lib/postgresql/11/main -U repl -P -X stream
Password: repl
mkdir /var/lib/postgresql/replarch
chown postgres /var/lib/postgresql/replarch
rsync -avR db1:/etc/postgresql/11/main/pg_hba.conf /
rsync -avR db1:/etc/postgresql/11/main/postgresql.conf /
cp /usr/share/postgresql/11/recovery.conf.sample /var/lib/postgresql/11/main/recovery.conf
chown postgres:postgres /var/lib/postgresql/11/main/recovery.conf
vi /var/lib/postgresql/11/main/recovery.conf
:
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=db1 port=5432 user=repl password=xxxx'
systemctl start postgresql
これでレプリ環境の構築は完了。マスター側で更新を行えばスレーブ側に反映されるのが確認できる。MariaDBの方はすっかりGalera Clusterを当たり前に使っているから、フェールオーバとか気にしなくていいんだけど、マスター・スレーブ構成の場合はフェールオーバ手順も確認する必要がある。フェールオーバそのものは簡単で、マスターを停止してからスレーブ側で昇格用のコマンドを発行すればよい。具体的には以下のような感じ。
ssh db1
systemctl stop postgresql
ssh db2
pg_ctlcluster 11 main promote
第1引数はバージョンで、第2引数はクラスター名。デフォルトはmainになってるので、そのまま実行。これでスレーブ側が昇格されて更新可能となる。停止した旧マスターをスレーブとして復帰させるには、recovery.confを用意してDBを起動すればよいだけ。意外と簡単。ちなみに新マスター側でrecovery.confはrecovery.doneと言う名前にリネームされているので注意。
ssh db1
rsync -avR db2:/var/lib/postgresql/11/main/recovery.done /
mv /var/lib/postgresql/11/main/recovery.done /var/lib/postgresql/11/main/recovery.conf
sed -i 's/db1/db2/' /var/lib/postgresql/11/main/recovery.conf
systemctl start postgresql
思ったよりもマスター・スレーブ運用は省力化できそうだけど、マルチマスターほど楽ではない。あとはpgpool-IIでどこまでマスター切替を自動化できるかにかかってるかな。PostgreSQLでも早くマルチマスターが実現してくれることを祈りつつ、次回はpgpool-IIの設定に挑戦してみる。