ラベル PostgreSQL の投稿を表示しています。 すべての投稿を表示
ラベル PostgreSQL の投稿を表示しています。 すべての投稿を表示
2024年7月15日月曜日

PostgreSQLのログ出力先と保管期間を設定する

PostgreSQLのデフォルト設定では、ログファイル/var/lib/pgsql/data/log/に、曜日単位で出力される。

# ls -l /var/lib/pgsql/data/log/
-rw-------. 1 postgres postgres    0  7月  5 00:00 postgresql-Fri.log
-rw-------. 1 postgres postgres    0  7月  8 00:00 postgresql-Mon.log
-rw-------. 1 postgres postgres    0  7月  6 00:00 postgresql-Sat.log
-rw-------. 1 postgres postgres    0  7月  7 00:00 postgresql-Sun.log
-rw-------. 1 postgres postgres    0  7月  4 00:00 postgresql-Thu.log
-rw-------. 1 postgres postgres    0  7月  9 00:00 postgresql-Tue.log
-rw-------. 1 postgres postgres 4943  7月 10 15:52 postgresql-Wed.log

デフォルト設定では、ログが1週間分しか保管されずログが上書きされてしまうことや、そもそもLinuxの標準のログ出力先である/var/log/ディレクトリに出力されていないことなど、管理面で問題がある。

そこで本記事では、PostgreSQLのログ出力設定を変更し、ログの出力先と保管期間の設定変更を行う。出力手順は大きく2つの方法があるため、両方の設定手順を記載する。

  • syslog経由で出力する方法
  • stderr経由で出力する方法 (デフォルト)

環境

  • OS : AlmaLinux 9.4
  • PostgreSQL : 13.14

ログ出力設定手順① (syslog)

1. ログ出力先のディレクトリを作成

ログ出力先のディレクトリを作成する。今回は、/var/log/postgresql/とした。

# mkdir /var/log/postgresql
# chown postgres:postgres /var/log/postgresql

# ls -ld /var/log/postgresql/
drwxr-xr-x. 2 postgres postgres 6  7月 14 17:24 /var/log/postgresql/

2. postgresql.confを修正

ログ出力先や出力時のファイル名を変更するため、postgresql.confを修正する。syslogのファシリティは任意でよいが、本記事ではlocal3を指定した。

# vi /var/lib/pgsql/data/postgresql.conf
------------------------------
# ログの出力先をsyslogに変更
#log_destination = 'stderr'
↓
log_destination = 'syslog'

# ログファイルのフォーマットをpostgresql.logに変更
log_filename = 'postgresql-%a.log'
   ↓
log_filename = 'postgresql.log'

# syslogの各種設定を追加
#syslog_facility = 'LOCAL0'
#syslog_ident = 'postgres'
#syslog_sequence_numbers = on
#syslog_split_messages = on
   ↓
syslog_facility = 'LOCAL3'
syslog_ident = 'postgres'
syslog_sequence_numbers = on
syslog_split_messages = on

3. rsyslog設定

PostgreSQLが出力したsyslogをログファイルに出力するよう、rsyslogの設定を行う。

rsyslog.confに以下行を追記する。先ほどのPostgreSQLの設定と合わせて、ファシリティはlocal3を指定する。

# vi /etc/rsyslog.conf
------------------------------
# Log PostgreSQL
local3.*                                                /var/log/postgres/postgres.log

4. 反映

設定を反映させるため、rsyslogとPostgreSQLを再起動する。

systemctl restart rsyslog
systemctl restart postgresql

PostgreSQLの再起動時にログが出力されていることを確認しておこう。

# cat /var/log/postgres/postgres.log
Jul 15 06:49:20 t1023zabi postgres[1540934]: [1-1] 2024-07-15 06:49:20.312 JST [1540934] LOG:  ログ出力をログ収集プロセスにリダイレクトしています
Jul 15 06:49:20 t1023zabi postgres[1540934]: [1-2] 2024-07-15 06:49:20.312 JST [1540934] ヒント:  ここからのログ出力はディレクトリ"/var/log/postgresql"に現れます。
Jul 15 06:49:20 t1023zabi postgres[1540934]: [2-1] 2024-07-15 06:49:20.312 JST [1540934] LOG:  標準エラー出力へのログ出力を終了しています
Jul 15 06:49:20 t1023zabi postgres[1540934]: [2-2] 2024-07-15 06:49:20.312 JST [1540934] ヒント:  この後のログ出力はログ配送先"syslog"に出力されます。
Jul 15 06:49:20 t1023zabi postgres[1540934]: [3-1] 2024-07-15 06:49:20.312 JST [1540934] LOG:  PostgreSQL 13.14 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 11.4.1 20230605 (Red Hat 11.4.1-2), 64-bit を起動しています
Jul 15 06:49:20 t1023zabi postgres[1540934]: [4-1] 2024-07-15 06:49:20.312 JST [1540934] LOG:  IPv6アドレス"::1"、ポート5432で待ち受けています
Jul 15 06:49:20 t1023zabi postgres[1540934]: [5-1] 2024-07-15 06:49:20.312 JST [1540934] LOG:  IPv4アドレス"127.0.0.1"、ポート5432で待ち受けています
Jul 15 06:49:20 t1023zabi postgres[1540934]: [6-1] 2024-07-15 06:49:20.313 JST [1540934] LOG:  Unixソケット"/var/run/postgresql/.s.PGSQL.5432"で待ち受けています
Jul 15 06:49:20 t1023zabi postgres[1540934]: [7-1] 2024-07-15 06:49:20.313 JST [1540934] LOG:  Unixソケット"/tmp/.s.PGSQL.5432"で待ち受けています
Jul 15 06:49:20 t1023zabi postgres[1540936]: [8-1] 2024-07-15 06:49:20.315 JST [1540936] LOG:  データベースシステムは 2024-07-15 06:49:20 JST にシャットダウンしました
Jul 15 06:49:20 t1023zabi postgres[1540934]: [8-1] 2024-07-15 06:49:20.317 JST [1540934] LOG:  データベースシステムの接続受け付け準備が整いました

5. logrotate設定

出力されたログに対してlogrotateの機能を用いてログローテートするよう設定する。

今回は、毎日ログローテートを行い31日間保管する設定とした。容量削減のため、翌々日のログから圧縮する設定としている。また、ログファイルの切り替わり時にログを正常に出力できるよう、ログローテート時にrsyslogサービスのリロード(kill -HUP)を設定した。

# vi /etc/logrotate.d/postgresql
------------------------------
/var/log/postgresql/*.log {
  daily
  rotate 31
  dateext
  compress
  delaycompress
  create 644 postgres postgres
  missingok
  sharedscripts
  postrotate
    /usr/bin/systemctl -s HUP kill rsyslog.service >/dev/null 2>&1 || true
  endscript
}

以上で、syslogを用いたPostgreSQLのログ出力設定手順は完了となる。

ログ出力設定手順② (stderr出力パターン)

1. ログ出力先のディレクトリを作成

ログ出力先のディレクトリを作成する。今回は、/var/log/postgresql/とした。

# mkdir /var/log/postgresql
# chown postgres:postgres /var/log/postgresql

# ls -ld /var/log/postgresql/
drwxr-xr-x. 2 postgres postgres 6  7月 14 17:24 /var/log/postgresql/

2. postgresql.confを修正

ログ出力先や出力時のファイル名を変更するため、postgresql.confを修正する。

# vi /var/lib/pgsql/data/postgresql.conf
------------------------------
# ログディレクトリを/var/log/postgresql/に変更
#log_directory = 'log'
   ↓
log_directory = '/var/log/postgresql'

# ログファイルのフォーマットをpostgresql.logに変更
log_filename = 'postgresql-%a.log'
   ↓
log_filename = 'postgresql.log'

# PostgreSQLの機能のログローテーションを無効化
log_rotation_age = 1d
   ↓
log_rotation_age = 0

3. 設定反映

PostgreSQLを再起動して、設定反映を行う。

# systemctl restart postgresql

PostgreSQLの再起動時に起動ログが出力されるので、問題なく新しいディレクトリでファイルに出力されていることを確認しておこう。

# ls -l /var/log/postgresql/
-rw-------. 1 postgres postgres 893  7月 14 17:27 postgresql-20240714.log

# cat /var/log/postgresql/postgresql-20240714.log
2024-07-14 17:27:47.517 JST [1507397] LOG:  PostgreSQL 13.14 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 11.4.1 20230605 (Red Hat 11.4.1-2), 64-bit を起動しています
2024-07-14 17:27:47.517 JST [1507397] LOG:  IPv6アドレス"::1"、ポート5432で待ち受けています
2024-07-14 17:27:47.517 JST [1507397] LOG:  IPv4アドレス"127.0.0.1"、ポート5432で待ち受けています
2024-07-14 17:27:47.518 JST [1507397] LOG:  Unixソケット"/var/run/postgresql/.s.PGSQL.5432"で待ち受けています
2024-07-14 17:27:47.518 JST [1507397] LOG:  Unixソケット"/tmp/.s.PGSQL.5432"で待ち受けています
2024-07-14 17:27:47.519 JST [1507399] LOG:  データベースシステムは 2024-07-14 17:27:47 JST にシャットダウンしました
2024-07-14 17:27:47.522 JST [1507397] LOG:  データベースシステムの接続受け付け準備が整いました

4. logrotate設定

PostgreSQLはログローテート機能はあるが、保管期間を超えたログを削除する機能がないため、logrotateの機能を用いてログローテートを実装する。

今回は、毎日ログローテートを行い31日間保管する設定とした。容量削減のため、翌々日のログから圧縮する設定としている。また、ログファイルの切り替わり時にログを正常に出力できるよう、copytruncateオプションを設定している。

# vi /etc/logrotate.d/postgresql
------------------------------
/var/log/postgresql/*.log {
  daily
  rotate 31
  dateext
  compress
  delaycompress
  create 0640 postgres postgres
  missingok
  copytruncate
}

以上で、stderrを用いたPostgreSQLのログ出力設定手順は完了となる。

参考

2023年9月16日土曜日

Pgpool-IIを使ってフェイルオーバーとオンラインリカバリを実行する

前回、Pgpool-IIを使ってPostgreSQLのストリーミングレプリケーション構成を管理するための構築手順を記載した。

Pgpool-IIでは、定期的にPostgreSQLに対してヘルスチェックを実行しており、マスターのDB停止を契機としてフェイルオーバー(スタンバイDBをマスターDBに昇格)を実行できる。

また、フェイルオーバー後に旧マスターをスタンバイDBとしてストリーミングレプリケーション構成に復旧させることもできる。この作業は、マスターDBのI/Oを停止させることなく実行できることから「オンラインリカバリ」と呼ばれる。

Pgpool-IIのフェイルオーバーやオンラインリカバリは、スクリプトにて実装される。本記事では、Pgpool-IIを使ってフェイルオーバーとオンラインリカバリを実行するための手順を記載する。

環境

OSはRHEL互換OSであるAlmaLinuxを利用し、パッケージ提供されているPostgreSQLを利用する。

  • OS : AlmaLinux release 8.8
  • PostgreSQL : 15.2
  • Pgpool-II : 4.4.4

マスターとスタンバイの2台にPostgreSQLをインストールし、ストリーミングレプリケーションを構成する。ホスト名やIPアドレスは以下図を参照いただきたい。

今回はPgpool-II導入サーバ、マスターDBサーバ、スタンバイDBサーバで実施する作業が異なる。そのため、本記事で記載するプロンプトを以下の通り記載し、作業対象が判別できるようにした。

プロンプト ユーザー 対象
[Pgpool]# root Pgpool-II導入サーバのみ実施
[Master/Standby]# root マスターとスタンバイ両方で実施
[Master]# root マスターのみ実施
[Standby]# root スタンバイのみ実施
[Pgpool]$ postgres Pgpool-II導入サーバのみ実施
[Master/Standby]$ postgres マスターとスタンバイ両方で実施
[Master]$ postgres マスターのみ実施
[Standby]$ postgres スタンバイのみ実施

スクリプト配置

Pgpool-IIのサンプルスクリプトは/etc/pgpool-II/sample_scripts/ディレクトリに存在する。そちらを使用してもよいが、不要な処理を削除してシンプルにしたいため、サンプルスクリプトは参考にしつつオリジナルのスクリプトを作成した。

以下サンプルスクリプトの一覧となる。

[Pgpool]$ ls -1 /etc/pgpool-II/sample_scripts/
aws_eip_if_cmd.sh.sample
aws_rtb_if_cmd.sh.sample
escalation.sh.sample
failover.sh.sample
follow_primary.sh.sample
pgpool_remote_start.sample
recovery_1st_stage.sample
replication_mode_recovery_1st_stage.sample
replication_mode_recovery_2nd_stage.sample

1. フェイルオーバー用スクリプトの作成・配置

フェイルオーバー用スクリプトの処理の流れを記載する。

  1. 引数を変数に代入する。
  2. 実行ユーザーをpostgresとして設定する。
  3. 昇格対象となるスタンバイDB(NEW_MAIN_NODE_HOST)にSSH接続するための、SSHコマンド文を作成する。
  4. スタンバイDBをマスターDBとして昇格させる。
  5. synchronous_standby_names='*'が設定されている場合、レプリケーション完了までDBが応答を返すことができず、実質更新ができなくなる。そのため、synchronous_standby_names=''のように空白設定に変更する。
  6. 設定反映のため、昇格したDBの設定をリロードする。

実際のスクリプトを以下に記載する。本スクリプトは、Pgpool-II導入サーバの/var/lib/pgsqlに配置する。

failover.sh

#!/bin/bash
# This script is run by failover_command.

set -eu
set -o xtrace

# Special values:
# 1)  %d = failed node id
# 2)  %h = failed node hostname
# 3)  %p = failed node port number
# 4)  %D = failed node database cluster path
# 5)  %m = new main node id
# 6)  %H = new main node hostname
# 7)  %M = old main node id
# 8)  %P = old primary node id
# 9)  %r = new main port number
# 10) %R = new main database cluster path
# 11) %N = old primary node hostname
# 12) %S = old primary node port number
# 13) %% = '%' character

FAILED_NODE_ID="$1"
FAILED_NODE_HOST="$2"
FAILED_NODE_PORT="$3"
FAILED_NODE_PGDATA="$4"
NEW_MAIN_NODE_ID="$5"
NEW_MAIN_NODE_HOST="$6"
OLD_MAIN_NODE_ID="$7"
OLD_PRIMARY_NODE_ID="$8"
NEW_MAIN_NODE_PORT="$9"
NEW_MAIN_NODE_PGDATA="${10}"
OLD_PRIMARY_NODE_HOST="${11}"
OLD_PRIMARY_NODE_PORT="${12}"

POSTGRESQL_STARTUP_USER=postgres
SSH_KEY_FILE=id_rsa
SSH_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/${SSH_KEY_FILE}"
SSH_CMD="ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@${NEW_MAIN_NODE_HOST}"

${SSH_CMD} /usr/bin/pg_ctl promote -D ${NEW_MAIN_NODE_PGDATA} -w
${SSH_CMD} "sed -ie \"s/^synchronous_standby_names = '\*'/synchronous_standby_names = ''/g\" ${NEW_MAIN_NODE_PGDATA}/postgresql.conf"
${SSH_CMD} /usr/bin/pg_ctl reload -D ${NEW_MAIN_NODE_PGDATA} -w

exit 0

2. オンラインリカバリ用スクリプトの作成・配置

オンラインリカバリ用スクリプトの処理の流れを記載する。

  1. 引数を変数に代入する。
  2. レプリケーション用のDBユーザーをdbrepl、実行ユーザーをpostgresとして設定する。
  3. リカバリ対象となるスタンバイDB(DEST_NODE_HOST)にSSH接続するための、SSHコマンド文を作成する。
  4. スタンバイDBのデータ領域を削除する。
  5. pg_basebackupコマンドを使って、マスターDBのデータをスタンバイDBにコピー(ベースバックアップ)を行う。
  6. スタンバイDBとして動作させるため、standby.signalファイルを生成する。
  7. postgresql.confに含まれるスタンバイDBのホスト名をマスターDBのホスト名に入れ替える。
  8. application_nameの設定値をスタンバイDBのホスト名に変更する。
  9. マスターDBにてフェイルオーバー時に変更したsynchronous_standby_namesの設定値をsynchronous_standby_names='*'に戻し、レプリケーションを再開する。
  10. 設定反映のため、昇格したDBの設定をリロードする。

以下のスクリプトをPgpool-IIの管理対象となるDBサーバーのデータ領域(通常は/var/lib/pgsql/data)に配置する。

replication_mode_recovery_1st_stage

#!/bin/bash
# This script is executed by "recovery_1st_stage" to recovery a Standby node.

set -eu
set -o xtrace

MAIN_NODE_PGDATA="$1"              # main node dabatase cluster path
DEST_NODE_HOST="$2"                # hostname of the DB node to be recovered
DEST_NODE_PGDATA="$3"              # database cluster path of the DB node to be recovered
MAIN_NODE_PORT="$4"                # main node port number
DEST_NODE_ID="$5"                  # node id of the DB node to be recovered
DEST_NODE_PORT="$6"                # port number of the DB node to be recovered
MAIN_NODE_HOST="$7"                # main node hostname

REPLUSER=dbrepl
POSTGRESQL_STARTUP_USER=postgres
SSH_KEY_FILE=id_rsa
SSH_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/${SSH_KEY_FILE}"
SSH_CMD="ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@${DEST_NODE_HOST}"

# Standby側(オンラインリカバリされる側)の処理
${SSH_CMD} "[ -d ${DEST_NODE_PGDATA} ] && rm -rf ${DEST_NODE_PGDATA}"
${SSH_CMD} "/usr/bin/pg_basebackup -D ${DEST_NODE_PGDATA} -h ${MAIN_NODE_HOST} -X stream -c fast -U ${REPLUSER} -p ${MAIN_NODE_PORT} -w"
${SSH_CMD} "touch ${DEST_NODE_PGDATA}/standby.signal"

${SSH_CMD} "sed -ie \"s#${DEST_NODE_HOST}#${MAIN_NODE_HOST}#g\" ${DEST_NODE_PGDATA}/postgresql.conf"
${SSH_CMD} "sed -ie \"s#application_name=${MAIN_NODE_HOST}#application_name=${DEST_NODE_HOST}#g\" ${DEST_NODE_PGDATA}/postgresql.conf"

# Master側の処理
sed -ie "s/^synchronous_standby_names = ''/synchronous_standby_names = '\*'/g" ${MAIN_NODE_PGDATA}/postgresql.conf
/usr/bin/pg_ctl reload -D ${MAIN_NODE_PGDATA} -w

exit 0

3. オンラインリカバリ後のスタンバイDB起動スクリプトの作成・配置

オンラインリカバリ後にスタンバイDB起動は、別のスクリプトとして用意する必要がある。本スクリプトの処理の流れを記載する。

  1. 引数を変数に代入する。
  2. 実行ユーザーをpostgresとして設定する。
  3. リカバリ対象となるスタンバイDB(DEST_NODE_HOST)にSSH接続するための、SSHコマンド文を作成する。
  4. スタンバイDB起動する。

以下のスクリプトをPgpool-IIの管理対象となるDBサーバーのデータ領域(通常は/var/lib/pgsql/data)に配置する。

pgpool_remote_start

#!/bin/bash
# This script is run after recovery_1st_stage to start Standby node.

set -eu
set -o xtrace

DEST_NODE_HOST="$1"
DEST_NODE_PGDATA="$2"

POSTGRESQL_STARTUP_USER=postgres
SSH_KEY_FILE=id_rsa
SSH_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/${SSH_KEY_FILE}"
SSH_CMD="ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@${DEST_NODE_HOST}"

# DB起動
${SSH_CMD} "/usr/bin/pg_ctl start -D ${DEST_NODE_PGDATA} -w -l /dev/null"

exit 0

フェイルオーバー確認

1. 事前状態確認

それでは実際にフェイルオーバーをさせてみる。まずは、Pgpool-IIの状態を確認する。node_id: 0がprimary、node_id: 1がstandbyとなっている。

[Pgpool]$ psql -p 9999 -x -c "show pool_nodes"
-[ RECORD 1 ]----------+--------------------
node_id                | 0
hostname               | t1117psgl
port                   | 5432
status                 | up
pg_status              | up
lb_weight              | 0.500000
role                   | primary
pg_role                | primary
select_cnt             | 0
load_balance_node      | false
replication_delay      | 0
replication_state      |
replication_sync_state |
last_status_change     | 2023-08-26 23:31:00
-[ RECORD 2 ]----------+--------------------
node_id                | 1
hostname               | t1118psgl
port                   | 5432
status                 | up
pg_status              | up
lb_weight              | 0.500000
role                   | standby
pg_role                | standby
select_cnt             | 0
load_balance_node      | true
replication_delay      | 0
replication_state      | streaming
replication_sync_state | sync
last_status_change     | 2023-08-26 23:31:00

2. マスター側のDBを停止

マスターDBとなるnode_id: 0のDBを停止する。

[Master]# systemctl stop postgresql

3. 実行後ログ確認

Pgpool-IIのログ(/var/log/pgpool_log/pgpool-*.log)に以下の通り出力される。failover.sh実行ログがそのまま出力されていることがわかる。

[Pgpool]$ cat /var/log/pgpool_log/pgpool-Sun.log

~(中略)~

2023-08-27 11:21:30.902: main pid 8071: LOG:  === Starting degeneration. shutdown host t1117psgl(5432) ===
2023-08-27 11:21:30.903: main pid 8071: LOG:  Restart all children
2023-08-27 11:21:30.903: main pid 8071: LOG:  execute command: /var/lib/pgsql/failover.sh  0 t1117psgl  5432 /var/lib/pgsql/data  1 t1118psgl 0 0 5432 /var/lib/pgsql/data t1117psgl 5432
+ FAILED_NODE_ID=0
+ FAILED_NODE_HOST=t1117psgl
+ FAILED_NODE_PORT=5432
+ FAILED_NODE_PGDATA=/var/lib/pgsql/data
+ NEW_MAIN_NODE_ID=1
+ NEW_MAIN_NODE_HOST=t1118psgl
+ OLD_MAIN_NODE_ID=0
+ OLD_PRIMARY_NODE_ID=0
+ NEW_MAIN_NODE_PORT=5432
+ NEW_MAIN_NODE_PGDATA=/var/lib/pgsql/data
+ OLD_PRIMARY_NODE_HOST=t1117psgl
+ OLD_PRIMARY_NODE_PORT=5432
+ POSTGRESQL_STARTUP_USER=postgres
+ SSH_KEY_FILE=id_rsa
+ SSH_OPTIONS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa'
+ SSH_CMD='ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa postgres@t1118psgl'
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1118psgl /usr/bin/pg_ctl promote -D /var/lib/pgsql/data -w
Warning: Permanently added 't1118psgl,192.168.11.118' (ECDSA) to the list of known hosts.
サーバーの昇格を待っています....完了
サーバーは昇格しました
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1118psgl 'sed -ie "s/^synchronous_standby_names = '\''\*'\''/synchronous_standby_names = '\'''\''/g" /var/lib/pgsql/data/postgresql.conf'
Warning: Permanently added 't1118psgl,192.168.11.118' (ECDSA) to the list of known hosts.
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1118psgl /usr/bin/pg_ctl reload -D /var/lib/pgsql/data -w
Warning: Permanently added 't1118psgl,192.168.11.118' (ECDSA) to the list of known hosts.
サーバーにシグナルを送信しました
+ exit 0
2023-08-27 11:21:31.954: main pid 8071: LOG:  find_primary_node_repeatedly: waiting for finding a primary node
2023-08-27 11:21:31.962: main pid 8071: LOG:  find_primary_node: primary node is 1
2023-08-27 11:21:31.962: main pid 8071: LOG:  failover: set new primary node: 1
2023-08-27 11:21:31.962: main pid 8071: LOG:  failover: set new main node: 1
2023-08-27 11:21:31.965: main pid 8071: LOG:  === Failover done. shutdown host t1117psgl(5432) ===

4. 事後状態確認

Pgpool-IIにてフェイルオーバー後の状態確認を行う。以下の通り、node_id: 1がprimaryに昇格し、node_id: 0がstandbyかつステータスがdownとなっていることが確認できる。

[Pgpool]$ psql -p 9999 -x -c "show pool_nodes"
-[ RECORD 1 ]----------+--------------------
node_id                | 0
hostname               | t1117psgl
port                   | 5432
status                 | down   ←★downに変化している
pg_status              | down   ←★downに変化している
lb_weight              | 0.500000
role                   | standby
pg_role                | unknown ←★unknownになっている
select_cnt             | 0
load_balance_node      | false
replication_delay      | 0
replication_state      |
replication_sync_state |
last_status_change     | 2023-08-27 11:21:31
-[ RECORD 2 ]----------+--------------------
node_id                | 1
hostname               | t1118psgl
port                   | 5432
status                 | up
pg_status              | up
lb_weight              | 0.500000
role                   | primary ←★マスター(=primary)に昇格
pg_role                | primary ←★マスター(=primary)に昇格
select_cnt             | 0
load_balance_node      | true
replication_delay      | 0
replication_state      |
replication_sync_state |
last_status_change     | 2023-08-27 11:21:31

オンラインリカバリ

1. オンラインリカバリ実行

オンラインリカバリはpcp_recovery_node -n [リカバリ対象のDBのnode_id]で実行する。今回は、node_id: 0をスタンバイDBとして復旧させることから、以下の通りコマンドを実行する。Command Successfulと表示されれば、オンラインリカバリ成功となる。

[Pgpool]$ pcp_recovery_node -n 0
Password:
pcp_recovery_node -- Command Successful

2. 実行後ログ確認

マスター側のPostgreSQLのログに、以下の通りスクリプト実行結果が出力される。

[Master]$ cat /var/lib/pgsql/data/log/postgresql-Sun.log

~(中略)~

2023-08-27 11:23:07.101 JST [7329] LOG:  checkpoint complete: wrote 957 buffers (5.8%); 0 WAL file(s) added, 0 removed, 0 recycled; write=95.410 s, sync=0.063 s, total=95.475 s; sync files=252, longest=0.063 s, average=0.001 s; distance=16036 kB, estimate=16662 kB
+ MAIN_NODE_PGDATA=/var/lib/pgsql/data
+ DEST_NODE_HOST=t1117psgl
+ DEST_NODE_PGDATA=/var/lib/pgsql/data
+ MAIN_NODE_PORT=5432
+ DEST_NODE_ID=0
+ DEST_NODE_PORT=5432
+ MAIN_NODE_HOST=t1118psgl
+ REPLUSER=dbrepl
+ POSTGRESQL_STARTUP_USER=postgres
+ SSH_KEY_FILE=id_rsa
+ SSH_OPTIONS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa'
+ SSH_CMD='ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa postgres@t1117psgl'
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1117psgl '[ -d /var/lib/pgsql/data ] && rm -rf /var/lib/pgsql/data'
Warning: Permanently added 't1117psgl,192.168.11.117' (ECDSA) to the list of known hosts.
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1117psgl '/usr/bin/pg_basebackup -D /var/lib/pgsql/data -h t1118psgl -X stream -c fast -U dbrepl -p 5432 -w'
Warning: Permanently added 't1117psgl,192.168.11.117' (ECDSA) to the list of known hosts.
2023-08-27 11:23:18.370 JST [7329] LOG:  checkpoint starting: immediate force wait
2023-08-27 11:23:18.388 JST [7329] LOG:  checkpoint complete: wrote 4 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.001 s, sync=0.001 s, total=0.019 s; sync files=2, longest=0.001 s, average=0.001 s; distance=16383 kB, estimate=16634 kB
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1117psgl 'touch /var/lib/pgsql/data/standby.signal'
Warning: Permanently added 't1117psgl,192.168.11.117' (ECDSA) to the list of known hosts.
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1117psgl 'sed -ie "s#^primary_conninfo =.*#primary_conninfo = '\''application_name=t1117psgl user=dbrepl passfile='\'''\''/var/lib/pgsql/.pgpass'\'''\'' host=t1118psgl port=5432'\''#g" /var/lib/pgsql/data/postgresql.conf'
Warning: Permanently added 't1117psgl,192.168.11.117' (ECDSA) to the list of known hosts.
+ sed -ie 's/^synchronous_standby_names = '\'''\''/synchronous_standby_names = '\''\*'\''/g' /var/lib/pgsql/data/postgresql.conf
+ /usr/bin/pg_ctl reload -D /var/lib/pgsql/data -w
server signaled
2023-08-27 11:23:18.833 JST [7327] LOG:  received SIGHUP, reloading configuration files
+ exit 0
2023-08-27 11:23:18.833 JST [7327] LOG:  parameter "synchronous_standby_names" changed to "*"
+ DEST_NODE_HOST=t1117psgl
+ DEST_NODE_PGDATA=/var/lib/pgsql/data
+ POSTGRESQL_STARTUP_USER=postgres
+ SSH_KEY_FILE=id_rsa
+ SSH_OPTIONS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa'
+ SSH_CMD='ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa postgres@t1117psgl'
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1117psgl '/usr/bin/pg_ctl start -D /var/lib/pgsql/data -w -l /dev/null'
Warning: Permanently added 't1117psgl,192.168.11.117' (ECDSA) to the list of known hosts.
waiting for server to start.... done
server started
+ exit 0
2023-08-27 11:23:19.606 JST [19019] LOG:  standby "t1117psgl" is now a synchronous standby with priority 1
2023-08-27 11:23:19.606 JST [19019] STATEMENT:  START_REPLICATION 0/6000000 TIMELINE 2

Pgpool-IIのログ(/var/log/pgpool_log/pgpool-*.log)に以下の通り出力される。

2023-08-27 11:23:17.984: pcp_child pid 9523: LOG:  starting recovering node 0
2023-08-27 11:23:17.996: pcp_child pid 9523: LOG:  executing recovery
2023-08-27 11:23:17.996: pcp_child pid 9523: DETAIL:  starting recovery command: "SELECT pgpool_recovery('replication_mode_recovery_1st_stage', 't1117psgl', '/var/lib/pgsql/data', '5432', 0, '5432', 't1118psgl')"
2023-08-27 11:23:17.996: pcp_child pid 9523: LOG:  executing recovery
2023-08-27 11:23:17.996: pcp_child pid 9523: DETAIL:  disabling statement_timeout
2023-08-27 11:23:18.834: pcp_child pid 9523: LOG:  node recovery, 1st stage is done
2023-08-27 11:23:19.411: pcp_child pid 9523: LOG:  checking if postmaster is started
2023-08-27 11:23:19.411: pcp_child pid 9523: DETAIL:  trying to connect to postmaster on hostname:t1117psgl database:postgres user:postgres (retry 0 times)
2023-08-27 11:23:19.422: pcp_child pid 9523: LOG:  node recovery, node: 0 restarted
2023-08-27 11:23:19.422: pcp_child pid 9523: LOG:  received failback request for node_id: 0 from pid [9523]
2023-08-27 11:23:19.422: pcp_child pid 9523: LOG:  signal_user1_to_parent_with_reason(0)
2023-08-27 11:23:19.422: main pid 8071: LOG:  Pgpool-II parent process received SIGUSR1
2023-08-27 11:23:19.422: main pid 8071: LOG:  Pgpool-II parent process has received failover request
2023-08-27 11:23:19.422: main pid 8071: LOG:  === Starting fail back. reconnect host t1117psgl(5432) ===
2023-08-27 11:23:19.422: main pid 8071: LOG:  Node 1 is not down (status: 2)
2023-08-27 11:23:19.422: main pid 8071: LOG:  Do not restart children because we are failing back node id 0 host: t1117psgl port: 5432 and we are in streaming replication mode and not all backends were down
2023-08-27 11:23:19.422: main pid 8071: LOG:  find_primary_node_repeatedly: waiting for finding a primary node
2023-08-27 11:23:19.435: main pid 8071: LOG:  find_primary_node: standby node is 0
2023-08-27 11:23:19.435: main pid 8071: LOG:  find_primary_node: primary node is 1
2023-08-27 11:23:19.435: main pid 8071: LOG:  failover: set new primary node: 1
2023-08-27 11:23:19.435: main pid 8071: LOG:  failover: set new main node: 0
2023-08-27 11:23:19.435: main pid 8071: LOG:  === Failback done. reconnect host t1117psgl(5432) ===
2023-08-27 11:23:19.435: sr_check_worker pid 9518: LOG:  worker process received restart request
2023-08-27 11:23:19.436: pcp_child pid 9523: LOG:  recovery done

3. 事後状態確認

オンラインリカバリ後の状態確認を行う。node_id: 0がstandbyかつステータスがupになっており、復旧していることが確認できる。

[Pgpool]$ psql -p 9999 -x -c "show pool_nodes"
-[ RECORD 1 ]----------+--------------------
node_id                | 0
hostname               | t1117psgl
port                   | 5432
status                 | up    ←★upに変化している
pg_status              | up    ←★upに変化している
lb_weight              | 0.500000
role                   | standby
pg_role                | standby  ←★standbyに変化している
select_cnt             | 0
load_balance_node      | true
replication_delay      | 0
replication_state      | streaming ←★streamingとなっている
replication_sync_state | sync    ←★syncステータスとなっている
last_status_change     | 2023-08-27 11:23:29
-[ RECORD 2 ]----------+--------------------
node_id                | 1
hostname               | t1118psgl
port                   | 5432
status                 | up
pg_status              | up
lb_weight              | 0.500000
role                   | primary
pg_role                | primary
select_cnt             | 0
load_balance_node      | false
replication_delay      | 0
replication_state      |
replication_sync_state |
last_status_change     | 2023-08-27 11:21:31

以上で、Pgpool-IIを使ってフェイルオーバーとオンラインリカバリを実行するための手順は完了となる。

2023年9月9日土曜日

Pgpool-IIを使ってPostgreSQL (ストリーミングレプリケーション構成) を管理する

PostgreSQLのストリーミングレプリケーションは、PostgreSQL単体では障害検知や自動フェイルオーバーといった機能はなく、他のMWにて制御する必要がある。

PostgreSQLを制御できるMWとしてPacemakerやPgpool-IIなどがある。本記事では、Pgpool-IIを使ってPostgreSQL (ストリーミングレプリケーション構成) を管理するための構築手順を記載する。

環境

OSはRHEL互換OSであるAlmaLinuxを利用し、パッケージ提供されているPostgreSQLを利用する。

  • OS : AlmaLinux release 8.8
  • PostgreSQL : 15.2
  • Pgpool-II : 4.4.4

マスターとスタンバイの2台にPostgreSQLをインストールし、ストリーミングレプリケーションを構成する。ホスト名やIPアドレスは以下図を参照いただきたい。

今回はPgpool-II導入サーバ、マスターDBサーバ、スタンバイDBサーバで実施する作業が異なる。そのため、本記事で記載するプロンプトを以下の通り記載し、作業対象が判別できるようにした。

プロンプト ユーザー 対象
[Pgpool]# root Pgpool-II導入サーバのみ実施
[Master/Standby]# root マスターとスタンバイ両方で実施
[Master]# root マスターのみ実施
[Standby]# root スタンバイのみ実施
[Pgpool]$ postgres Pgpool-II導入サーバのみ実施
[Master/Standby]$ postgres マスターとスタンバイ両方で実施
[Master]$ postgres マスターのみ実施
[Standby]$ postgres スタンバイのみ実施

PostgreSQLをストリーミングレプリケーションで構成する

PostgreSQLをストリーミングレプリケーションで構成する手順は、以前記載した以下記事を参照いただきたい。

Pgpool-II構成手順概要

Pgpool-IIを構成する手順の概要を以下に図示する。

①Pgpool-IIインストール

1. Pgpool-IIインストール

Pgpool-IIはリポジトリ登録を行うことで、dnfを用いてインストールすることができる。DBとの接続確認にpsqlコマンドを多用するため、postgresqlパッケージも導入する。

[Pgpool]# rpm -ivh https://www.pgpool.net/yum/rpms/4.4/redhat/rhel-8-x86_64/pgpool-II-release-4.4-1.noarch.rpm
[Pgpool]# dnf module enable postgresql:15 -y
[Pgpool]# dnf install pgpool-II-pg15 postgresql -y

2. postgresユーザーのパスワードを変更

Pgpool-IIの操作は原則postgresユーザーにて操作する。パッケージインストール後にpostgresユーザーのパスワードを設定しておこう。

[Pgpool]# passwd postgres
[Pgpool]# mkdir /var/lib/pgsql
[Pgpool]# chown postgres:postgres /var/lib/pgsql

3. hostsを登録

Pgpool/Master/Standbyのホスト名とIPアドレスをお互いにhostsファイルへ登録しておく。これは、後程レプリケーションの設定の際にホスト名による登録をするために必要となる。

[Pgpool/Master/Standby]# vi /etc/hosts
192.168.11.116   t1116pgpl
192.168.11.117   t1117psgl
192.168.11.118   t1118psgl

4. UNIXソケット用ディレクトリ作成

Pgpool-IIのUNIXソケットで使用するディレクトリは、デフォルトで/run/postgresqlとなる(pgpool.confにて設定変更可能)。ただし、このディレクトリは存在しないため起動に失敗することから、ディレクトリの作成及び起動時に自動でディレクトリを作成するよう/etc/tmpfiles.d/pgpool.confを設定しておく。

[Pgpool]# mkdir /run/postgresql
[Pgpool]# chown postgres:postgres /run/postgresql
[Pgpool]# vi /etc/tmpfiles.d/pgpool.conf
d /run/postgresql 0755 postgres postgres

②Pgpool-II設定

1. Pgpool-II設定 (pgpool.conf設定)

Pgpool-IIの設定ファイルは/etc/pgpool-II/pgpool.confとなる。本設定ファイルの設定箇所を以下に記載する。

設定項目 設定内容
backend_clustering_mode ストリーミングレプリケーションを構成するためstreaming_replicationを設定する。
listen_addresses DBが接続を受け付けるIPアドレスを指定する。サーバが持つすべてのIPアドレスで接続を許可する場合は、*を指定する。
port デフォルトの9999で設定する。
backend_hostname0 管理対象のDB(マスター)のホスト名を設定する。
backend_port0 管理対象のDB(マスター)の接続ポート番号を設定する。デフォルトであれば、5432を設定する。
backend_weight0 管理対象のDB(マスター)への参照アクセスの重みづけを行う。均等にアクセスさせる場合は1を設定する。
backend_data_directory0 管理対象のDB(マスター)のPostgreSQLのデータ領域のパスを設定する。デフォルトであれば、/var/lib/pgsql/dataを設定する。
backend_flag0 管理対象のDB(マスター)のPgpool-IIの挙動の設定となる。Pgpool-IIからフェイルオーバーや切り離しを可能とするデフォルトのALLOW_TO_FAILOVERを設定すれば通常問題ないだろう。
backend_application_name0 管理対象のDB(マスター)にてストリーミングレプリケーションを確認した際に設定されるapplication_nameを設定する。ここはbackend_hostname0で設定したホスト名を指定する。
backend_hostname1 管理対象のDB(スタンバイ)のホスト名を設定する。
backend_port1 管理対象のDB(スタンバイ)の接続ポート番号を設定する。デフォルトであれば、5432を設定する。
backend_weight1 管理対象のDB(スタンバイ)への参照アクセスの重みづけを行う。均等にアクセスさせる場合は1を設定する。
backend_data_directory1 管理対象のDB(スタンバイ)のPostgreSQLのデータ領域のパスを設定する。デフォルトであれば、/var/lib/pgsql/dataを設定する。
backend_flag1 管理対象のDB(スタンバイ)のPgpool-IIの挙動の設定となる。Pgpool-IIからフェイルオーバーや切り離しを可能とするデフォルトのALLOW_TO_FAILOVERを設定すれば通常問題ないだろう。
backend_application_name1 管理対象のDB(スタンバイ)にてストリーミングレプリケーションを確認した際に設定されるapplication_nameを設定する。ここはbackend_hostname1で設定したホスト名を指定する。
sr_check_period ストリーミングレプリケーションの状態確認を行う間隔を指定する。デフォルトの10秒で設定する。
sr_check_user ストリーミングレプリケーションの状態確認を行うユーザーを指定する。今回はpostgresユーザーを指定する。
sr_check_password ストリーミングレプリケーションの状態確認を行うユーザーのパスワードを指定する。空白で指定すると、pool_passwdファイルの内容をもとにパスワードを確認する動作となる。今回は空白で設定する。
health_check_period 各DBの状態確認を行う間隔を指定する。デフォルトの0で設定されおり無効化されてしまっているので、ストリーミングレプリケーションの間隔と同じ10秒で設定する。
health_check_user 各DBの状態確認を行うユーザーを指定する。今回はpostgresユーザーを指定する。
health_check_password 各DBの状態確認を行うユーザーのパスワードを指定する。空白で指定すると、pool_passwdファイルの内容をもとにパスワードを確認する動作となる。今回は空白で設定する。
failover_command フェイルオーバー発生時のコマンドのフルパスを設定する。本スクリプトは、DB側ではなくPgpool-IIをインストールしたサーバに保存する。スクリプト実行時に必要な情報をパラメータとして渡すことができるので、併せて設定する。
recovery_user オンラインリカバリ実行時のユーザーを指定する。今回はpostgresユーザーを指定する。
recovery_password オンラインリカバリ実行時のユーザーのパスワードを指定する。空白で指定すると、pool_passwdファイルの内容をもとにパスワードを確認する動作となる。今回は空白で設定する。
recovery_1st_stage_command オンラインリカバリ実行時のコマンドを指定する。後述するが、オンラインリカバリのスクリプトは、DBのデータディレクトリ(通常/var/lib/pgsql/data)に保存する。

実際のpgpool.confの設定例を以下に記載する。

pgpool.conf

backend_clustering_mode = 'streaming_replication'
listen_addresses = '*'
port = 9999
unix_socket_directories = '/var/run/postgresql'
pcp_socket_dir = '/var/run/postgresql'
backend_hostname0 = 't1117psgl'
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/var/lib/pgsql/data'
backend_flag0 = 'ALLOW_TO_FAILOVER'
backend_application_name0 = 't1117psgl'
backend_hostname1 = 't1118psgl'
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/var/lib/pgsql/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'
backend_application_name1 = 't1118psgl'
log_destination = 'stderr'
logging_collector = on
log_directory = '/var/log/pgpool_log'
log_filename = 'pgpool-%a.log'
log_truncate_on_rotation = on
log_rotation_age = 1d
log_rotation_size = 0
sr_check_period = 10
sr_check_user = 'postgres'
sr_check_password = ''
health_check_period = 10
health_check_user = 'postgres'
health_check_password = ''
failover_command = '/var/lib/pgsql/failover.sh %d %h %p %D %m %H %M %P %r %R %N %S'
recovery_user = 'postgres'
recovery_password = ''
recovery_1st_stage_command = 'replication_mode_recovery_1st_stage'
hostname0 = ''
wd_ipc_socket_dir = '/var/run/postgresql'

③Pgpool-IIパスワード設定

Pgpool-IIを使用する場合、以下4つのファイルに認証情報のファイルを設定する。

ファイル パスワード記載内容 説明
.pgpoolkey 平文 scram-sha-256で用いる暗号化パスワード情報。
pool_passwd scram-sha-256 Pgpool-IIがDB接続時に使用する認証情報。pg_encコマンドで設定する。
pcp.conf md5 Pgpool-IIの管理コマンド(pcp_node_info コマンド等)を実行する際に使用する認証情報。pg_md5コマンドで設定する。
.pgpass 平文 psqlコマンド等を用いて、Pgpool-II経由でDB接続を行う際に使用する認証情報。

各認証情報ファイルの概要を以下に記載する。

1. scram-sha-256用の暗号化パスワードファイル設定

Pgpoolから各DBへの接続ユーザーのパスワードを設定する。認証方式はscram-sha-256を用いる。まずは、scram-sha-256で使用する暗号化キーを.pgpoolkeyファイルに記載する。パスワードが記載されることから、パーミッションは600で設定する。

[pgpool]# su - postgres
[pgpool]$ echo 'ScramP@ssw0rd!Key' > ~/.pgpoolkey
[pgpool]$ chmod 600 ~/.pgpoolkey

2. DB接続用ユーザーのパスワードファイル設定

pg_encコマンドを以下の通り実行することで、pool_passwdにDB接続用のユーザー及びパスワード情報が追記される。

[pgpool]$ pg_enc -m -f /etc/pgpool-II/pgpool.conf -u postgres 'P@ssw0rd!'
[pgpool]$ cat /etc/pgpool-II/pool_passwd
postgres:AES2XNdfLOB5dSz6BGu3O+sIQ==

3. Pgpool-II管理コマンド用パスワードファイル設定

Pgpool-IIでは管理用のコマンドが各種存在する(例えば、pcp_node_infoなど)。このコマンド実行時のユーザー及びパスワードを設定するため、認証用ファイルであるpcp.confファイルに以下の通り追記する。

[pgpool]# su - postgres
[pgpool]$ echo "postgres:$(pg_md5 'P@ssw0rd!')" >> /etc/pgpool-II/pcp.conf
[pgpool]$ tail -1 /etc/pgpool-II/pcp.conf
postgres:8a24367a1f46c141048752f2d5bbd14b

4. psqlコマンドによる接続時にパスワードを聞かれないようにする

Pgpool-II導入サーバのローカルからpsqlコマンドを用いて接続する際にパスワードを聞かれないようにするため、.pgpassファイルを以下の通りホームディレクトリに作成しておく。

[pgpool]$ vi ~/.pgpass
localhost:9999:*:postgres:P@ssw0rd!

5. マスターとスタンバイのSSHキーを互いに交換

Pgpool-IIはSSHを用いてDBに対してコマンド実行を行う場合がある。SSH接続の際にパスワードを聞かれないよう、SSHキーの交換を行っておく。

[Pgpool]# su - postgres
[Pgpool]$ ssh-keygen
[Pgpool]$ ssh-copy-id t1117psgl
[Pgpool]$ ssh-copy-id t1118psgl

④管理対象DBの設定

1. 管理対象DBへPgpool-II Extentionsをインストール

Pgpool-IIは管理対象とするPostgreSQL側にもインストールが必要である点に注意する。正確にはpgpool-II-pg15-extensionsのパッケージが必要であり、依存関係としてPgpool-II本体のインストールも必要となる。

[Master/Standby]# rpm -ivh https://www.pgpool.net/yum/rpms/4.4/redhat/rhel-8-x86_64/pgpool-II-release-4.4-1.noarch.rpm
[Master/Standby]# dnf install pgpool-II-pg15 pgpool-II-pg15-extensions -y

2. DBのアクセス設定にてPgpool-IIを許可

Pgpool-IIからDBへのアクセス許可のため、pg_hba.confに以下を追記する。認証方式はscram-sha-256とする。

[Master/Standby]# vi /var/lib/pgsql/data/pg_hba.conf
~(中略)~
host    all             all             192.168.11.116/32       scram-sha-256

設定反映のためDBの設定リロードを行う。

[Master/Standby]# systemctl reload postgresql

3. オンラインリカバリ用の設定

DBのフェイルオーバー後にDBを再参加させるオンラインリカバリを実行する際には、DBに事前に設定を投入しておく必要がある。

必要な設定はSQLで用意されているが、SQL実行前にpgpool-recovery.soのライブラリが必要となるので、あらかじめシンボリックリンクを作成しておく。

[Master/Standby]# ln -s /usr/pgsql-15/lib/pgpool-recovery.so /usr/lib64/pgsql/pgpool-recovery.so

次にpgpool-recovery.sqlのSQLを実行する。

[Master]# su - postgres
[Master]$ psql -f /usr/pgsql-15/share/extension/pgpool-recovery.sql template1
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION

⑤Pgpool-II動作確認

1. Pgpool-II起動

ここまでで一度Pgpool-IIを起動し、動作確認を行う。wait for connection requestの行が多数表示されているが、Pgpool-IIはnum_init_childrenというパラメータでクライアントの最大同時接続数を制御しており、デフォルト32個で設定されているため、正常な表示となる。

[Pgpool]# systemctl start pgpool
[Pgpool]# systemctl status pgpool
● pgpool.service - Pgpool-II
   Loaded: loaded (/usr/lib/systemd/system/pgpool.service; disabled; vendor preset: disabled)
   Active: active (running) since Sat 2023-08-26 13:00:00 JST; 5s ago
  Process: 12643 ExecStop=/usr/bin/pgpool -f /etc/pgpool-II/pgpool.conf $STOP_OPTS stop (code=killed, signal=TERM)
 Main PID: 12664 (pgpool)
    Tasks: 34 (limit: 23204)
   Memory: 145.5M
   CGroup: /system.slice/pgpool.service
           tq12664 /usr/bin/pgpool -f /etc/pgpool-II/pgpool.conf -n
           tq12666 pgpool: PgpoolLogger
           tq12668 pgpool: wait for connection request
           tq12669 pgpool: wait for connection request
           tq12670 pgpool: wait for connection request
           tq12671 pgpool: wait for connection request
           tq12672 pgpool: wait for connection request
           tq12673 pgpool: wait for connection request
           tq12674 pgpool: wait for connection request
           tq12675 pgpool: wait for connection request
           tq12676 pgpool: wait for connection request
           tq12677 pgpool: wait for connection request
           tq12678 pgpool: wait for connection request
           tq12679 pgpool: wait for connection request
           tq12680 pgpool: wait for connection request
           tq12681 pgpool: wait for connection request
           tq12682 pgpool: wait for connection request
           tq12683 pgpool: wait for connection request
           tq12684 pgpool: wait for connection request
           tq12685 pgpool: wait for connection request
           tq12686 pgpool: wait for connection request
           tq12687 pgpool: wait for connection request
           tq12688 pgpool: wait for connection request
           tq12689 pgpool: wait for connection request
           tq12690 pgpool: wait for connection request
           tq12691 pgpool: wait for connection request
           tq12692 pgpool: wait for connection request
           tq12693 pgpool: wait for connection request
           tq12694 pgpool: wait for connection request

2. Pgpool-IIにてDBの状態確認

Pgpool-IIからバックエンドとなるDBの状態確認は、以下コマンドで確認できる。statusupになっていることや、Master (=primary)とStandby (=standby)の役割が正常に認識していることを確認しよう。

[Pgpool]# su - postgres
[Pgpool]$ psql -p 9999 -x -c "show pool_nodes"
-[ RECORD 1 ]----------+--------------------
node_id                | 0
hostname               | t1117psgl
port                   | 5432
status                 | up    ←★upであること
pg_status              | up    ←★upであること
lb_weight              | 0.500000
role                   | primary ←★primaryであること
pg_role                | primary ←★primaryであること
select_cnt             | 0
load_balance_node      | false
replication_delay      | 0
replication_state      |
replication_sync_state |
last_status_change     | 2023-08-26 22:03:26
-[ RECORD 2 ]----------+--------------------
node_id                | 1
hostname               | t1118psgl
port                   | 5432
status                 | up    ←★upであること
pg_status              | up    ←★upであること
lb_weight              | 0.500000
role                   | standby ←★standbyであること
pg_role                | standby ←★standbyであること
select_cnt             | 0
load_balance_node      | true
replication_delay      | 0
replication_state      | streaming ←★streamingであること
replication_sync_state | sync    ←★syncであること
last_status_change     | 2023-08-26 22:03:26

以上で、Pgpool-IIを使ってPostgreSQL (ストリーミングレプリケーション構成) を管理するための構築手順は完了となる。

次回はPgpool-IIを使用して、DB停止時の自動フェイルオーバーの動作確認と、オンラインリカバリの動作確認を行う。

2023年9月2日土曜日

PostgreSQLをストリーミングレプリケーションで構成する (PostgreSQL 15.x版)

PostgreSQLは「ストリーミングレプリケーション」と呼ばれる構成を取ることで、DBの冗長構成を取ることができる。以前、PostgreSQL 10.xの環境にてストリーミングレプリケーションを構築する手順を記載した。

PostgreSQL 10.xは2017年10月リリースとなっており、かなり古いバージョンであり、結果的にはPostgreSQL 10.xと手順に細かな差異があることを確認した。

本記事ではPostgreSQL 15.xをインストールしてストリーミングレプリケーションを構成する手順を記載する。

環境

OSはRHEL互換OSであるAlmaLinuxを利用し、パッケージ提供されているPostgreSQLを利用する。

  • OS : AlmaLinux release 8.8
  • PostgreSQL : 15.2

マスターとスタンバイの2台にPostgreSQLをインストールし、ストリーミングレプリケーションを構成する。ホスト名やIPアドレスは以下図を参照いただきたい。

今回はマスターとスタンバイ両方で実施する作業と、片方のみで実施する作業がある。そのため、本記事で記載するプロンプトを以下の通り記載し、作業対象が判別できるようにした。

プロンプト ユーザー 対象
[Master/Standby]# root マスターとスタンバイ両方で実施
[Master]# root マスターのみ実施
[Standby]# root スタンバイのみ実施
[Master/Standby]$ postgres マスターとスタンバイ両方で実施
[Master]$ postgres マスターのみ実施
[Standby]$ postgres スタンバイのみ実施

事前作業として、検証目的なので、firewalldとSELinuxは無効化しておく。

[Master/Standby]# systemctl stop firewalld
[Master/Standby]# systemctl disable firewalld
[Master/Standby]# sed -ie 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
[Master/Standby]# reboot

ストリーミングレプリケーション構成手順概要

PostgreSQLでストリーミングレプリケーションを構成する手順の概要を以下に図示する。

①PostgreSQLインストール・初期セットアップ

1. dnfでPostgreSQLをインストール

まずは、PostgreSQLをインストールする。通常PostgreSQLをRHEL 8にインストールしようとすると、PostgreSQL 10.xがインストールされてしまう。そこで、まずはdnf module enableコマンドでインストールバージョンを選択可能な最新のPostgreSQL 15.xに変更する。

[Master/Standby]# dnf module enable postgresql:15 -y
メタデータの期限切れの最終確認: 5:46:55 前の 2023年08月05日 09時00分46秒 に実施しました。
依存関係が解決しました。
====================================================================================================================================================
 パッケージ                         アーキテクチャー                  バージョン                           リポジトリー                       サイズ
====================================================================================================================================================
モジュールストリームの有効化中:
 postgresql                                                           15

トランザクションの概要
====================================================================================================================================================

完了しました!

postgresql-serverがPostgreSQLのDBエンジン本体となり、依存関係でクライアントツール (posgresqlパッケージ) もインストールされる。それ以外に、各種管理用のスクリプトなどが含まれるpostgresql-contribパッケージとPythonでPostgreSQLを接続するために使用するpython3-psycopg2をインストールしておく。

[Master/Standby]# dnf install postgresql-server postgresql-contrib python3-psycopg2 -y

2. postgresユーザーのパスワードを変更

PostgreSQLは原則postgresユーザーにて操作する。パッケージインストール後にpostgresユーザーのパスワードを設定しておこう。

[Master/Standby]# passwd postgres

postgresユーザーのホームディレクトリに、.pgpassファイルを作成する。本ファイルにはレプリケーションで用いるユーザーのパスワード情報が記載されることから、パーミッションも600に設定する。

[Master/Standby]# su - postgres
[Master/Standby]$ cd ~

[Master/Standby]$ vi .pgpass
t1117psgl:5432:*:dbrepl:P@ssw0rd
t1118psgl:5432:*:dbrepl:P@ssw0rd

[Master/Standby]$ chmod 600 .pgpass

[Master/Standby]$ exit
[Master/Standby]#

3. 初期セットアップ

DBの初期データを作成するため、DB初期セットアップコマンドを実行する。/var/lib/pgsql/dataに初期状態のDBが作成される。

[Master/Standby]# postgresql-setup initdb
WARNING: using obsoleted argument syntax, try --help
WARNING: arguments transformed to: postgresql-setup --initdb --unit postgresql
 * Initializing database in '/var/lib/pgsql/data'
 * Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log

4. DBを起動

一度このタイミングでDBが問題なく起動することを確認しておこう。

[Master/Standby]# systemctl start postgresql
[Master/Standby]# systemctl enable postgresql

5. hostsを登録

Master/Standbyのホスト名とIPアドレスをお互いにhostsファイルへ登録しておく。これは、後程レプリケーションの設定の際にホスト名による登録をするために必要となる。

[Master/Standby]# vi /etc/hosts
192.168.11.117   t1117psgl
192.168.11.118   t1118psgl

6. DBのpostgresユーザーのパスワードを設定

[Master]# su - postgres
[Master]$ psql
postgres=# alter role postgres with password 'P@ssw0rd!';
postgres=# \q

②マスターのDB初期設定

1. マスターにてWALアーカイブログディレクトリ作成

ストリーミングレプリケーションを構成するため、事前にWALアーカイブログを保存するディレクトリを作成する。今回は、/var/lib/pgsql/data/archivedirを保存場所とした。

[Master]# su - postgres
[Master]$ mkdir /var/lib/pgsql/data/archivedir
[Master]$ chmod 700 /var/lib/pgsql/data/archivedir
[Master]$ ls -ld /var/lib/pgsql/data/archivedir
drwx------ 2 postgres postgres 6  6月  5 17:06 /var/lib/pgsql/data/archivedir

2. マスターにてレプリケーション用のDBユーザーを作成

レプリケーション用のDBユーザーを作成する。今回はdbreplというユーザーを作成した。

[Master]$ psql
postgres=# create user dbrepl replication login encrypted password 'P@ssw0rd';
CREATE ROLE

postgres=# \q

3. マスターにて各種設定を実施

次に、マスターにてDBのレプリケーションに必要な各種設定を実施する。設定前に、念のため変更前の設定ファイルをバックアップしておこう。

[Master]$ cp /var/lib/pgsql/data/postgresql.conf ~/postgresql.conf.org
[Master]$ cp /var/lib/pgsql/data/pg_hba.conf ~/pg_hba.conf.org

以下にpostgresql.confにおいて変更する設定値を記載する。なお、PostgreSQL 10.xでは、レプリケーションの設定をrecovery.confという名称の別ファイルで保存していたが、PostgreSQL 15.xではpostgresql.confに統合されている。

postgresql.conf

PostgreSQLの各種設定を変更するため、postgresql.confを更新する。以下に設定内容の概要を記載する。

設定項目 設定内容
listen_addresses DBが接続を受け付けるIPアドレスを指定する。サーバが持つすべてのIPアドレスで接続を許可する場合は、*を指定する。
wal_level replicaで指定する。
synchronous_commit DBに更新があった際に、どこまで更新が反映されたら応答を返すかを設定する。例えば、localの場合はマスターでWALがディスクに記録されたら応答を返す。onの場合はスタンバイに転送されたWALがディスクに記録されたのちに応答を返す。今回は、onで設定する。
archive_mode スタンバイのレプリケーションが長期間停止した際に、マスター側のWALが削除された場合は、WALアーカイブログを使う可能性があるため、WALアーカイブログを有効にする。ストリーミングレプリケーションの場合はalwaysに設定すればよさそうだ。
archive_command WALアーカイブログを出力時に、WALをコピーするためのコマンドを指定する。
max_wal_senders スタンバイから接続を許可する接続数の最大値を設定する。スタンバイ1台の構成であるため、10に設定すれば十分となる。
wal_keep_size ストリーミングレプリケーション用に保持するWALのファイルのサイズ (MB)。PostgreSQL 10.xまではwal_keep_segmentsという設定項目となっていたが、本値はwal_keep_segments x wal_segment_size (デフォルト16MB)で計算可能となる。今回は30 x 16MB = 480MBとした。
synchronous_standby_names スタンバイのリストを記載する。スタンバイを識別する名称は、後述するprimary_conninfoの設定値で設定したapplication_nameとなる。今回はフェイルオーバー時の設定簡素化のため、* (all) で設定する。
hot_standby ストリーミングレプリケーションを有効にするためonに設定する。
lc_messages PostgreSQLのエラーメッセージを日本語から英語に変更する場合は、Cで設定する。この変更は任意である。
restore_command 本設定はスタンバイ側だけ有効になる値となる (マスターでは無視される)。ストリーミングレプリケーションでWALアーカイブログを用いる場合のコピーコマンドを指定する。今回は、scpコマンドを利用する。scp実行時にパスワードを聞かれないようにするため、後程SSHキーの交換を行っておく。
recovery_target_timeline 本設定はスタンバイ側だけ有効になる値となる (マスターでは無視される)。ストリーミングレプリケーションの場合はlatestを設定する。
primary_conninfo 本設定はスタンバイ側だけ有効になる値となる (マスターでは無視される)。application_nameは今回は「スタンバイのホスト名」を設定する。userpasswordは前の手順で作成したレプリケーション用DBユーザーを指定する。hostportは接続先となる「マスターのホスト名」とポート番号 (デフォルト5432) を指定する。
[Master]$ cd $PGDATA
[Master]$ vi postgresql.conf
listen_addresses = '*'
 ↑★すべてのIPアドレスで接続を許可
wal_level = replica    ←★replicaで設定
synchronous_commit = on  ←★onで設定
archive_mode =  always  ←★alwaysで設定
archive_command = 'test ! -f /var/lib/pgsql/data/archivedir/%f && cp %p /var/lib/pgsql/data/archivedir/%f'
 ↑★上記で設定
max_wal_senders = 10    ←★10で設定
wal_keep_size = 480   ←★480 (MB) で設定
synchronous_standby_names = '*' ←★* (all) で設定
hot_standby = on       ←★onで設定
lc_messages = 'C'      ←★エラーメッセージを日本語から英語にするため変更
restore_command = 'scp -o StrictHostKeyChecking=no t1117psgl:/var/lib/pgsql/data/archivedir/%f %p'
 ↑★上記で設定
recovery_target_timeline = latest ←★latestで設定
primary_conninfo = 'application_name=t1118psgl user=dbrepl passfile=''/var/lib/pgsql/.pgpass'' host=t1117psgl port=5432'
 ↑★上記で設定

pg_hba.conf

PostgreSQLにスタンバイからの接続許可を行うため、pg_hba.confに追記する。なお、PostgreSQL 15.xでは、暗号化認証方式のデフォルト設定は、md5ではなくscram-sha-256になっているので、レプリケーションの認証設定もscram-sha-256を採用する。

[Master]$ cd $PGDATA
[Master]$ vi pg_hba.conf
~(中略)~
host    replication     dbrepl          192.168.11.117/32       scram-sha-256
host    replication     dbrepl          192.168.11.118/32       scram-sha-256

4. マスターのDB再起動

設定反映するため、DBを再起動する。一部設定はリロードでは反映されないため、必ず再起動を実施しよう。

[Master]$ systemctl restart postgresql
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
'postgresql.service'を再起動するには認証が必要です。
Authenticating as: root
Password:
==== AUTHENTICATION COMPLETE ====

③マスターのDBをスタンバイにコピー(ベースバックアップ取得)

1. マスターのDBをスタンバイにコピー(ベースバックアップ取得)

スタンバイはマスターからベースバックアップを取得することで、初期設定と初期データのコピーを行う。コピーはPostgreSQLのバックアップ機能であるベースバックアップを使用する。

ベースバックアップを取得するため、スタンバイのDBを一度停止する。

[Standby]# systemctl stop postgresql

DB初期化時に作成されたデータをすべて削除してから、pg_basebackupコマンドを用いてマスターのベースバックアップを直接コピーする。

[Standby]# su - postgres
[Standby]$ rm -rf /var/lib/pgsql/data/*
[Standby]$ pg_basebackup -D /var/lib/pgsql/data -h t1117psgl -X stream -c fast -U dbrepl -w
[Standby]$ echo $?
0        ←★0であることを確認

④スタンバイのDB設定(レプリケーション設定)

1. スタンバイを示すファイル(standby.signal)を作成

DBをスタンバイとして動作させるためのファイルとして、standby.signalという名称の空ファイルを作成する。

[Standby]$ touch /var/lib/pgsql/data/standby.signal

2. マスターとスタンバイのSSHキーを互いに交換

スタンバイからマスターのアーカイブログを取得する際にscpコマンドを使うため、その際にパスワードを聞かれないよう、SSHキーの交換を行っておく。

マスター

[Master]$ ssh-keygen
[Master]$ ssh-copy-id 192.168.11.118

スタンバイ

[Standby]$ ssh-keygen
[Standby]$ ssh-copy-id 192.168.11.117

3. スタンバイのDBを起動

以上で準備が整ったので、停止していたスタンバイのDBを起動する。

[Standby]$ systemctl start postgresql
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
'postgresql.service'を開始するには認証が必要です。
Authenticating as: root
Password:
==== AUTHENTICATION COMPLETE ====

4. マスターにてレプリケーション状態確認

起動後、マスターにてレプリケーションの状態確認を行う。レプリケーションが開始されると、pg_stat_replicationテーブルにレコードが記載される。もし、なにも表示されない場合は、何らかの理由でレプリケーションが正常にできていないことを意味する。

[Master]$ psql -x -c "SELECT * FROM pg_stat_replication;"
-[ RECORD 1 ]----+------------------------------
pid              | 35349
usesysid         | 16384
usename          | dbrepl
application_name | t1118psgl
client_addr      | 192.168.11.118
client_hostname  |
client_port      | 41536
backend_start    | 2023-08-21 07:59:42.847297+09
backend_xmin     |
state            | streaming   ←★streamingであることを確認
sent_lsn         | 0/1B000148
write_lsn        | 0/1B000148
flush_lsn        | 0/1B000148
replay_lsn       | 0/1B000148
write_lag        |
flush_lag        |
replay_lag       |
sync_priority    | 1
sync_state       | sync     ←★syncであることを確認
reply_time       | 2023-08-23 21:25:27.104786+09

⑤レプリケーション動作確認

1. マスターにてDB及びテーブルを作成

それでは、実際にマスターにて更新した内容がストリーミングレプリケーションによってスタンバイ側に反映されることを確認しよう。

まず、テスト用DBとしてtestdbを作成する。

[Master]$ psql -l
                                                            データベース一覧
   名前    |  所有者  | エンコーディング |  照合順序   | Ctype(変換演算子) | ICUロケール | ロケールプロバイダー |     アクセス権限
-----------+----------+------------------+-------------+-------------------+-------------+----------------------+-----------------------
 postgres  | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       |             | libc                 |
 template0 | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       |             | libc                 | =c/postgres          +
           |          |                  |             |                   |             |                      | postgres=CTc/postgres
 template1 | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       |             | libc                 | =c/postgres          +
           |          |                  |             |                   |             |                      | postgres=CTc/postgres
(3 行)

[Master]$ createdb testdb
[Master]$ psql -l
                                                            データベース一覧
   名前    |  所有者  | エンコーディング |  照合順序   | Ctype(変換演算子) | ICUロケール | ロケールプロバイダー |     アクセス権限
-----------+----------+------------------+-------------+-------------------+-------------+----------------------+-----------------------
 postgres  | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       |             | libc                 |
 template0 | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       |             | libc                 | =c/postgres          +
           |          |                  |             |                   |             |                      | postgres=CTc/postgres
 template1 | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       |             | libc                 | =c/postgres          +
           |          |                  |             |                   |             |                      | postgres=CTc/postgres
 testdb    | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       |             | libc                 |
(4 行)

次に、testdbに対してテーブルmytableを作成する。mytableidnameの二つの列を持つシンプルなテーブルとしている。

[Master]$ psql -d testdb
testdb=# \dt
リレーションが見つかりませんでした。
testdb=# create table mytable (id integer primary key, name varchar(20));
CREATE TABLE
testdb=# \dt
             リレーション一覧
 スキーマ |  名前   |  タイプ  |  所有者
----------+---------+----------+----------
 public   | mytable | テーブル | postgres
(1 行)

testdb=# \q

2. スタンバイにレプリケーションされることを確認

作成したテーブルmytableに対して、レコードを3行登録する。

[Master]$ psql -d testdb -c "insert into mytable (id, name) values (1, 'Ichiro');"
[Master]$ psql -d testdb -c "insert into mytable (id, name) values (2, 'Jiro');"
[Master]$ psql -d testdb -c "insert into mytable (id, name) values (3, 'Saburo');"
[Master]$ psql -d testdb -c "select * from mytable;"
 id |  name
----+--------
  1 | Ichiro
  2 | Jiro
  3 | Saburo
(3 行)

スタンバイで確認すると、3行のレコードが存在することを確認できる。

[Standby]$ psql -d testdb -c "select * from mytable;"
 id |  name
----+--------
  1 | Ichiro
  2 | Jiro
  3 | Saburo
(3 行)

なお、スタンバイは参照のみ可能となるため、以下の通りDBの更新を行うとエラーとなり失敗する点に注意しよう。

[Standby]$ psql -d testdb -c "insert into mytable (id, name) values (4, 'Shiro');"
ERROR:  cannot execute INSERT in a read-only transaction

以上で、PostgreSQL 15.xをインストールしてストリーミングレプリケーションを構成する手順は完了となる。

次回は、ストリーミングレプリケーション構成のPostgreSQLをPgpool-IIで管理するための構築手順を記載する。

参照

2022年10月1日土曜日

PostgreSQLのDBを手動フェイルオーバーする手順 (ストリーミングレプリケーション構成)

以下記事にてPostgreSQLをストリーミングレプリケーションで構成する手順を記載した。

ストリーミングレプリケーション構成では、更新・参照が可能なマスターと、参照のみ可能なスタンバイの構成となるが、マスターのDBが障害により停止した場合は、スタンバイのDBを更新可能とする必要がある。このようにスタンバイのDBをマスターDBとして昇格する手順を「フェイルオーバー」と呼ぶ。

PostgreSQLは自動でフェイルオーバーする機能は提供されておらず、PacemakerやPgpool-IIなど、別製品を組み合わせて実現するパターンが多いと想定されるが、今回は手動でPostgreSQLをフェイルオーバーする手順を記載する。

環境

OSはRHEL 8を利用し、ディストリビューションでパッケージ提供されているPostgreSQLのバージョンをそのまま利用する。

  • OS : Red Hat Enterprise Linux 8.2
  • PostgreSQL : 10.6

すでに以下記事の手順にてPostgreSQLのストリーミングレプリケーションは構成されていることを前提とする。

今回は1号機マスター、2号機スタンバイとして構成したものを、1号機スタンバイ、2号機マスターとして入れ替える。作業対象がわかりやすくなるよう、プロンプトを以下のように記載する。

プロンプト 説明
[#1(Master/Standby)] 1号機で作業を実施。()はMaster/Standbyのいずれかを記載。
[#2(Master/Standby)] 2号機で作業を実施。()はMaster/Standbyのいずれかを記載。

手動フェイルオーバー手順

1. マスターのDBを停止

マスターのDBをpg_ctlコマンドで停止する。systemctlコマンドで停止も可能だが、その場合パスワード認証を求められるため、作業簡略化のためpg_ctlコマンドを用いる。

[#1(Master)]$ pg_ctl stop -D ${PGDATA}

2. スタンバイのDBを更新可能となるよう昇格

スタンバイのDBを更新可能にするため、昇格 (Promote) する。これをすると、スタンバイの設定が記載されていたrecovery.confrecovery.doneというファイル名に変更され、それによってスタンバイとしてのDB設定が無効化される。

[#2(Standby)]$ pg_ctl promote -D ${PGDATA}

3. ストリーミングレプリケーションの同期を停止

スタンバイDBを昇格しマスターDBとなったとしても、スタンバイDBが停止しているためWAL転送ができず、更新完了の応答を返すことができない。

以下はこの状態であえてDBに更新を行った際のエラーメッセージとなる。ローカルではコミットされているが、スタンバイにレプリケーションされていない旨のメッセージが表示されている。

[#2(Master)]$ psql -d testdb -c "insert into mytable (id, name) values (4, 'Shiro');"
^CCancel request sent
WARNING:  canceling wait for synchronous replication due to user request
DETAIL:  The transaction has already committed locally, but might not have been replicated to the standby.
INSERT 0 1

これはDBとしては正常な動作であり、postgresql.confsynchronous_commitの設定値がonであったりremote_writeであったりすると発生する。本事象回避のため、一時的に同期レプリケーションを停止させるため、synchronous_standby_namesの値を空白に設定する。

[#2(Master)]$ sed -ie "s/^synchronous_standby_names = '\*'/synchronous_standby_names = ''/g" ${PGDATA}/postgresql.conf
[#2(Master)]$ pg_ctl reload -D ${PGDATA}

これによって、以下の通りDBの更新が可能となる。

[#2(Master)]$ psql -d testdb -c "delete from mytable where id=4;"
DELETE 1
[#2(Master)]$ psql -d testdb -c "insert into mytable (id, name) values (4, 'Shiro');"
INSERT 0 1

4. 旧マスターのDBをスタンバイとして設定

旧マスターのDBをスタンバイとして動作させるため、recovery.donerecovery.confにリネームする。

[#1(Standby)]$ mv ${PGDATA}/recovery.done ${PGDATA}/recovery.conf

もしrecovery.doneが存在しない場合(過去一度もrecovery.confを設定したことがない場合)は、以下のように新規作成する。IPアドレスは新マスターのIPアドレスを指定すること。

[#1(Standby)]$ vi $PGDATA/recovery.conf
standby_mode = 'on'
primary_conninfo = 'application_name=t1116psgl user=dbrepl password=''P@ssw0rd'' host=192.168.11.117 port=5432'
recovery_target_timeline = 'latest'
restore_command = 'scp -o StrictHostKeyChecking=no 192.168.11.117:$PGDATA/archivedir/%f "%p"'

recovery.confを作成後、DBをリロードし設定を反映させる。

[#1(Standby)]$ pg_ctl start -D ${PGDATA}

5. ストリーミングレプリケーションの同期を再開

前の手順で変更したsynchronous_standby_namesをもとの設定値である*に戻す。

[#2(Master)]$ sed -ie "s/^synchronous_standby_names = ''/synchronous_standby_names = '\*'/g" ${PGDATA}/postgresql.conf
[#2(Master)]$ pg_ctl reload -D ${PGDATA}

6. ストリーミングレプリケーションの状態確認

最後にマスターとなったDBにて、レプリケーションの状態を確認しよう。sync_statesyncとなっていれば問題なくマスターとスタンバイでストリーミングレプリケーションが構成できている。

[#2(Master)]$ psql -x -c "SELECT * FROM pg_stat_replication;"
-[ RECORD 1 ]----+------------------------------
pid              | 6616
usesysid         | 16384
usename          | dbrepl
application_name | t1116psgl
client_addr      | 192.168.11.116
client_hostname  |
client_port      | 55756
backend_start    | 2022-06-10 10:58:02.832958+09
backend_xmin     |
state            | streaming
sent_lsn         | 0/701CA08
write_lsn        | 0/701CA08
flush_lsn        | 0/701CA08
replay_lsn       | 0/701CA08
write_lag        |
flush_lag        |
replay_lag       |
sync_priority    | 1
sync_state       | sync

以上で、手動でPostgreSQLをフェイルオーバーする手順は完了となる。

フェイルオーバー手順をスクリプト化する

フェイルオーバーの手順を毎回手作業で実施することは、手間を要するだけでなく、順序を誤ると最悪スタンバイのDB再構築 (ベースバックアップのコピーから実施) が必要となる。

そのため、本作業を自動化すべく、以下の通りスクリプト化してみた。以下にスクリプトの内容を記載する。本スクリプトはスタンバイのDBで実行する。また、互いにSSHの鍵交換を行いパスワードなしでSSHできることが前提となる。

#!/bin/bash

# PostgreSQLのストリーミングレプリケーションをフェイルオーバーするスクリプト

set -eu

# 本スクリプトはスタンバイのDBで実行すること
# スタンバイであるかをチェック
if [ $(psql -xt -c "SELECT * FROM pg_stat_replication;" | grep -c sync_state) -ne 0 ]; then
  echo "[ERROR] This DB is a master. Please run it on standby DB."
  exit 1
fi

# DBのIPアドレスを取得
myhost=$(nmcli c s ens192 | grep ipv4.addresses | sed -e 's#.* \(.*\)/.*#\1#g')
peer=$(grep -e 'primary_conninfo' ${PGDATA}/recovery.conf | sed -e 's/.*host=\(.*\) .*/\1/g')

# マスターの停止
ssh -o StrictHostKeyChecking=no $peer "pg_ctl stop -D ${PGDATA}"

# スタンバイからマスターへ昇格及びレプリケーション停止
pg_ctl promote -D ${PGDATA}
sed -ie "s/^synchronous_standby_names = '\*'/synchronous_standby_names = ''/g" ${PGDATA}/postgresql.conf
pg_ctl reload -D ${PGDATA}

# 旧マスターをスタンバイへ変更
ssh -o StrictHostKeyChecking=no $peer "mv ${PGDATA}/recovery.done ${PGDATA}/recovery.conf"
ssh -o StrictHostKeyChecking=no $peer "pg_ctl start -D ${PGDATA} -l /dev/null"

# レプリケーション再開
sed -ie "s/^synchronous_standby_names = ''/synchronous_standby_names = '\*'/g" ${PGDATA}/postgresql.conf
pg_ctl reload -D $PGDATA

exit 0

スクリプトはfailover.shという名前でpostgresユーザーのホームディレクトリなどに配置すればよい。実行権限も付与しておこう。

[Master/Standby]$ cd ~
[Master/Standby]$ vi failover.sh
[Master/Standby]$ chmod +x failover.sh

実際に本スクリプトを用いてフェイルオーバーを実施してみた結果が以下となる。

[#2(Standby)]$ ./failover.sh
サーバ停止処理の完了を待っています....完了
サーバは停止しました
サーバの昇格を待っています....完了
サーバは昇格しました
サーバにシグナルを送信しました
サーバの起動完了を待っています.....完了
サーバ起動完了
サーバにシグナルを送信しました

[#2(Master)]$ psql -x -c "SELECT * FROM pg_stat_replication;"
-[ RECORD 1 ]----+------------------------------
pid              | 11421
usesysid         | 16384
usename          | dbrepl
application_name | t1116psgl
client_addr      | 192.168.11.116
client_hostname  |
client_port      | 56022
backend_start    | 2022-06-11 15:44:35.698242+09
backend_xmin     |
state            | streaming
sent_lsn         | 0/150001A8
write_lsn        | 0/150001A8
flush_lsn        | 0/150001A8
replay_lsn       | 0/150001A8
write_lag        | 00:00:00.02531
flush_lag        | 00:00:00.02543
replay_lag       | 00:00:00.025536
sync_priority    | 1
sync_state       | sync
2022年9月24日土曜日

PostgreSQLをストリーミングレプリケーションで構成する (PostgreSQL 10.x版)

PostgreSQLは「ストリーミングレプリケーション」と呼ばれる構成を取ることで、DBの冗長構成を取ることができる。

ストリーミングレプリケーションの仕組みはこうだ。まず、構成は「マスター」と呼ばれる1台のDB更新・参照が可能なDBと、1台以上の参照のみ可能な「スタンバイ」で構成される。マスターにてDBの更新がされる際に出力される更新ログ「WAL (Write Ahead Log)」をスタンバイに転送し、DBに反映する。これによって、マスターとスタンバイの持つDBの内容が同一となるよう動作する。

今回、実際にPostgreSQLをインストールしてストリーミングレプリケーションを構成してみたので、その手順を記載する。

本記事ではPostgreSQL 10.xの手順を記載している。PostgreSQL 15.x版の手順は以下URLを参照すること。

環境

OSはRHEL 8を利用し、ディストリビューションでパッケージ提供されているPostgreSQLのバージョンをそのまま利用する。

  • OS : Red Hat Enterprise Linux 8.2
  • PostgreSQL : 10.6

マスターとスタンバイの2台にPostgreSQLをインストールし、ストリーミングレプリケーションを構成する。ホスト名やIPアドレスは以下図を参照いただきたい。

今回はマスターとスタンバイ両方で実施する作業と、片方のみで実施する作業がある。そのため、本記事で記載するプロンプトを以下の通り記載し、作業対象が判別できるようにした。

プロンプト 説明
[Master/Standby] マスターとスタンバイ両方で実施
[Master] マスターのみ実施
[Standby] スタンバイのみ実施

事前作業として、検証目的なので、firewalldとSELinuxは無効化しておこう。

[Master/Standby]# systemctl stop firewalld
[Master/Standby]# systemctl disable firewalld
[Master/Standby]# sed -ie 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
[Master/Standby]# reboot

ストリーミングレプリケーション構成手順概要

PostgreSQLでストリーミングレプリケーションを構成する手順の概要を以下に図示する。

①PostgreSQLインストール・初期セットアップ

1. dnfでPostgreSQLをインストール

まずは、PostgreSQLをインストールする。postgresql-serverがPostgreSQLのDBエンジン本体となり、依存関係でクライアントツール (posgresqlパッケージ) もインストールされる。それ以外に、各種管理用のスクリプトなどが含まれるpostgresql-contribパッケージをインストールしておく。

[Master/Standby]# dnf install postgresql-server postgresql-contrib -y

~(中略)~

依存関係が解決しました。
================================================================================
 パッケージ         Arch   バージョン                       リポジトリー  サイズ
================================================================================
インストール中:
 postgresql-contrib x86_64 10.6-1.module+el8+2469+5ecd5aae  dvd-AppStream 805 k
 postgresql-server  x86_64 10.6-1.module+el8+2469+5ecd5aae  dvd-AppStream 5.1 M
依存関係のインストール中:
 libpq              x86_64 12.1-3.el8                       dvd-AppStream 195 k
 perl-Carp          noarch 1.42-396.el8                     dvd-BaseOS     30 k
 perl-Exporter      noarch 5.72-396.el8                     dvd-BaseOS     34 k
 perl-libs          x86_64 4:5.26.3-416.el8                 dvd-BaseOS    1.6 M
 postgresql         x86_64 10.6-1.module+el8+2469+5ecd5aae  dvd-AppStream 1.5 M
 uuid               x86_64 1.6.2-42.el8                     dvd-AppStream  63 k
モジュールストリームの有効化中:
 postgresql                10

トランザクションの概要
================================================================================
インストール  8 パッケージ

~(以下略)~

2. postgresユーザーのパスワードを変更

PostgreSQLは原則postgresユーザーにて操作する。パッケージインストール後にpostgresユーザーのパスワードを設定しておこう。

[Master/Standby]# passwd postgres

3. 初期セットアップ

DBの初期データを作成するため、DB初期セットアップコマンドを実行する。/var/lib/pgsql/dataに初期状態のDBが作成される。

[Master/Standby]# postgresql-setup initdb
WARNING: using obsoleted argument syntax, try --help
WARNING: arguments transformed to: postgresql-setup --initdb --unit postgresql
 * Initializing database in '/var/lib/pgsql/data'
 * Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log

4. DBを起動

一度このタイミングでDBが問題なく起動することを確認しておこう。

[Master/Standby]# systemctl start postgresql
[Master/Standby]# systemctl enable postgresql
Created symlink /etc/systemd/system/multi-user.target.wants/postgresql.service  → /usr/lib/systemd/system/postgresql.service.

②マスターのDB初期設定

1. マスターにてWALアーカイブログディレクトリ作成

ストリーミングレプリケーションを構成するため、事前にWALアーカイブログを保存するディレクトリを作成する。今回は、/var/lib/pgsql/data/archivedirを保存場所とした。

[Master]$ su - postgres
[Master]$ mkdir /var/lib/pgsql/data/archivedir
[Master]$ chmod 700 /var/lib/pgsql/data/archivedir
[Master]$ ls -ld /var/lib/pgsql/data/archivedir
drwx------ 2 postgres postgres 6  6月  5 17:06 /var/lib/pgsql/data/archivedir

2. マスターにてレプリケーション用のDBユーザーを作成

レプリケーション用のDBユーザーを作成する。今回はdbreplというユーザーを作成した。

[Master]$ psql
postgres=# \du
                                               ロール一覧
 ロール名 |                                     属性                                     | 所属グループ
----------+------------------------------------------------------------------------------+--------------
 postgres | スーパーユーザー, ロール作成可, DB作成可, レプリケーション可, RLS のバイパス | {}

postgres=# create user dbrepl replication login encrypted password 'P@ssw0rd';
CREATE ROLE
postgres=# \du
                                               ロール一覧
 ロール名 |                                     属性                                     | 所属グループ
----------+------------------------------------------------------------------------------+--------------
 dbrepl   | レプリケーション可                                                           | {}
 postgres | スーパーユーザー, ロール作成可, DB作成可, レプリケーション可, RLS のバイパス | {}

postgres=# \q

3. マスターにて各種設定を実施

次に、マスターにてDBのレプリケーションに必要な各種設定を実施する。設定前に、念のため変更前の設定ファイルをバックアップしておこう。

[Master]$ cp /var/lib/pgsql/data/postgresql.conf ~/postgresql.conf.org
[Master]$ cp /var/lib/pgsql/data/pg_hba.conf ~/pg_hba.conf.org

postgresql.conf

PostgreSQLの各種設定を変更するため、postgresql.confを更新する。以下に設定内容の概要を記載する。

設定項目 設定内容
listen_addresses DBが接続を受け付けるIPアドレスを指定する。今回はすべてのインタフェースにて許可するため* (all)を設定する。
wal_level replicaで指定する。
synchronous_commit DBに更新があった際に、どこまで更新が反映されたら応答を返すかを設定する。例えば、localの場合はマスターでWALがディスクに記録されたら応答を返す。onの場合はスタンバイに転送されたWALがディスクに記録されたのちに応答を返す。今回は、onで設定する。
archive_mode スタンバイのレプリケーションが長期間停止した際に、マスター側のWALが削除された場合は、WALアーカイブログを使う可能性があるため、WALアーカイブログを有効にする。ストリーミングレプリケーションの場合はalwaysに設定すればよさそうだ。
archive_command WALアーカイブログを出力時に、WALをコピーするためのコマンドを指定する。
max_wal_senders スタンバイから接続を許可する接続数の最大値を設定する。スタンバイ1台の構成であるため、10に設定すれば十分となる。
wal_keep_segments ストリーミングレプリケーション用に保持するWALのファイル数。今回は決め打ちで30とした。
synchronous_standby_names スタンバイのリストを記載する。スタンバイを識別する名称は、後述するスタンバイのrecovery.confファイルで設定したapplication_nameとなる。今回はフェイルオーバー時の設定簡素化のため、* (all) で設定する。
hot_standby ストリーミングレプリケーションを有効にするためonに設定する。
lc_messages PostgreSQLのエラーメッセージを日本語から英語に変更する場合は、Cで設定する。この変更は任意である。
[Master]$ cd $PGDATA
[Master]$ vi postgresql.conf
listen_addresses = '*'
 ↑★すべてのインタフェースにて接続を受け付ける
wal_level = replica    ←★コメントアウトを外す
synchronous_commit = on  ←★コメントアウトを外す
archive_mode =  always  ←★コメントアウトを外しalwaysに設定
archive_command = 'test ! -f /var/lib/pgsql/data/archivedir/%f && cp %p /var/lib/pgsql/data/archivedir/%f'
 ↑★コメントアウトを外し上記に設定
max_wal_senders = 10    ←★コメントアウトを外す
wal_keep_segments = 30   ←★コメントアウト外し30に設定
synchronous_standby_names = '*' ←★コメントアウトを外し* (all) に設定
hot_standby = on       ←★コメントアウトを外す
lc_messages = 'C'      ←★エラーメッセージを日本語から英語にするため変更

pg_hba.conf

PostgreSQLにスタンバイからの接続許可を行うため、pg_hba.confに追記する。

[Master]$ cd $PGDATA
[Master]$ vi pg_hba.conf
~(中略)~
host    replication     dbrepl          192.168.11.116/32       md5
host    replication     dbrepl          192.168.11.117/32       md5

4. マスターのDB再起動

設定反映するため、DBを再起動する。一部設定はリロードでは反映されないため、必ず再起動を実施しよう。

[Master]$ systemctl restart postgresql
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
'postgresql.service'を再起動するには認証が必要です。
Authenticating as: root
Password:
==== AUTHENTICATION COMPLETE ====

③マスターのDBをスタンバイにコピー(ベースバックアップ取得)

1. マスターのDBをスタンバイにコピー(ベースバックアップ取得)

スタンバイはマスターからベースバックアップを取得することで、初期設定と初期データのコピーを行う。コピーはPostgreSQLのバックアップ機能であるベースバックアップを使用する。

ベースバックアップを取得するため、スタンバイのDBを一度停止する。

[Standby]# systemctl stop postgresql

DB初期化時に作成されたデータをすべて削除してから、pg_basebackupコマンドを用いてマスターのベースバックアップを直接コピーする。

[Standby]# su - postgres
[Standby]$ rm -rf /var/lib/pgsql/data/*
[Standby]$ pg_basebackup -D /var/lib/pgsql/data -h 192.168.11.116 -X stream -c fast -U dbrepl -W
パスワード:   ←★DBレプリケーション用のユーザーのパスワードを指定
[Standby]$ echo $?
0        ←★0であることを確認

④スタンバイのDB設定(レプリケーション設定)

1. スタンバイにてレプリケーション設定を実施

ベースバックアップを行うとpostgresql.confpg_hba.confも一緒にスタンバイへコピーされるため、追加で設定は不要となる。スタンバイ独自で設定が必要なファイルは、recovery.confとなる。

recovery.conf

recovery.confにはPostgreSQLをスタンバイとして動作させるための設定を記載する。以下に設定内容の概要を記載する。

設定項目 設定内容
standby_mode スタンバイで動作させるため、onを設定する。
primary_conninfo application_nameは任意の名前でよいが、今回はスタンバイのホスト名を設定する。userpasswordは前の手順で作成したレプリケーション用DBユーザーを指定する。hostportはマスターのIPアドレスとポート番号 (デフォルト5432) を指定する。
recovery_target_timeline ストリーミングレプリケーションの場合はlatestを設定する。
restore_command ストリーミングレプリケーションでWALアーカイブログを用いる場合のコピーコマンドを指定する。今回は、scpコマンドを利用する。scp実行時にパスワードを聞かれないようにするため、後程SSHキーの交換を行っておく。
[Standby]$ cd $PGDATA
[Standby]$ vi recovery.conf
standby_mode = 'on'
primary_conninfo = 'application_name=t1117psgl user=dbrepl password=''P@ssw0rd'' host=192.168.11.116 port=5432'
recovery_target_timeline = 'latest'
restore_command = 'scp -o StrictHostKeyChecking=no 192.168.11.116:$PGDATA/archivedir/%f "%p"'

2. マスターとスタンバイのSSHキーを互いに交換

スタンバイからマスターのアーカイブログを取得する際にscpコマンドを使うため、その際にパスワードを聞かれないよう、SSHキーの交換を行っておく。

[Master]$ ssh-keygen
[Master]$ ssh-copy-id 192.168.11.117

[Standby]$ ssh-keygen
[Standby]$ ssh-copy-id 192.168.11.116

3. スタンバイのDBを起動

以上で準備が整ったので、停止していたスタンバイのDBを起動する。

[Standby]$ systemctl start postgresql
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
'postgresql.service'を開始するには認証が必要です。
Authenticating as: root
Password:
==== AUTHENTICATION COMPLETE ====

4. マスターにてレプリケーション状態確認

起動後、マスターにてレプリケーションの状態確認を行う。レプリケーションが開始されると、pg_stat_replicationテーブルにレコードが記載される。もし、なにも表示されない場合は、何らかの理由でレプリケーションが正常にできていないことを意味する。

[Master]$ psql -x -c "SELECT * FROM pg_stat_replication;"
-[ RECORD 1 ]----+------------------------------
pid              | 3486
usesysid         | 16384
usename          | dbrepl
application_name | t1117psgl
client_addr      | 192.168.11.117
client_hostname  |
client_port      | 51458
backend_start    | 2022-06-05 17:37:57.698886+09
backend_xmin     |
state            | streaming
sent_lsn         | 0/7000060
write_lsn        | 0/7000060
flush_lsn        | 0/7000060
replay_lsn       | 0/7000060
write_lag        |
flush_lag        |
replay_lag       |
sync_priority    | 1
sync_state       | sync   ←★syncであることを確認

⑤レプリケーション動作確認

1. マスターにてDB及びテーブルを作成

それでは、実際にマスターにて更新した内容がストリーミングレプリケーションによってスタンバイ側に反映されることを確認しよう。

まず、テスト用DBとしてtestdbを作成する。

[Master]$ psql -l
                                         データベース一覧
   名前    |  所有者  | エンコーディング |  照合順序   | Ctype(変換演算子) |     アクセス権限
-----------+----------+------------------+-------------+-------------------+-----------------------
 postgres  | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       |
 template0 | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       | =c/postgres          +
           |          |                  |             |                   | postgres=CTc/postgres
 template1 | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       | =c/postgres          +
           |          |                  |             |                   | postgres=CTc/postgres
(3 行)

[Master]$ createdb testdb
[Master]$ psql -l
                                         データベース一覧
   名前    |  所有者  | エンコーディング |  照合順序   | Ctype(変換演算子) |     アクセス権限
-----------+----------+------------------+-------------+-------------------+-----------------------
 postgres  | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       |
 template0 | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       | =c/postgres          +
           |          |                  |             |                   | postgres=CTc/postgres
 template1 | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       | =c/postgres          +
           |          |                  |             |                   | postgres=CTc/postgres
 testdb    | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       |
(4 行)

次に、testdbに対してテーブルmytableを作成する。mytableidnameの二つの列を持つシンプルなテーブルとしている。

[Master]$ psql -d testdb
testdb=# \dt
リレーションが見つかりませんでした。
testdb=# create table mytable (id integer primary key, name varchar(20));
CREATE TABLE
testdb=# \dt
             リレーション一覧
 スキーマ |  名前   |    型    |  所有者
----------+---------+----------+----------
 public   | mytable | テーブル | postgres
(1 行)

testdb=# \q

2. スタンバイにレプリケーションされることを確認

作成したテーブルmytableに対して、レコードを3行登録する。

[Master]$ psql -d testdb -c "insert into mytable (id, name) values (1, 'Ichiro');"
[Master]$ psql -d testdb -c "insert into mytable (id, name) values (2, 'Jiro');"
[Master]$ psql -d testdb -c "insert into mytable (id, name) values (3, 'Saburo');"
[Master]$ psql -d testdb -c "select * from mytable;"
 id |  name
----+--------
  1 | Ichiro
  2 | Jiro
  3 | Saburo
(3 行)

スタンバイで確認すると、3行のレコードが存在することを確認できる。

[Standby]$ psql -d testdb -c "select * from mytable;"
 id |  name
----+--------
  1 | Ichiro
  2 | Jiro
  3 | Saburo
(3 行)

なお、スタンバイは参照のみ可能となるため、以下の通りDBの更新を行うとエラーとなり失敗する点に注意しよう。

[Standby]$ psql -d testdb -c "insert into mytable (id, name) values (4, 'Shiro');"
ERROR:  cannot execute INSERT in a read-only transaction

以上で、PostgreSQLをインストールしてストリーミングレプリケーションを構成できた。次回は、マスターとスタンバイのDBの役割を切り替えるフェイルオーバーの手順を記載する。

次回記事↓。

PostgreSQLのDBを手動フェイルオーバーする手順 (ストリーミングレプリケーション構成)

参照

人気の投稿