本記事では、Pgpool-IIを使用してPostgreSQLの自動フェイルオーバーを実現する方法を紹介します。
- Pgpool-IIとは
- 全体構成図
- サーバー構成
- PostgreSQL構築
- Pgpool-II構築
- SSH公開鍵交換
- Firewalld設定
- Pgpool-II起動/Standby PostgreSQLサーバー構築
- 自動フェイルオーバーテスト
- 最後に
Pgpool-IIとは
Pgpool-IIは、PostgreSQLサーバとPostgreSQLデータベースクライアントの間に位置するプロキシソフトウェアです。
主な機能は以下の通りです。
- 自動フェイルオーバー
- 複数のPostgreSQLサーバーをバックエンドとして管理し、プライマリーサーバーに到達できなくなったときは、自動的にスタンバイサーバーをプライマリーサーバーへ昇格させ、サービスを継続させます。
- 負荷分散
- SELECTクエリを複数のPostgreSQLサーバーに分散させ、システム全体のスループットを改善します。
- コネクションプール
- PostgreSQLサーバーへの確立された接続を維持し、他に指定されていれば接続パラメータも)が同じ新規のコネクションが到着する度に再利用します。
- コネクションオーバヘッドを軽減することによって、システム全体のスループットを改善します。
今回は、自動フェイルオーバー機能の実装方法を説明します。
全体構成図
Pgpool-IIサーバーは1台、PostgreSQL サーバーはMaster/Standbyの2台構成とします。

サーバー構成
本手順は、以下要件のサーバーが準備済みであることを前提としています。
※ 本検証ではPgpool-IIサーバー、PostgreSQLサーバー共に同じハードウェア構成のサーバーを準備します。
- ハードウェア
- CPU:2コア
- メモリ: 4GB
- ディスク: 32GB x 1
また、ソフトウェアは以下のバージョンを使用します。
- OS
- AlmaLinux 9.5
- PostgreSQL/Pgpool-II
- PostgreSQL17
- Pgpool-II 4.5.5
PostgreSQL構築
PostgreSQLインストール
各PostgreSQLサーバーにrootユーザーでログインし、PostgreSQL用リポジトリをインストールします。
# dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
PostgreSQL17をインストールします。
# dnf install -y postgresql17-server
walアーカイブ用のディレクトリを作成します。
# su - postgres
$ mkdir /var/lib/pgsql/archivedir
Pgpool-II extensionsインストール
今回、Pgpool-IIのオンラインリカバリ機能を使用するために、各PostgreSQLサーバーにpgpool-II-pgXX-extensionsをインストールします。
オンラインリカバリ機能とは、ダウンしたノードを復旧させることができる仕組みです。 この機能を使用すると、プライマリノードからデータをスタンバイノードへとコピーし、プライマリと同期させます。
※オンラインリカバリ機能を使用しない場合、Pgpool-II extensionsインストールは不要です
Pgpool-IIの依存関係パッケージがインストールできるように、CRBリポジトリを有効化します。
# dnf config-manager --set-enabled crb
Pgpool-IIリポジトリをインストールします。
# dnf install https://www.pgpool.net/yum/rpms/4.5/redhat/rhel-9-x86_64/pgpool-II-release-4.5-1.noarch.rpm
pgpool-II-pgXX-extensionsと依存パッケージのpgpool-II-pgXXをインストールします。
# dnf install pgpool-II-pg17-extensions pgpool-II-pg17
Pgpool-II オンラインリカバリ設定
オンラインリカバリ用スクリプトを作成します。サンプルスクリプトをコピーして、PGHOMEパラメータを編集します。
# cp -p /etc/pgpool-II/sample_scripts/recovery_1st_stage.sample /var/lib/pgsql/17/data/recovery_1st_stage
# cp -p /etc/pgpool-II/sample_scripts/pgpool_remote_start.sample /var/lib/pgsql/17/data/pgpool_remote_start
# chown postgres:postgres /var/lib/pgsql/17/data/{recovery_1st_stage,pgpool_remote_start}
# vi /var/lib/pgsql/17/data/recovery_1st_stage
(更新)
PGHOME=/usr/pgsql-17
# vi /var/lib/pgsql/17/data/pgpool_remote_start
(更新)
PGHOME=/usr/pgsql-17
Primary PostgreSQLサーバー構築
Primary PostgreSQLサーバーを構築します。尚、Standby サーバーはPgpool-IIのオンラインリカバリ機能を使用して構築しますので、この時点では構築しません。
PostgreSQLを初期化します。
$ /usr/pgsql-17/bin/initdb -D $PGDATA
設定ファイル"postgresql.conf"のパラメータ値を編集します。
$ vi $PGDATA/postgresql.conf
(更新)
# PostgreSQLへのアクセス許可設定
listen_addresses = '*'
# WALアーカイブモードを有効化し、アーカイブ用コマンドを指定
archive_mode = on
archive_command = 'cp "%p" "/var/lib/pgsql/archivedir/%f"'
# MasterからStandbyへのレプリケーション有効化と設定
max_wal_senders = 10
max_replication_slots = 10
wal_level = replica
# Standby側で参照クエリを受け付けるよう設定
hot_standby = on
# オンラインリカバリ機能を使用するためwal_log_hintsを有効化
wal_log_hints = on
設定ファイル"pg_hba.conf"にアクセス許可設定を追加します。今回は、Pgpool-IIサーバとPostgreSQLバックエンドサーバが同サブネット(samenet)にあることを想定しています。また、各ユーザがscram-sha-256認証方式で接続できるよう設定します。
$ vi $PGDATA/pg_hba.conf
(追加)
host all pgpool samenet scram-sha-256
host all postgres samenet scram-sha-256
host replication all samenet scram-sha-256
PostgreSQLを起動します。
$ /usr/pgsql-17/bin/pg_ctl start -D $PGDATA
PostgreSQLに接続し、ユーザーの作成およびパスワードの設定を行います。scram-sha-256認証方式に変更したうえで、レプリケーション遅延チェックとヘルスチェック用のpgpoolと、レプリケーション用のreplを作成します。また、オンラインリカバリで使用するpostgresユーザーのパスワードも設定します。
$ psql
=# SET password_encryption = 'scram-sha-256';
=# CREATE ROLE pgpool WITH LOGIN;
=# CREATE ROLE repl WITH REPLICATION LOGIN;
=# \password pgpool
=# \password repl
=# \password postgres
Pgpool-IIのバックエンドであるPostgreSQLサーバーの状態を確認するshow pool_nodesコマンドでreplication_statカラムとreplication_sync_stateカラムを表示するには、pgpoolユーザーはPostgreSQLのスーパーユーザであるか、pg_monitorグループに所属する必要があります(Pgpool-II 4.1以降)。
以下のコマンドで、pgpoolユーザーをそのグループに所属させます。
$ psql
=# GRANT pg_monitor TO pgpool;
これでPrimary PostgreSQL サーバーの構築は完了です。
StandbyサーバーはPgpool-IIのオンラインリカバリ機能で構築するので、この時点では構築しません。オンラインリカバリ機能での構築手順は後述します。
Pgpool-II構築
Pgpool-IIインストール
Pgpool-IIサーバーに、Pgpool-IIをインストールします。
Pgpool-IIの依存関係パッケージがインストールできるように、CRBリポジトリを有効化します。
# dnf config-manager --set-enabled crb
Pgpool-II用リポジトリをインストールします。
# dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
インストールが成功すると、/etc/yum.repos.d ディレクトリ配下にリポジトリが作成されます。
# ls /etc/yum.repos.d/pgpool-II-release-45.repo
Pgpool-IIをインストールします。
# dnf install pgpool-II-pg17
Pgpool-IIをインストールするとpostgresユーザーが作成されます。postgresユーザーのホームディレクトリ(/var/lib/pgsql)を作成します。
# mkdir /var/lib/pgsql
# chown postgres:postgres /var/lib/pgsql
Pgpool-II設定ファイル編集
pgpool.confを編集します。
# vi /etc/pgpool-II/pgpool.conf
(更新)
#アクセス許可設定および、受付ポートを設定
listen_addresses = '*'
pcp_listen_addresses = '*'
port = 9999
#クラスタリングモードの選択。今回は推奨されているストリーミングレプリケーションを選択
backend_clustering_mode = 'streaming_replication'
# バックエンド情報をPrimary/Standby PostgreSQLサーバーを指定
backend_hostname0 = '<Primary PostgreSQLサーバー名>'
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/var/lib/pgsql/17/data'
backend_flag0 = 'ALLOW_TO_FAILOVER'
backend_application_name0 = '<Primary PostgreSQLサーバー名>'
backend_hostname1 = '<Standby PostgreSQLサーバー名>'
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/var/lib/pgsql/17/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'
backend_application_name1 = '<Standby PostgreSQLサーバー名>'
#PostgreSQL自動フェイルオーバーのためのヘルスチェックを有効化
health_check_period = 5
health_check_timeout = 30
health_check_user = 'pgpool'
health_check_password = ''
health_check_max_retries = 3
#フェイルオーバーコマンドを設定
failover_command = '/etc/pgpool-II/failover.sh %d %h %p %D %m %H %M %P %r %R %N %S'
#オンラインリカバリ用のパラメーターを設定
recovery_user = 'postgres'
recovery_password = ''
recovery_1st_stage_command = 'recovery_1st_stage'
#pool_hba.conf によるアクセス制限を有効化します
enable_pool_hba = on
#socket pathを以下パスに変更
unix_socket_directories = '/var/run/pgpool'
pcp_socket_dir = '/var/run/pgpool'
ここまでパラメーターを設定したら、保存します。
フェイルオーバー用スクリプトを作成します。サンプルスクリプトをコピーして、PGHOMEパラメータを編集します。
# cp -p /etc/pgpool-II/sample_scripts/failover.sh.sample /etc/pgpool-II/failover.sh
# chown postgres:postgres /etc/pgpool-II/failover.sh
# vi /etc/pgpool-II/failover.sh
(更新)
PGHOME=/usr/pgsql-17
pool_hba.confにアクセス許可設定を追記します。書式はpg_hba.confとほぼ同じです。同サブネット(samenet)からのアクセスを許可します。また、各ユーザがscram-sha-256認証方式で接続できるよう設定します。
# vi /etc/pgpool-II/pool_hba.conf
(追記)
host all pgpool samenet scram-sha-256
host all postgres samenet scram-sha-256
パスワードファイル"pool_passwd"に、PostgreSQLユーザーの暗号化したパスワードを出力します。Pgpool-IIがPostgreSQLへ接続するための認証情報です。
# su - postgres
$ echo 'pgpoolkey' > ~/.pgpoolkey
$ chmod 600 ~/.pgpoolkey
$ pg_enc -m -k ~/.pgpoolkey -u pgpool -p
$ pg_enc -m -k ~/.pgpoolkey -u postgres -p
Pgpool-IIの管理コマンドであるPCPコマンドを使用するには、username:encryptedpassword形式のPCPユーザ名とmd5暗号化パスワードをpcp.confに登録する必要があります。今回は、PCPユーザ名を"pgpool"、パスワードを"pgpool_password"に設定します。
# echo 'pgpool:'`pg_md5 pgpool_password` >> /etc/pgpool-II/pcp.conf
SSH公開鍵交換
自動フェイルオーバー、オンラインリカバリ機能を利用するために、Pgpool-IIサーバーとPostgreSQLサーバー間でSSH公開鍵交換を行います。
Pgpool-IIサーバーとPostgreSQLサーバーのpostgresユーザーでSSH秘密鍵・公開鍵を生成します。
# su - postgres
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ cd ~/.ssh
$ ssh-keygen -t rsa -f id_rsa_pgpool
公開鍵id_rsa_pgpool.pubに記載されている内容を、各サーバーの/var/lib/pgsql/.ssh/authorized_keysファイルに追記します。
$ vi /var/lib/pgsql/.ssh/authorized_keys
SELinuxが有効の場合は以下のコマンドを実行し、パスワードなしでのSSH接続を許可します。
$ restorecon -Rv ~/.ssh
設定後、以下SSHコマンドで各サーバーへパスワードなしでログインできることを確認します。
$ ssh postgres@serverX -i ~/.ssh/id_rsa_pgpool
パスワード入力なしでストリーミングレプリケーションを実行するために、Master/Standby PostgreSQLサーバーにパスワードファイル".pgpass"を生成します。
$ vi /var/lib/pgsql/.pgpass
(追記)
<Primary PostgreSQLサーバー名>:5432:replication:repl:<パスワード>
<Standby PostgreSQLサーバー名>:5432:replication:repl:<パスワード>
<Primary PostgreSQLサーバー名>:5432:postgres:postgres:<パスワード>
<Standby PostgreSQLサーバー名>:5432:postgres:postgres:<パスワード>
ファイルのパーミッションを以下のように設定します。
$ chmod 600 /var/lib/pgsql/.pgpass
Firewalld設定
Pgpool-IIサーバー Firewalld設定
Pgpool-IIのポートに対する許可設定を追加します。
# firewall-cmd --permanent --zone=public --add-port=9999/tcp --add-port=9898/tcp
# firewall-cmd --reload
PostgreSQLサーバー Firewalld設定
PostgreSQLのポートに対する許可設定を追加します。
# firewall-cmd --permanent --zone=public --add-service=postgresql
# firewall-cmd --reload
Pgpool-II起動/Standby PostgreSQLサーバー構築
Pgpool-IIを起動します。
# systemctl start pgpool.service
Pgpool-II経由でPostgreSQLへ接続できるか確認するのと同時に、バックエンドのPostgreSQLのステータスを確認します。Primary PostgreSQLサーバーはステータスが"up"で、roleは"Primary"になっているはずです。Standbyはまだ構築していないのでステータスがunsedになっています。Standbyのnode_id番号を確認してください。
$ psql -h <Pgpool-IIサーバーのIPアドレス> -p 9999 -U pgpool postgres -c "show pool_nodes"
ユーザー pgpool のパスワード:
node_id | hostname | port | status | pg_status | lb_weight | role | pg_role | select_cnt | load_balance_node | replication_delay
| replication_state | replication_sync_state | last_status_change
---------+---------------+------+--------+-----------+-----------+---------+---------+------------+-------------------+------------------
-+-------------------+------------------------+---------------------
0 | <Primary PostgreSQLサーバー名> | 5432 | up | up | 0.500000 | primary | primary | 0 | true | 0
| | | 2024-12-19 19:45:34
1 | <Standby PostgreSQLサーバー名> | 5432 | unused | down | 0.500000 | standby | unknown | 0 | false | 0
| | | 2024-12-19 19:45:34
(2 行)
Standbyのステータスが"unsed"になっていることを確認したら、以下コマンドを実行しノードをアタッチします。-n オプションの値は前手順で確認したnode_idを指定します。
$ pcp_attach_node -h <Pgpool-IIサーバーのIPアドレス> -p 9898 -U pgpool -n 1 -W
アタッチが成功すると、ステータスが”down”に変化します。
$ psql -h <Pgpool-IIサーバーのIPアドレス> -p 9999 -U pgpool postgres -c "show pool_nodes"
node_id | hostname | port | status | pg_status | lb_weight | role | pg_role | select_cnt | load_balance_node | replication_delay
| replication_state | replication_sync_state | last_status_change
---------+---------------+------+--------+-----------+-----------+---------+---------+------------+-------------------+------------------
-+-------------------+------------------------+---------------------
0 | <Primary PostgreSQLサーバー名> | 5432 | up | up | 0.500000 | primary | primary | 0 | true | 0
| | | 2024-12-19 19:45:34
1 | <Standby PostgreSQLサーバー名> | 5432 | down | down | 0.500000 | standby | unknown | 0 | false | 0
| | | 2024-12-19 19:58:41
(2 行)
Standbyサーバーに対してオンラインリカバリを実行します。
# pcp_recovery_node -h <Pgpool-IIサーバーのIPアドレス> -p 9898 -U pgpool -n 1 -W
ステータスが"up"、roleが"Standby"になっていれば、Standbyサーバー の構築完了です。
$ psql -h <Pgpool-IIサーバーのIPアドレス> -p 9999 -U pgpool postgres -c "show pool_nodes"
node_id | hostname | port | status | pg_status | lb_weight | role | pg_role | select_cnt | load_balance_node | replication_delay
| replication_state | replication_sync_state | last_status_change
---------+---------------+------+--------+-----------+-----------+---------+---------+------------+-------------------+------------------
-+-------------------+------------------------+---------------------
0 | <Primary PostgreSQLサーバー名> | 5432 | up | up | 0.500000 | primary | primary | 0 | false | 0
| | | 2024-12-19 19:45:34
1 | <Standby PostgreSQLサーバー名> | 5432 | up | up | 0.500000 | standby | standby | 0 | true | 0
| streaming | async | 2024-12-19 20:43:07
(2 行)
自動フェイルオーバーテスト
Primary PostgreSQLサーバーへログインし、疑似障害としてPostgreSQLを停止します。
$ /usr/pgsql-17/bin/pg_ctl -m immediate stop -D $PGDATA
以下コマンドを実行し、Pgpoo-II経由でPostgreSQLへ接続可能であることと、Primaryのステータスが"down"となりStandbyサーバーのroleが"Primary"へ昇格していれば、自動フェイルオーバー成功です。
$ psql -h <Pgpool-IIサーバーのIPアドレス> -p 9999 -U pgpool postgres -c "show pool_nodes"
node_id | hostname | port | status | pg_status | lb_weight | role | pg_role | select_cnt | load_balance_node | replication_delay
| replication_state | replication_sync_state | last_status_change
---------+---------------+------+--------+-----------+-----------+---------+---------+------------+-------------------+------------------
-+-------------------+------------------------+---------------------
0 | <Primary PostgreSQLサーバー名> | 5432 | down | down | 0.500000 | standby | unknown | 0 | false | 0
| | | 2024-12-19 20:47:07
1 | <Standby PostgreSQLサーバー名> | 5432 | up | up | 0.500000 | primary | primary | 0 | true | 0
| | | 2024-12-19 20:47:07
(2 行)
最後に
今回は、Pgpool-IIを利用してPostgreSQLの自動フェイルオーバー機能を実装しました。
PostgreSQLの標準機能では自動フェイルオーバーは実装できないので、高可用性の面でPgpool-IIはとても有用ですね。
今回の構成はPgpool-IIサーバーが1台なのでSPOFになる可能性があります。今後、Pgpool-IIサーバーの冗長構成についても検証していきたいと思います。
坂本 典久(日本ビジネスシステムズ株式会社)
クラウドソリューション事業本部所属。 SQL ServerやPostgreSQLなどのデータベース設計・構築、Azureなどのクラウドを中心としたシステムの設計・構築に携わっています。
担当記事一覧