◇本稿の構成。
本稿ではストリーミング・レプリケーション方式を実装し、冗長化を行う為、前稿で作成したdb1サーバーをプライマリ側のホストとして使用し、新たにスタンバイ側のホストとしてdb2サーバーを追加します。
RDBMSに関するレプリケーション方式は幾つかあり、過去に当方が関わった案件ではheartbeatとDRBDを使用していましたが、個人的には余計なツールを増やす事に抵抗があった事と、結構面倒だった記憶があります。実際の安定性はこれらのツールを入れた方が高いのかも知れませんが、本稿ではPostgreSQL独自のレプリケーション方式を試してみます。
〇db1サーバー
・ホスト名:db1.stream.server
・アドレス:192.168.128.91/24
・DNS:192.168.128.101
・ゲートウェイ:192.168.128.1
〇db2サーバー
・ホスト名:db2.stream.server
・アドレス:192.168.128.92/24
・DNS:192.168.128.101
・ゲートウェイ:192.168.128.1
〇DNSサーバー
・ホスト名:host1.stream.server
・アドレス:192.168.128.101/24
・DNS:192.168.128.101
・ゲートウェイ:192.168.128.1
本稿で取り扱う仕組みは以下の図の様になります。
◇DNSサーバーの追加設定
・DNSサーバーの正引きゾーンファイルの設定追加。
末尾にdb2を追記します。
[root@host1 ~]# cp -p /var/named/stream.server.zone{,.20230205}
[root@host1 ~]# vi /var/named/stream.server.zone
$TTL 86400
@ IN SOA host1.stream.server. root.stream.server. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
IN NS host1.stream.server.
IN MX 10 mail1.stream.server.
IN MX 20 mail2.stream.server.
host1 IN A 192.168.128.101
host2 IN A 192.168.128.102
mail1 IN A 192.168.128.101
mail2 IN A 192.168.128.102
web1 IN A 192.168.128.100
nginx1 IN A 192.168.128.103
nginx2 IN A 192.168.128.103
db1 IN A 192.168.128.91
db2 IN A 192.168.128.92
・DNSサーバーの逆引きファイルを追加
db2.stream.server.を追記します。
[root@host1 ~]# cp -p /var/named/128.168.192.in-addr.arpa.zone{,.20230205}
[root@host1 ~]# vi /var/named/128.168.192.in-addr.arpa.zone
$TTL 86400
@ IN SOA host1.stream.server. root.stream.server. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
IN NS host1.stream.server.
IN A 255.255.255.0
101 IN PTR host1.stream.server.
102 IN PTR host2.stream.server.
101 IN PTR mail1.stream.server.
102 IN PTR mail2.stream.server.
100 IN PTR web1.stream.server.
103 IN PTR nginx1.stream.server.
103 IN PTR nginx2.stream.server.
91 IN PTR db1.stream.server.
92 IN PTR db2.stream.server.
[root@host1 ~]# named-checkconf -z
zone localhost.localdomain/IN: loaded serial 0
zone localhost/IN: loaded serial 0
zone 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa/IN: loaded serial 0
zone 1.0.0.127.in-addr.arpa/IN: loaded serial 0
zone 0.in-addr.arpa/IN: loaded serial 0
zone stream.server/IN: loaded serial 0
zone 128.168.192.in-addr.arpa/IN: loaded serial 0
[root@host1 ~]# systemctl reload named-chroot.service
[root@host1 ~]# systemctl is-active named-chroot.service
active
DNSサーバーの設定終了後、先ずはdb1(プライマリ)側の設定から行っていきます。
◇db1(プライマリ)側の設定
レプリケーションを実施する為にpostgresql.confの設定を変更します。
[postgres@db1 ~]$ cp -p /var/lib/pgsql/data/postgresql.conf{,.20230205}
[postgres@db1 ~]$ vi /var/lib/pgsql/data/postgresql.conf
(中略)
wal_level = replica
(中略)
#synchronous_standby_names = '' # この行を以下に変更します。
synchronous_standby_names = '*'
続いてpg_hba.confでレプリケーションを行うホストのIPアドレスを指定します。
[root@db1 ~]# cp -p /var/lib/pgsql/data/pg_hba.conf{,.20230205}
[root@db1 ~]# vi /var/lib/pgsql/data/pg_hba.conf
(中略)
# IPv4 local connections:
host all all 127.0.0.1/32 ident
host replication postgres 192.168.128.91/24 trust #←プライマリ側追記
host replication postgres 192.168.128.92/24 trust #←スタンバイ側追記
因みに上記「trust」は無条件で接続を許可する方式でパスワード無しで接続可能となります。
終了後、サービスを再起動し、設定を反映させます。
[root@db1 ~]# systemctl restart postgresql.service
[root@db1 ~]# systemctl is-active postgresql.service
active
◇db2(スタンバイ)側の設定
先ずはPostgreSQLのインストールを行います。
[root@db2 ~]# dnf install postgresql-server -y
(中略)
インストール済み:
postgresql-13.7-1.el9.x86_64 postgresql-private-libs-13.7-1.el9.x86_64
postgresql-server-13.7-1.el9.x86_64
完了しました!
この後、プライマリ側(db1)ではデータベースの初期化を行いましたが、スタンバイ側ではプライマリ側からデータをコピーする為にデータベースの初期化は行いません。以下の様にpg_basebackupを実行し、db2がスタンバイ側である事を認識させます。
[root@db2 ~]# sudo -u postgres -i
[postgres@db2 ~]$ pg_basebackup -h 192.168.128.91 -U postgres -D $PGDATA -X stream -P -R
33645/33645 kB (100%), 1/1 テーブル空間
次にpostgresql.confの設定を変更します。なお、古いバージョンではrecovery.confというファイルに分離されていましたが、現在ではpostgresql.confに統一されています。
[postgres@db2 ~]$ cp -p /var/lib/pgsql/data/postgresql.conf{,.20230205}
[postgres@db2 ~]$ vi /var/lib/pgsql/data/postgresql.conf
(中略)
primary_conninfo = 'user-postgres host-192.168.128.91 port-5432'
[postgres@db2 ~]$ exit
ログアウト
続いてサービスの有効化、及びファイアウォールの許可設定を行います。
[root@db2 ~]# systemctl enable postgresql.service --now
Created symlink /etc/systemd/system/multi-user.target.wants/postgresql.service → /usr/lib/systemd/system/postgresql.service.
[root@db2 ~]# firewall-cmd --add-service=postgresql
success
[root@db2 ~]# firewall-cmd --runtime-to-permanent
success
以上でストリーミング・レプリケーションの設定は終了しました。
スタンバイ側からプライマリ側で作成したデータベースへアクセスできるか確認します。
[root@db2 ~]# sudo -u postgres -i
[postgres@db2 ~]$ psql -l
データベース一覧
名前 | 所有者 | エンコーディング | 照合順序 | Ctype(変換演算子) |
アクセス権限
-----------+----------+------------------+-------------+-------------------+----
-------------------
joudai | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 |
postgres | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 |
template0 | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/
postgres +
| | | | | pos
tgres=CTc/postgres
template1 | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/
postgres +
| | | | | pos
tgres=CTc/postgres
(4 行)
[postgres@db2 ~]$ psql joudai
psql (13.7)
"help"でヘルプを表示します。
joudai=# SELECT * FROM ancient;
ancient_id | ancient_name | turns
------------+--------------+-------
1 | 古事記 | 3
2 | 日本書紀 | 30
3 | 先代旧事本紀 | 10
(3 行)
因みに作成などのクエリーの実行は、以下の実行結果の様に、リードオンリー以外のトランザクションは拒否されます。
joudai=# CREATE TABLE test(id INTEGER PRIMARY KEY);
ERROR: リードオンリーのトランザクションでは CREATE TABLE を実行できません
確認後、一旦joudaiへの接続を終了します。
joudai=# \q
◇スタンバイ側のホストから接続状態を確認
以下のコマンドで client_addr がスタンバイのIPアドレス、stateがstreaming、 sync_stateがsyncである事を確認します。
[root@db1 ~]# sudo -u postgres -i
[postgres@db1 ~]$ psql
psql (13.7)
"help"でヘルプを表示します。
postgres=# SELECT application_name, client_addr, backend_start, state, sync_stat
e FROM pg_stat_replication;
application_name | client_addr | backend_start | state |
sync_state
------------------+----------------+-------------------------------+-----------+
------------
walreceiver | 192.168.128.92 | 2023-02-05 00:03:27.428116+09 | streaming |
sync
(1 行)
postgres=# \q
[postgres@db1 ~]$
以上でPostgreSQLサーバーのストリーミング・レプリケーションは完成しました。
◇スタンバイ側のホストをプライマリに切り替える
続いてプライマリとスタンバイを切り替えるテストを行っていきます。
以下の様にスタンバイ側のホストにはstandby.signalファイルが存在します。
[postgres@db2 ~]$ exit
ログアウト
[root@db2 ~]# find / -iname "standby.signal"
/var/lib/pgsql/data/standby.signal
このファイルを以下のコマンドで削除する事により、スタンバイ側のホストがプライマリに切り替わります。
[root@db2 ~]# sudo -u postgres -i
[postgres@db2 ~]$ psql -c "SELECT pg_promote();"
pg_promote
------------
t
(1 行)
下記コマンドでstandby.signalファイルが削除された事を確認します。
[postgres@db2 ~]$ exit
ログアウト
[root@db2 ~]# find / -iname "standby.signal"
[root@db2 ~]# ←何も表示されない
◇旧プライマリ(現スタンバイ)ホストの再同期
スタンバイとプライマリの切り替えは行われましたが、現状では同期が行われていません。その為、現スタンバイ側(db1)でpg_backupを行い、データが同期された状態のスタンバイに戻します。
[root@db1 ~]# sudo -u postgres -i
[postgres@db1 ~]$ pg_ctl -D $PGDATA stop
サーバ停止処理の完了を待っています....完了
サーバは停止しました
[postgres@db1 ~]$ mv $PGDATA data-20230206
[postgres@db1 ~]$ pg_basebackup -h 192.168.128.92 -U postgres -D $PGDATA -X stream -P -R
33728/33728 kB (100%), 1/1 テーブル空間
[postgres@db1 ~]
[postgres@db1 ~]$ exit
ログアウト
[root@db1 ~]# cp -p /var/lib/pgsql/data/postgresql.conf{,.20230208}
[root@db1 ~]# vi /var/lib/pgsql/data/postgresql.conf
(中略)
primary_conninfo = 'user-postgres host-192.168.128.91 port-5432'
[root@db1 ~]# systemctl start postgresql.service
[root@db1 ~]# systemctl status postgresql.service
● postgresql.service - PostgreSQL database server
Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; prese>
(略)
再同期後、現プライマリ側(db2)からスタンバイのホストdb1が接続されている事を確認します。
[postgres@db2 ~]$ psql
psql (13.7)
"help"でヘルプを表示します。
postgres=# SELECT application_name, client_addr, backend_start, state, sync_state FROM pg_stat_replication;
application_name | client_addr | backend_start | state |
sync_state
------------------+----------------+-------------------------------+-----------+
------------
walreceiver | 192.168.128.91 | 2023-02-06 23:59:03.231457+09 | streaming |
sync
(1 行)