Japan
サイト内の現在位置
PostgreSQL
Pgpool-II を用いた自動フェイルオーバーの実現方法
本ページでは、Pgpool-II を用いた自動フェイルオーバーの実現方法について解説します。
具体的な設定手順と動作確認の流れをご紹介していきますので、ぜひ最後までご覧ください。
①Pgpool-II の概要とメリット
Pgpool-II とは、PostgreSQLのpool(=PostgreSQLのプロセス)を管理する事により
以下の機能を提供するクラスタ制御系ソフトウェアです。
主な機能とそのメリットは、以下のページで解説していますのでご覧下さい。
【Pgpool-II 機能紹介】
②Pgpool-II に関する重要なキーワード解説
その1:スプリットブレイン
クラスタが分断された時に、プライマリノードが複数存在してしまう状態の事を指します。
- この状態でDDL等のクエリが発行されて更新がかかると、データの整合性が損なわれてしまう恐れがあります。
また、仮想IPが複数起動してしまい、IPアドレスが重複してしまう恐れもあります。(図1) - 基本的に、スプリットブレインはネットワーク障害やパラメータの設定ミス、
スクリプトの記載ミスが原因で引き起こされます。
対処法としては、後述する「クォーラム」が挙げられます。
たとえ特定のノードで障害が起きたり、ノード間のネットワークで障害が起きても3台以上の構成であれば、
多数決による合意形成で過半数を取らなければフェイルオーバーは行われず、
スプリットブレインは起こりません。(図3)
その2:クォーラム(quorum)
アルゴリズムの1つで、分散システムにおいてデータの一貫性や可用性を維持するために、
データの読み書き等を実行する際に合意形成を行う必要のある最小ノード数の事を指します。
- 今回の場合だと、フェイルオーバーを安全にするための Pgpool-II ノード間の多数決会議を指します。(図3)
可用性においては、以下のケースにおいて、Watchdogクラスタでクォーラム確認と合意形成を行います。
①バックエンド(PostgreSQLサーバー)でのフェイルオーバー実行前
②Pgpool-II サーバー側でリーダーノードを選定する際
③仮想IPの保持、引継ぎの際
- リーダーに選出されたPgpool-II ノードだけが、実際のfailover_commandを実行する事が出来ます。
- failover_when_quorum_exists = on にすると、Pgpool‑II が「他の Pgpool‑II と合意(クォーラム)」ができた場合にのみフェイルオーバーを発火させ、誤検知による無用な昇格を抑止する事が可能です。
- クォーラムが存在しない場合は、Watchdogが仮想IPを特定のノードに上げる事はないが、
OSレベルで手動で付与する事は可能です。
その際、ip addr addとarpingコマンドを使用して、ネットワークインターフェースに
新たに仮想IPを記載します。 - enable_consensus_with_half_votes = on にすると、偶数台のノードでもクォーラム投票を行う事が
出来るようになるがスプリットブレインの発生確率が大きく上がります。



③実際の設定手順と動作確認
環境情報
今回の検証における動作環境は以下の通りです。
奇数台の投票を原則とするため、3台構成とします。
ストリーミングレプリケーションを行うので、各マシンでインストールする
PostgreSQLのメジャーバージョンは16で一致させます。
Linux、Pgpool-II のメジャーバージョンも合わせておくと安心です。
また、Pgpool-II サーバーとPostgreSQLサーバーが同一サブネット内にあり、
かつクラスター構成である事を前提とします。
・プライマリサーバー:
IPアドレス:172.16.7.201
ホスト名:Server1
バージョン:RHEL8.10、PostgreSQL16.10、pgpool-II version4.6.4
・スタンバイサーバー(1台目):
IPアドレス:172.16.7.211
ホスト名:Server2
バージョン:RHEL8.40、PostgreSQL16.10、pgpool-II version4.6.4
・スタンバイサーバー(2台目):
IPアドレス:172.16.7.212
ホスト名:Server3
・仮想IP:172.16.7.203

前提条件
- $PGDATAは、/home/postgres/pgdata/pg16_3です。
- PostgreSQLのホームディレクトリは、3台ともvar/lib/pgsqlです。
- レプリケーションスロットは無効とします。
- 公開鍵認証方式を用いて、あらかじめSSH認証を自動化設定を行います。
- ポートの占有を確実に防ぐため、ファイアウォールは無効化します。
※補足
レプリケーションスロットとは:
未取得のWALをプライマリが削除しないように保証する仕組みです。
→無効化すると、WAL肥大化によるディスク容量圧迫リスクを回避出来ます。
ただし、WALの取りこぼしが発生する可能性があります。
全体の流れ
1. 事前準備
1.1. PostgreSQL, Pgpool-II のインストール
2. サーバーセットアップ
2.1. プライマリサーバーのセットアップ
2.2. スタンバイサーバーのセットアップ
2.3. PostgreSQLユーザーの作成
2.4. .pgpassの作成
3. ストリーミングレプリケーション構築
3.1. 手動レプリケーションの構築
4. Pgpool-II 関連設定
4.1. PCP接続認証の設定
4.2. pgpool_node_idファイルの作成
4.3. Pgpool-II の設定
4.4. クライアント認証設定
4.5. Watchdog設定
4.6. ログの設定
4.7. 別サーバーへの各種設定ファイルの転送
5. 動作確認
5.1. 各ノードの状態確認
5.2. Pgpool-II サーバー、仮想IPのフェイルオーバーの確認
5.3. PostgreSQLサーバー(バックエンド)のフェイルオーバーの確認
1. 事前準備
1.1. PostgreSQL, Pgpool-II のインストール
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
各サーバーに、PostgreSQLとPgpool-II をそれぞれ各々でインストールしておいて下さい。
2. サーバーセットアップ
2.1. プライマリサーバーのセットアップ
対象サーバー:172.16.7.201
プライマリサーバー(Server1)上でinitdbコマンドを実行して、DBクラスタの初期化を行います。
|
$ su - postgres |
設定ファイル$PGDATA/postgresql.confを以下のように編集する。 pg_rewindを使うためにwal_log_hintsを有効にします。
|
listen_addresses = '*' |
※補足
pg_rewindとは:
分岐したタイムライン差分同期ツール
wal_log_hintsを有効にする事で、全てのページ変更情報がWALに書き出されるようになるため、
pg_rewindが正しく差分を検出出来るようになる。デフォルトはoffです。
2.2. スタンバイサーバーのセットアップ
対象サーバー:172.16.7.211、172.16.7.212
スタンバイサーバー(Server2, Server3)上でpg_basebackupコマンドを実行し、
プライマリデータベースのバックアップを作成する。
|
pg_basebackup -h 172.16.7.201 -p 5432 -U repl_user -D $PGDATA -Fp -Xs -P |
Server2上の$PGDATA配下にmyrecovery.confファイルを作成し、中身に下記の内容を記述します。
Server3に関しても同様に設定を行います。
|
$ primary_conninfo = 'host=172.16.7.201 port=5432 user=repl_user application_name=172.16.7.211 passfile=''/var/lib/pgsql/.pgpass''' |
*hostにはプライマリサーバーのIPアドレスを記入します。
*application_nameには、各サーバーのIPアドレスを記入します。
*passfileには、.pgpassのパスを記入します。
postgresql.confの中に、上記のmyrecovery.confへのパスを記載します。
|
$ vi $PGDATA/postgresql.conf |
*デフォルトでは、後述するフェイルオーバー関連スクリプトのリカバリファイルがpostgresql.confになっています。
そのため、postgresql.confの中にリカバリ専用ファイルへのパスを記入する事で、管理を簡単にする事が可能です。
Server2の$PGDATA配下に、standby.signalファイルを作成し、スタンバイサーバーとして起動出来るようにします。
Server3についても同様に作成します。
|
$ touch $PGDATA/standby.signal |
Server2を起動します。
Server3についても同様に起動します。
|
$ pg_ctl -D $PGDATA start |
2.3. PostgreSQLユーザーの作成
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
各サーバー上で、強固な安全性とリスク低減能力を持つ、scram-sha-256認証を設定します。
password_encryption = 'scram-sha-256'に変更してから、ユーザを登録します。
以下の3つのユーザーを作成し、適切な権限設定とパスワード設定を行います。
| ユーザー名 | パスワード | 備考 |
|---|---|---|
| reple_user | repl | PostgreSQLのレプリケーション専用ユーザー。 |
| pgpool | pgpool | Pgpool-II のレプリケーション遅延チェック(sr_check_user)とヘルスチェック専用ユーザー(health_check_user)。 |
| postgres | postgres | スーバーユーザー権限を持った予備ユーザー。 |
2.4. .pgpassの作成
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
各サーバー上でパスワード入力なしで、ストリーミングレプリケーションやpg_rewindを行うために、
postgresユーザーのホームディレクトリ(var/lib/pgsql)に.pgpassを作成し、
適切な権限(600)を設定します。
3. ストリーミングレプリケーション構築
3.1. 手動レプリケーションの構築
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
Server1上で、WALアーカイブ保存用の専用ディレクトリを作成します。
|
$ mkdir -p /home/postgres/repl_wal-archive |
Server1上で、以下のようにパラメータを設定します。
|
# postgresql.conf |
Server2上で、以下のようにパラメータを設定します。
Server3についても同様にパラメータ設定を行います。
|
# postgresql.conf |
Server1上のDBサーバーにログインし、レプリケーション状態を確認します。
|
$ psql -d repl_user -U repl_db |
*プライマリサーバー上で上記のようにreplicationが表示出来れば、
スタンバイサーバー上でpg_stat_wal_receiverをSELECTする必要はありません。
4. Pgpool-II 関連設定
4.1. PCP接続認証の設定
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
Pgpool-II インストール時のデフォルトのパスを、/home/postgres/配下にコピーします。
|
$ cp -r /etc/pgpool-II /home/postgres/ |
pg_md5を用いて、PCPユーザーのパスワードを暗号化し、「username:encryptedpassword」という形で、
pcp.confに記載します。
|
$ pg_md5 pgpool_password |
follow_primary.shのスクリプトでパスワード入力なしでPCPコマンドを実行するために、
Pgpool-II の起動ユーザ(postgresユーザ)のホームディレクトリに.pcppassを作成します。
適切な権限設定も行います。
|
$ sudo vi ./.pcppass |
scpで他のサーバーにも.pcppassを転送します。
|
$ sudo scp -i ~/.ssh/id_rsa_pgpool -p ~/.pcppass postgres@172.16.7.211: |
*下記のファイルの違いについて把握しておきましょう。
pgpool.conf:Pgpool-II の「動作設定」
pcp.conf:Pgpool-II の「管理者認証情報(暗号化)」
.pgpass:PostgreSQL接続の「パスワード自動入力(平文)」
.pcppass:PCPコマンドの「パスワード自動入力(平文)」
4.2. pgpool_node_idファイルの作成
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
Watchdog機能によって、どの設定がどのホストであるかを区別するために、
各サーバー上でpgpool_node_idファイルにpgpool(watchdog)ホストを識別するための
ノード番号(0、1、2など)を追加します。
始めに、172.16.7.201上で、pgpool_node_idファイルを編集します。
|
$ sudo vi /home/postgres/pgpool-II/pgpool_node_id 0 |
他サーバー(Server1, Server2)上でも同様に、pgpool_node_idファイルにpgpool(watchdog)ホストを
識別するためのノード番号(1、2)をそれぞれpgpool_node_id追加します。
*ファイルの中身は、単一の数字のみを記述します。
4.3. Pgpool-II の設定
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
/home/postgres/pgpool-II/配下にあるpgpool.confを以下のように編集し、
自動フェイルオーバーを実行するためのヘルスチェック設定を行います。
|
# ヘルスチェック設定 |
※補足
backend_application_nameとは:
接続元アプリの名前。
replication_statカラムとreplication_sync_stateカラムを表示するために必要です。
これが設定されていない場合、Pgpoolユーザは「どのレプリカの行なのか」を特定出来ません。
primary_conninfoの名前と一致させる必要があります。
failover_commandとは:
フェイルオーバーを実行するために Pgpool-II から呼び出される外部コマンドです。
主に「旧プライマリノードの切り分け」と 「新プライマリノードの昇格(promote)」を行います。
follow_primary_commandとは:
フェイルオーバーにより新プライマリノードが決定した後、
残りのスタンバイノードを新プライマリノードに従わせるためにPgpool-II から呼び出される外部コマンドです。
/home/postgres/pgpool-II/sample_scripts配下にある、サンプルの実行ファイル
(=failover.sh.sample、follow_primary.sh.sample)をコピーして、
/home/postgres/pgpool-II配下に新たなファイルとして作成します。
|
$ cp -p /home/postgres/pgpool-II/sample_scripts/failover.sh.sample /home/postgres/pgpool-II/failover.sh |
failover.shとfollow_primary.shを開き、PGHOMEのディレクトリパスが正しいかを確認します。
|
$ vi /home/postgres/pgpool-II/failover.sh |
follow_primary.shを開き、各種パラメータが正しく設定されている事を確認します。
|
REPLUSER=repl_user |
4.4. クライアント認証設定
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
Pgpool-II とPostgreSQL間で設定した認証方式(=scram-sha-256)を用いて、
クライアントとPgpool-II の間でも接続するために、
pgpool.confを以下のように編集し、Pgpool-II の認証ファイルであるpool_hba.confによる認証を許可します。
|
enable_pool_hba=on |
pool_hba.confを以下のように編集し、クライアントが接続に用いる仮想IP並びに全ノードから、
Pgpool-II サーバーへの接続を許可します。
|
host all pgpool 172.16.7.201/32 scram-sha-256 |
復号鍵ファイルである.pgpool_keyをpostgresユーザーのホームディレクトリ配下に作成し、
適切な権限を設定します。
|
$ echo client_login > ~/.pgpoolkey |
作成した復号鍵を、他のサーバーにコピーします。
|
$ scp -i ~/.ssh/id_rsa_pgpool -p ~/.pgpoolkey postgres@172.16.7.211: |
以下のコマンドを実行し、ユーザー名と、暗号化したパスワードのエントリをpool_passwdに登録します。
pgpool、postgres双方のユーザーにおいて暗号化を行います。
|
$ pg_enc -m -k /var/lib/pgsql/.pgpoolkey -u pgpool -p |
/etc/pgpool-II/pool_passwd配下にAESで暗号化されたパスワードが登録されるので、
これらを今回使用しているPgpool-II の設定ファイルのディレクトリ(home/postgres/pgpool-II/pool_passwd)
にコピーします。
|
$ cp -r /etc/pgpool-II/pool_passwd /home/postgres/pgpool-II/pool_passwd |
pool_passwdにユーザー名と暗号化されたパスワードが問題なくエントリされているかを確認します。
|
$ cat /etc/pgpool-II/pool_passwd |
4.5. Watchdog設定
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
pgpool.conf内のパラメータを編集し、Watchdogを有効にします。
|
# pgpool.conf |
以下のファイルを確認し、postgresユーザーがパスワードなしにsudoコマンドを実行して
if_up/down_cmdやarping_cmdを実行する事が出来るか確認します。
|
$ sudo cat /etc/sudoers.d/pgpool |
sudoを通して、仮想IPの起動、停止、状態の周知を実行するように、pgpool.confを以下のように設定します。
|
if_up_cmd = '/usr/bin/sudo /usr/sbin/ip addr add $_IP_$/32 dev ens3' |
pgpool.conf内のパラメータを編集し、各種設定を行います。
|
# pgpool.conf |
wd_lifecheck_method = 'heartbeat'の場合において、特定のノードを障害と判定するまでの秒数を指定するwd_heartbeat_deadtimeとハートビート信号を送る間隔の秒数を指定するwd_heartbeat_keepaliveを
以下のように設定します。
|
wd_heartbeat_keepalive = 2 |
/etc/pgpool-II/sample_scripts/escalation.shを/home/postgres/pgpool-II/にコピーし、
wd_escalation_commandに新しいリーダー以外のPgpool-II ノードで仮想IPを停止するスクリプトを設定します。
|
$ cp -p /etc/pgpool-II/sample_scripts/escalation.sh.sample /home/postgres/pgpool-II/escalation.sh |
escalation.shの中身を編集し、サーバーのホスト名、仮想IP、仮想IPを設定するネットワークインターフェース名を
正しく設定します。
|
・ |
4.6. ログの設定
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
pgpool.confを編集し、ログ出力に関して設定を行います。
|
log_destination = 'stderr' |
4.7. 別サーバーへの各種設定ファイルの転送
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
Server1のPgpool-II 関連のconfファイル、.shファイル、pool_passwdファイルを172.16.7.211, 172.16.7.212に転送します。
|
$ scp -p /home/postgres/pgpool-II/{*.conf,*.sh,pool_passwd} postgres@172.16.7.211:/home/postgres/pgpool-II/ |
Server2, Server3にsshでログインし、転送した各種confファイル、.shファイル並びにpool_passwdファイルの
所有者と所属グループをpostgresに変更します。
|
$ ssh server2 "chown postgres:postgres /etc/pgpool-II/{*.conf,*.sh,pool_passwd}" |
5. 動作確認
5.1. 各ノードの状態確認
対象サーバー:172.16.7.201、172.16.7.211、172.16.7.212
各ノードで、PostgreSQLサーバーを起動します。
|
$ pg_ctl start -D /home/postgres/pgdata/pg16_3 |
各ノードで、pgpoolコマンドを用いてPgpool-II を起動します。
|
$ pgpool -f /home/postgres/pgpool-II/pgpool.conf -F /home/postgres/pgpool-II/pcp.conf -a /home/postgres/pgpool-II/pool_hba.conf |
各ノードで、Pgpool-II の各種プロセスがバックエンドプロセスとして適切に実行されているか確認します。
|
$ ps -ef | grep pgpool |
Server1上で、各ノードの状態を確認します。
node_id、hostname~last_status_changeまでのパラメータが表示されていれば問題ありません。
|
$ psql -h 172.16.7.203 -p 9999 -U pgpool -d postgres -c "show pool_nodes" |
pcp_watchdog_infoでPgpool-II のWatchdogの情報を確認します。
Node Name~Status Name、Membership Statusまでのパラメータが表示されていれば問題ありません。
|
$ pcp_watchdog_info -h 172.16.7.211 -p 9898 -U pgpool --verbose |
5.2. Pgpool-II サーバー、仮想IPのフェイルオーバーの確認
リーダーノードであるServer1のPgpool-II を停止し、スタンバイノードで以下のコマンドを実行します。
スタンバイノードであるServer2またはServer3のどちらかがリーダーになることを確認します。
|
$ pgpool -f /home/postgres/pgpool-II/pgpool.conf -F /home/postgres/pgpool-II/pcp.conf -a /home/postgres/pgpool-II/pool_hba.conf -m f stop |
停止したServer1のPgpool-II を再起動し、スタンバイとして起動していることを確認します。
|
$ pgpool -f /home/postgres/pgpool-II/pgpool.conf -F /home/postgres/pgpool-II/pcp.conf -a /home/postgres/pgpool-II/pool_hba.conf |
リーダーノードであるServer2上でip aコマンドを実行し、Linux上で正しくVIPが移り変わっているか確認します。
|
$ ip a |
5.3. PostgreSQLサーバー(バックエンド)のフェイルオーバーの確認
Server1上で、現在のノード状況を確認します。
|
$ psql -h 172.16.7.203 -p 9999 -U pgpool -d postgres -c "show pool_nodes" |
プライマリであるServer1のPostgreSQLサーバーを停止します。
|
$ pg_ctl -m f stop |
フェイルオーバーが発生し、Server2が プライマリに昇格したことを確認します。
|
$ psql -h 172.16.7.203 -p 9999 -U pgpool -d postgres -c "show pool_nodes" |
スタンバイであるServer3のPostgreSQLサーバー上で、walを受信しているか確認します。
|
$ repl_db=# select * from pg_stat_wal_receiver; |
Advancedサポートサービスのご紹介
PostgreSQL保守Advancedサポートサービスでは、PostgreSQL技術者による24時間365日体制のサポートのもと、PostgreSQLの技術的な問い合わせや、障害調査、pg_statsinfoを含む指定のOSSツールのサポートに対応します。
詳細はこちらをご覧ください。
お問い合わせ