「実機サーバー1台しか開発環境ないけど、本番2台でいい感じに同期とる仕組みつくって」と言われたのでいろいろ試した中でのひとつ。
PostgreSQL童貞・Docker童貞からなんとか、動くところまで行ったのでその時に結果を記載
そんな状態なので間違ったこと書いていたらすみません。
やりたいこと
本番相当を作りたいので
- CentOS7
- PostgreSQL10.3
を2台という形で作りたかった(PostgreSQLのサーバーだけでなく、普通にこのあと開発サーバーとしても使うのでこの構成)
事前の状態
もはや用意された実機で動かす必要もないので自前のIDCF Cloud(Ubuntu16.04)を利用
Dokcerの入れ方は公式をそのまま打っただけ
https://docs.docker.com/install/linux/docker-ce/ubuntu/
Dockerのコンテナを作る
マスタ側
何度もはまったところだが、CentOS7をDockerで作ると
systemd コマンド、serviceコマンドなどで
Failed to get D-Bus connection: Operation not permitted
が出て起動しないので、以下を参考に実施
https://blog.adachin.me/archives/3588
# つなぎやすいようにネットワークの設定を入れる
$ sudo docker network create --driver bridge psql
# privilegedと/sbin/initがキモ 今回の内容的には-pのポートフォワードは必要なかったっぽい
$ sudo docker run --privileged --name=postgresql1 --net=psql -d -p 5431:5432 -p 8000:80 centos /sbin/init
# bashで入ってみる
$ sudo docker exec -it postgresql1 /bin/bash
スレーブ側
名前とポートフォワードの設定だけかぶらないようにする
$ sudo docker run --privileged --name=postgresql2 --net=psql -d -p 5433:5432 -p 8080:80 centos /sbin/init
PostgreSQLサーバーの準備(M/S共通)
足りないコマンドを補いつつ下記を参考にというか、ほぼそのまま実行
https://weblabo.oscasierra.net/postgresql10-centos7-install/
# serviceコマンド等がなくて困るので
yum -y install initscripts && yum clean all
# wgetを入れる
yum -y install wget
wget https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm
yum -y localinstall pgdg-centos10-10-2.noarch.rpm
yum -y install postgresql10-server
/usr/pgsql-10/bin/postgresql-10-setup initdb
systemctl enable postgresql-10
systemctl start postgresql-10
PostgreSQLサーバーが外から参照できるようにする(マスタのみ)
実際の作業では「つながらないじゃん」を繰り返して終盤にやった作業
https://qiita.com/YusukeHigaki/items/9bd0c21fbcc47e12b5c1
マスターとなるサーバー側だけで大丈夫です
vi /var/lib/pgsql/10/data/postgresql.conf
59行目~あたり。#を外して書き換える(試しなので全受け入れ)
listen_addresses = '*' # what IP address(es) to listen on;
# comma-separated list of addresses;
# defaults to 'localhost'; use '*' for all
port = 5432 # (change requires restart)
さらに接続できるクライアントを設定する
vi /var/lib/pgsql/10/data/pg_hba.conf
一番最後の似たようなのが書いてあるあたりにテキトーに
host all all all trust
こちらも試しなので全受け入れにしてますが、実際はADDRESS等を絞ったほうがいいと思います
再起動
service postgresql-10 restart
PostgreSQLのユーザー等の設定(M/S共通)
適当にmydbというデータベースに、test_dbというテーブルを作ってそれをレプリケーションするようにします
testユーザーが実行できるようにします。レプリケーションができるユーザーにする必要があります。
権限はテストなので適当
# su postgres
$ createdb mydb
$ psql mydb
mydb=# CREATE TABLE test_db (
id SERIAL,
name varchar(80)
);
mydb=# CREATE ROLE test WITH LOGIN REPLICATION PASSWORD 'hogehoge';
mydb=# GRANT ALL ON test_db TO test;
レプリケーションの設定
マスタ側
論理レプリケーションをするにあたって、
http://tkrd.hatenablog.com/entry/2017/04/23/223936
vi /var/lib/pgsql/10/data/postgresql.conf
180行目あたり
wal_level = logical # minimal, replica, or logical
max_replication_slotsあたりも触るべき?(触らなくてもとりあえず動いた)
service postgresql-10 restart
$ psql mydb
mydb=# CREATE PUBLICATION pub_srv1_test_db FOR TABLE test_db;
スレーブ側
別ホストとみなせるのでポートは5432でよい。
$ psql mydb
mydb=# CREATE SUBSCRIPTION sub_srv2_test_db CONNECTION 'dbname=mydb host=postgresql1 port=5432 user=test' PUBLICATION pub_srv1_test_db;
NOTICE: created replication slot "sub_srv2_test_db" on publisher
CREATE SUBSCRIPTION
この時点で接続を試みるため、接続設定がうまくいっていないとここでこける。
このあたり釈然としないものがいまのところあるが、とりあえず動いたのでよしとする・・・(?~~~
さすがにアレなので調べたら、pg_hba.confのtrustが理由らしい
https://www.postgresql.jp/document/10/html/auth-pg-hba-conf.html
```
host mydb test samenet password
```
こうするとpasswordが必要になる(同じネットワーク内なのでまあ平文でよいでしょ)
またmydbデータベースのみのtestユーザーによる接続の許可もついでに入れた
```
mydb=# CREATE SUBSCRIPTION sub_srv2_test_db CONNECTION 'dbname=mydb host=postgresql1 port=5432 user=test' PUBLICATION pub_srv1_test_db;
ERROR: could not connect to the publisher: fe_sendauth: no password supplied
mydb=# CREATE SUBSCRIPTION sub_srv2_test_db CONNECTION 'dbname=mydb host=postgresql1 port=5432 user=test password=hogehoge' PUBLICATION pub_srv1_test_db;
NOTICE: created replication slot "sub_srv2_test_db" on publisher
CREATE SUBSCRIPTION
```
### 試してみる
マスタ側
```sql
mydb=# insert into test_db (name) values('aaa');
```
スレーブ側
```sql
mydb=# select * from test_db;
id | name
----+------
1 | aaa
(1 row)
```
なんか動いた。
### その他
マスタ側で以下を実行してもスレーブは変わらない
```
truncate test_db;
```
スレーブ側でinsertすると
```
mydb=# insert into test_db (name) values('aaa');
mydb=# select * from test_db;
id | name
----+------
1 | aaa
1 | aaa
```
うーむ。まあスレーブ側は基本的には読み込みのみだからいいのだけど、id,nameともに値としてレプリケーションされるのね。
MySQLに慣れているのもあって、SERIALとsequenceテーブルの存在がなかなかにわかりにくい。
### 感想
PostgreSQL初めて触ったけど、古い情報が結構出てきて情報が調べにくいですね。。。
というか10のドキュメントに簡単に飛べないのどうなんよ・・・
https://www.postgresql.jp/document/