LoginSignup
3
0

More than 5 years have passed since last update.

DockerをつかってCentOS7上でPostgreSQLの論理レプリケーションを試す

Last updated at Posted at 2018-03-30

「実機サーバー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

試してみる

マスタ側

mydb=# insert into test_db (name) values('aaa');

スレーブ側

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/

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0