ここでは、ストリーミングレプリケーション構成のPostgreSQLをPgpool-IIで管理するシステムの構成例を示します。この例では、3台のPgpool-IIを使ってPostgreSQLを管理し、単一障害点やスプリットブレインの起きない堅牢なクラスタを運用することが可能です。
この設定例ではPostgreSQL 13を使っていますが、各種スクリプトはPostgreSQL 9.5以降での動作確認を行っています。
Pgpool-IIサーバとPostgreSQLサーバが同じサブネットにあることを前提とします。
今回は、Linuxサーバを3台用意し、それぞれのホスト名は 「server1」、「server2」、「server3」 とします。使用するOSはすべてCentOS 7.4とします。それぞれのサーバにPostgreSQLとPgpool-IIをインストールします。3台のPostgreSQLがストリーミングレプリケーション構成になります。全体構成図は以下の通りです。
注意: 「アクティブ」「スタンバイ」「Primary」「Standby」といった役割は固定されているものではなく、運用と共に変化することがあります。
表 8-2. ホスト名とIPアドレス
ホスト名 | IPアドレス | 仮想IP |
---|---|---|
server1 | 192.168.137.101 | 192.168.137.150 |
server2 | 192.168.137.102 | |
server3 | 192.168.137.103 |
表 8-3. PostgreSQLのバージョンと設定情報
項目 | 値 | 説明 |
---|---|---|
PostgreSQLバージョン | 13.0 | - |
ポート番号 | 5432 | - |
$PGDATA | /var/lib/pgsql/13/data | - |
アーカイブモード | 有効 | /var/lib/pgsql/archivedir |
レプリケーションスロット | 有効 | - |
自動起動 | 有効 | - |
表 8-4. Pgpool-IIのバージョンと設定情報
項目 | 値 | 説明 |
---|---|---|
Pgpool-IIバージョン | 4.2.0 | - |
ポート番号 | 9999 | Pgpool-IIが接続を受け付けるポート番号 |
9898 | PCPプロセスが接続を受け付けるポート番号 | |
9000 | watchdogが接続を受け付けるポート番号 | |
9694 | Watchdogのハートビート信号を受信するUDPポート番号 | |
設定ファイル | /etc/pgpool-II/pgpool.conf | Pgpool-IIの設定ファイル |
Pgpool-II起動ユーザ | postgres (Pgpool-II 4.1以降) | Pgpool-II 4.0 以前のバージョンでは、デフォルトではrootでPgpool-IIを起動する |
Pgpool-II動作モード | ストリーミングレプリケーションモード | - |
Watchdog機能 | 有効 | ハートビート方式 |
自動起動 | 有効 | - |
表 8-5. RPMに含まれるサンプルスクリプト
機能 | スクリプト | 説明 |
---|---|---|
自動フェイルオーバ | /etc/pgpool-II/failover.sh.sample | フェイルオーバを実行するスクリプト。failover_commandで使用します。 |
/etc/pgpool-II/follow_primary.sh.sample | フェイルオーバ後、新しいプライマリサーバとスタンバイサーバを同期させるスクリプト。follow_primary_commandで使用します。 | |
オンラインリカバリ | /etc/pgpool-II/recovery_1st_stage.sample | スタンバイサーバをリカバリするスクリプト。recovery_1st_stage_commandで使用します。 |
/etc/pgpool-II/pgpool_remote_start.sample | recovery_1st_stage_command 後に、スタンバイノードを起動させるスクリプト。 | |
Watchdog | /etc/pgpool-II/escalation.sh.sample | Pgpool-II のアクティブ/スタンバイ切り替え時に新アクティブ機以外で起動している仮想IPを停止するスクリプト。wd_escalation_commandで使用します。 |
上記各種スクリプトはRPMパッケージに同梱されており、必要に応じてカスタマイズできます。
この設定例ではYUMを使用してPostgreSQLおよびPgpool-IIをインストールします。
PostgreSQLのインストールはPostgreSQLコミュニティのリポジトリを使います。
[全サーバ]# yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm [全サーバ]# yum install -y postgresql13-server
Pgpool-IIのインストールはPgpool-II開発コミュニティが提供するYumリポジトリを用いてインストールします。
Pgpool-II関連のパッケージはPostgreSQLコミュニティのリポジトリにもあるため、 PostgreSQLコミュニティのリポジトリからPgpool-IIをインストールしないように/etc/yum.repos.d/pgdg-redhat-all.repoにexclude設定を追加します。
[全サーバ]# vi /etc/yum.repos.d/pgdg-redhat-all.repo
以下は、/etc/yum.repos.d/pgdg-redhat-all.repoの設定例です。
[pgdg-common] ... exclude=pgpool* [pgdg14] ... exclude=pgpool* [pgdg13] ... exclude=pgpool* [pgdg12] ... exclude=pgpool* [pgdg11] ... exclude=pgpool* [pgdg10] ... exclude=pgpool* [pgdg96] ... exclude=pgpool*
Pgpool-IIをインストールします。
[全サーバ]# yum install -y https://www.pgpool.net/yum/rpms/4.2/redhat/rhel-7-x86_64/pgpool-II-release-4.2-2.noarch.rpm [全サーバ]# yum install pgpool-II-pg13-*
Pgpool-IIの設定の前に、以下の設定を行ってください。
PostgreSQLプライマリサーバのみでストリーミングレプリケーションの設定を行います。 スタンバイサーバの設定は、プライマリが起動した状態で、Pgpool-IIのオンラインリカバリ機能を使って行うため不要です。 この設定の例ではアーカイブリカバリを行うように設定します。
まず、すべてのサーバにてWALを格納するディレクトリ/var/lib/pgsql/archivedirを事前に作成します。この設定例では、プライマリサーバのみでWALアーカイブをローカルで実施します。
[全サーバ]# su - postgres [全サーバ]$ mkdir /var/lib/pgsql/archivedir
プライマリサーバのPostgreSQLを初期化します。
[server1]# su - postgres [server1]$ /usr/pgsql-13/bin/initdb -D $PGDATA
次にserver1にて、設定ファイル$PGDATA/postgresql.confを以下のように編集します。 pg_rewindを使うためにwal_log_hintsを有効にしておきます。 プライマリが後でスタンバイになる可能性があるので、hot_standby = onにしておきます。
listen_addresses = '*' archive_mode = on archive_command = 'cp "%p" "/var/lib/pgsql/archivedir/%f"' max_wal_senders = 10 max_replication_slots = 10 wal_level = replica hot_standby = on wal_log_hints = on
Pgpool-IIのヘルスチェック及びレプリケーションの遅延チェックでPostgreSQLのユーザを設定する必要があります。セキュリティ上の理由で、この設定例ではスーパーユーザを使わないようにします。 Pgpool-IIのレプリケーションの遅延チェックとヘルスチェック用のユーザpgpoolを作成します。 また、PostgreSQLプライマリサーバserver1でレプリケーション専用ユーザreplを作成します。 Pgpool-II4.0からSCRAM認証を利用できるようになりました。この設定例では、scram-sha-256認証方式を利用します。 まず、password_encryption = 'scram-sha-256'に変更してから、ユーザを登録します。
表 8-6. ユーザ
ユーザ名 | パスワード | 備考 |
---|---|---|
repl | repl | PostgreSQLのレプリケーション専用ユーザ |
pgpool | pgpool | Pgpool-IIのレプリケーション遅延チェック(sr_check_user)、ヘルスチェック専用ユーザ(health_check_user) |
postgres | postgres | オンラインリカバリを実行するユーザ |
[server1]# psql -U postgres -p 5432 postgres=# SET password_encryption = 'scram-sha-256'; postgres=# CREATE ROLE pgpool WITH LOGIN; postgres=# CREATE ROLE repl WITH REPLICATION LOGIN; postgres=# \password pgpool postgres=# \password repl postgres=# \password postgres
SHOW POOL_NODESコマンドでreplication_statカラムとreplication_sync_stateカラムを表示するには、 pgpoolユーザはPostgreSQLのスーパーユーザーであるか、 pg_monitorグループに所属する必要があります。(Pgpool-II4.1以降) 以下のコマンドでpgpoolユーザをそのグループに所属させます。
GRANT pg_monitor TO pgpool;
注意: detach_false_primary(Pgpool-II 4.1以降)を利用する予定がある場合、"pgpool" ロールはPostgreSQLのスーパーユーザーであるか、pg_monitorグループに所属する必要があります。
Pgpool-IIサーバとPostgreSQLバックエンドサーバが同じサブネットワークにあることを想定し、各ユーザがscram-sha-256認証方式で接続できるように、pg_hba.confを編集しておきます。
host all all samenet scram-sha-256 host replication all samenet scram-sha-256
自動フェイルオーバ、オンラインリカバリ機能を利用するには、すべてのPgpool-IIノード間でPgpool-IIの起動ユーザ(デフォルトはpostgresユーザ。Pgpool-II 4.0以前、デフォルトはrootユーザ)およびPostgreSQLの起動ユーザ(デフォルトはpostgresユーザ)として双方向にSSH公開鍵認証(パスワードなし)で接続できるように設定する必要があります。
まず、全サーバでpostgresユーザのパスワードを設定します。
[全サーバ]# passwd postgres
全サーバで以下のコマンドを実行し、SSH公開鍵の登録を行います。 この設定例では生成される鍵ファイル名はid_rsa_pgpoolとします。
[全サーバ]# mkdir ~/.ssh [全サーバ]# chmod 700 ~/.ssh [全サーバ]# cd ~/.ssh [全サーバ]# ssh-keygen -t rsa -f id_rsa_pgpool [全サーバ]# ssh-copy-id -i id_rsa_pgpool.pub postgres@server1 [全サーバ]# ssh-copy-id -i id_rsa_pgpool.pub postgres@server2 [全サーバ]# ssh-copy-id -i id_rsa_pgpool.pub postgres@server3 [全サーバ]# su - postgres [全サーバ]$ mkdir ~/.ssh [全サーバ]$ chmod 700 ~/.ssh [全サーバ]$ cd ~/.ssh [全サーバ]$ ssh-keygen -t rsa -f id_rsa_pgpool [全サーバ]$ ssh-copy-id -i id_rsa_pgpool.pub postgres@server1 [全サーバ]$ ssh-copy-id -i id_rsa_pgpool.pub postgres@server2 [全サーバ]$ ssh-copy-id -i id_rsa_pgpool.pub postgres@server3
設定後、Pgpool-IIの起動ユーザでおよびPostgreSQLの起動ユーザでssh postgres@serverX -i ~/.ssh/id_rsa_pgpoolコマンドを実行し、パスワード入力せずログインできることを確認してください。
注意: 公開鍵認証によるログインに失敗した場合には、以下を確認してください。
/etc/ssh/sshd_configで公開鍵認証が許可されていることを確認します。
PubkeyAuthentication yes
SSHのパスワード認証を無効化している場合は、ssh-copy-idの実行に失敗するので、一時的に/etc/ssh/sshd_config内のPasswordAuthenticationをyesに変更するなどしてください。
PasswordAuthentication yes
SELinuxを有効化している場合は、SSH公開鍵認証(パスワードなし)が失敗する可能性があるので、すべてのサーバで以下のコマンドを実行する必要があります。
[全サーバ]# su - postgres [全サーバ]$ restorecon -Rv ~/.ssh
replユーザのパスワード入力なしで、ストリーミングレプリケーションとオンラインリカバリを行うために、またはpostgresユーザでpg_rewindを実行するために、すべてのサーバにてpostgresユーザのホームディレクトリ/var/lib/pgsql に.pgpassを作成・配置し、パーミッションを 600 に設定しておきます。
[全サーバ]# su - postgres [全サーバ]$ vi /var/lib/pgsql/.pgpass (以下を追加) server1:5432:replication:repl:<replユーザのパスワード> server2:5432:replication:repl:<replユーザのパスワード> server3:5432:replication:repl:<replユーザのパスワード> server1:5432:postgres:postgres:<postgresユーザのパスワード> server2:5432:postgres:postgres:<postgresユーザのパスワード> server3:5432:postgres:postgres:<postgresユーザのパスワード> [全サーバ]$ chmod 600 /var/lib/pgsql/.pgpass
Pgpool-IIやPostgreSQLに接続する際には、ファイアーウォールによって目的のポートが開けられていなければなりません。CentOS/RHEL7の場合、以下のように設定します。
[全サーバ]# firewall-cmd --permanent --zone=public --add-service=postgresql [全サーバ]# firewall-cmd --permanent --zone=public --add-port=9999/tcp --add-port=9898/tcp --add-port=9000/tcp --add-port=9694/udp [全サーバ]# firewall-cmd --reload
Pgpool-IIの自動起動設定を全てのサーバで行います。
[全サーバ]# systemctl enable pgpool.service
注意: Pgpool-IIを自動起動にした場合、サーバ起動後にPostgreSQLを起動できるだけの時間をsearch_primary_node_timeoutに設定してください。 search_primary_node_timeoutの間にバックエンドのPostgreSQLに接続できない場合、 Pgpool-IIはPostgreSQLに接続できなくなります。
Pgpool-II 4.2以降、すべての設定パラメーターがすべてのホストで同一になりました。 Watchdog機能が有効になっている場合、どの設定がどのホストであるかを区別するには、 pgpool_node_idファイルの設定が必要になります。 pgpool_node_idファイルを作成し、そのファイルにpgpool(watchdog)ホストを識別するためのノード番号(0、1、2など)を追加します。
server1
[server1]# cat /etc/pgpool-II/pgpool_node_id 0
server2
[server2]# cat /etc/pgpool-II/pgpool_node_id 1
server3
[server3]# cat /etc/pgpool-II/pgpool_node_id 2
Pgpool-II 4.2以降、すべての設定パラメーターがすべてのホストで同一になったので、どれか一つのノード上でpgpool.confを編集し、編集したpgpool.confファイルを他のpgpoolノードにコピーすれば良いです。
Pgpool-IIにはいくつかのクラスタリングモードがあります。 クラスタリングモードの設定にはbackend_clustering_modeを使用します。 今回の設定例では、ストリーミングレプリケーションモードを設定します。
RPMからインストールした場合、すべてのPgpool-IIのサンプル設定ファイルは/etc/pgpool-IIにあります。今回はストリーミングレプリケーションモードのテンプレートとしてpgpool.conf.sample-streamサンプルファイルを使用します。
[全サーバ]# cp -p /etc/pgpool-II/pgpool.conf.sample-stream /etc/pgpool-II/pgpool.conf
Pgpool-IIおよびPCPが全てのIPアドレスから接続を受け付けるように、listen_addressesパラメータに'*'を設定します。
listen_addresses = '*' pcp_listen_addresses = '*'
レプリケーションの遅延チェックユーザsr_check_userにpgpoolユーザを設定します。 この設定例では、sr_check_passwordはpgpool.confに指定せず、pool_passwdファイルに作成します。作成方法については後述の項8.2.6.9を参照ください。 Pgpool-II 4.0から、sr_check_passwordが空白の場合、Pgpool-IIは空のパスワードを使用する前にまずpool_passwdファイルからsr_check_userに指定したユーザのパスワードを取得できるか試みます。
sr_check_user = 'pgpool' sr_check_password = ''
自動フェイルオーバのため、ヘルスチェックを有効にします。health_check_periodのデフォルト値が0で、これはヘルスチェックが無効であることを意味します。 また、ネットワークが不安定な場合には、バックエンドが正常であるにも関わらず、ヘルスチェックに失敗し、フェイルオーバや縮退運転が発生してしまう可能性があります。そのようなヘルスチェックの誤検知を防止するため、ヘルスチェックのリトライ回数をhealth_check_max_retries = 3 に設定しておきます。 health_check_user、health_check_passwordは前述のsr_check_user、sr_check_passwordと同様に設定します。
health_check_period = 5 # Health check period # Disabled (0) by default health_check_timeout = 30 # Health check timeout # 0 means no timeout health_check_user = 'pgpool' health_check_password = '' health_check_max_retries = 3
また、バックエンド情報を前述のserver1、server2及びserver3の設定に従って設定しておきます。複数バックエンドノードを定義する場合、以下のbackend_*などのパラメータ名の末尾にノードIDを表す数字を付加することで複数のバックエンドを指定することができます。
# - Backend Connection Settings - backend_hostname0 = 'server1' # Host name or IP address to connect to for backend 0 backend_port0 = 5432 # Port number for backend 0 backend_weight0 = 1 # Weight for backend 0 (only in load balancing mode) backend_data_directory0 = '/var/lib/pgsql/13/data' # Data directory for backend 0 backend_flag0 = 'ALLOW_TO_FAILOVER' # Controls various backend behavior # ALLOW_TO_FAILOVER or DISALLOW_TO_FAILOVER backend_hostname1 = 'server2' backend_port1 = 5432 backend_weight1 = 1 backend_data_directory1 = '/var/lib/pgsql/13/data' backend_flag1 = 'ALLOW_TO_FAILOVER' backend_hostname2 = 'server3' backend_port2 = 5432 backend_weight2 = 1 backend_data_directory2 = '/var/lib/pgsql/13/data' backend_flag2 = 'ALLOW_TO_FAILOVER'
SHOW POOL_NODESコマンドでreplication_statカラムとreplication_sync_stateカラムを表示するには、 backend_application_nameパラメータを設定する必要があります。ここではそれぞれのホスト名を設定します。(Pgpool-II 4.1以降)
... backend_application_name0 = 'server1' ... backend_application_name1 = 'server2' ... backend_application_name2 = 'server3'
PostgreSQLバックエンドノードがダウンした時に実行するスクリプトをfailover_commandに設定します。 また、PostgreSQLサーバが3台の場合、プライマリノードのフェイルオーバ後に新しいプライマリからスレーブをリカバリするためにfollow_primary_commandも設定する必要があります。follow_primary_commandはプライマリノードのフェイルオーバ後に実行されます。PostgreSQLサーバが2台の場合、follow_primary_commandの設定は不要です。
それぞれの実行スクリプトの引数は、それぞれ実行時にPgpool-IIによってバックエンドの具体的な情報に置き換えられます。各引数の意味はfailover_commandをご参照ください。
failover_command = '/etc/pgpool-II/failover.sh %d %h %p %D %m %H %M %P %r %R %N %S' follow_primary_command = '/etc/pgpool-II/follow_primary.sh %d %h %p %D %m %H %M %P %r %R'
注意: %N、%SはPgpool-II 4.1で追加された引数です。 Pgpool-II 4.0 または以前のバージョンを利用している場合、これらの引数を指定できないので、ご注意ください。
サンプルスクリプトfailover.sh及びfollow_primary.shは /etc/pgpool-II/配下にインストールされていますので、これらのファイルをコピーして作成します。
[全サーバ]# cp -p /etc/pgpool-II/failover.sh{.sample,} [全サーバ]# cp -p /etc/pgpool-II/follow_primary.sh{.sample,} [全サーバ]# chown postgres:postgres /etc/pgpool-II/{failover.sh,follow_primary.sh}
基本的にはPGHOMEを環境に合わせて変更すれば、動作します。
[全サーバ]# vi /etc/pgpool-II/failover.sh ... PGHOME=/usr/pgsql-13 ... [全サーバ]# vi /etc/pgpool-II/follow_primary.sh ... PGHOME=/usr/pgsql-13 ...
PCPコマンドを使用するにはユーザ認証が必要になるので、ユーザ名とmd5ハッシュに変換されたパスワードを"username:encrypted password"の形式でpcp.confファイルに設定します。
follow_primary.shでpgpoolユーザがPCP_USERに指定されている場合、
# cat /etc/pgpool-II/follow_primary.sh ... PCP_USER=pgpool ...
以下のようにpg_md5コマンドを利用し、ハッシュ化されたpgpoolユーザのパスワードエントリを/etc/pgpool-II/pcp.confに追加します。
[全サーバ]# echo 'pgpool:'`pg_md5 PCPコマンドパスワード` >> /etc/pgpool-II/pcp.conf
前述のfollow_primary.shのスクリプトでパスワード入力なしでPCPコマンドを実行できるように、すべてのサーバでPgpool-IIの起動ユーザのホームディレクトリに.pcppassを作成します。
[全サーバ]# su - postgres [全サーバ]$ echo 'localhost:9898:pgpool:<pgpool user password>' > ~/.pcppass [全サーバ]$ chmod 600 ~/.pcppass
注意: follow_primary.shスクリプトはテーブルスペースに対応していません。 テーブルスペースを使っている場合は、スクリプトを自分で変更する必要があります。
続いて、オンラインリカバリを行うためのPostgreSQLのユーザ名およびオンラインリカバリ時に呼び出されるコマンドrecovery_1st_stageを設定します。
オンラインリカバリで実行されるpgpool_recovery
関数はPostgreSQLのスーパーユーザ権限が必要なため、recovery_userにスーパーユーザを指定しなければなりません。ここでは、postgresユーザを指定します。
recovery_user = 'postgres' # Online recovery user recovery_password = '' # Online recovery password recovery_1st_stage_command = 'recovery_1st_stage'
オンラインリカバリ用のサンプルスクリプトrecovery_1st_stage 及びpgpool_remote_startは /etc/pgpool-II/配下にインストールされていますので、これらのファイルをプライマリサーバ(server1)のデータベースクラスタ配下に配置します。
[server1]# cp -p /etc/pgpool-II/recovery_1st_stage.sample /var/lib/pgsql/13/data/recovery_1st_stage [server1]# cp -p /etc/pgpool-II/pgpool_remote_start.sample /var/lib/pgsql/13/data/pgpool_remote_start [server1]# chown postgres:postgres /var/lib/pgsql/13/data/{recovery_1st_stage,pgpool_remote_start}
基本的にはPGHOMEを環境に合わせて変更すれば、動作します。
[server1]# vi /var/lib/pgsql/13/data/recovery_1st_stage ... PGHOME=/usr/pgsql-13 ... [server1]# vi /var/lib/pgsql/13/data/pgpool_remote_start ... PGHOME=/usr/pgsql-13 ...
また、オンラインリカバリ機能を使用するには、pgpool_recovery
、pgpool_remote_start
、pgpool_switch_xlog
という関数が必要になるので、server1のtemplate1にpgpool_recovery
をインストールしておきます。
[server1]# su - postgres [server1]$ psql template1 -c "CREATE EXTENSION pgpool_recovery"
注意: recovery_1st_stageスクリプトはテーブルスペースに対応していません。 テーブルスペースを使っている場合は、スクリプトを自分で変更する必要があります。
事前設定の章で、Pgpool-IIとPostgreSQLの間に認証方式をscram-sha-256に設定しました。この設定例では、クライアントとPgpool-IIの間でもscram-sha-256認証方式を利用し接続するように設定します。 Pgpool-IIのクライアント認証の設定ファイルはpool_hba.confと呼ばれ、RPMパッケージからインストールする場合、デフォルトでは/etc/pgpool-II配下にインストールされます。 デフォルトではpool_hba.confによる認証は無効になっているので、pgpool.confでは以下の設定をonに変更します。
enable_pool_hba = on
pool_hba.confのフォーマットはPostgreSQLのpg_hba.confとほとんど同じです。pgpoolとpostgresユーザをscram-sha-256認証に設定します。
host all pgpool 0.0.0.0/0 scram-sha-256 host all postgres 0.0.0.0/0 scram-sha-256
注意: Pgpool-II 4.0の場合、pgpool.confファイル内のhealth_check_password、 sr_check_password、wd_lifecheck_password、 recovery_passwordにはAES256暗号化形式、平文形式しか指定できないので、 ご注意ください。
Pgpool-IIのクライアント認証で用いるデフォルトのパスワードファイル名はpool_passwdです。 scram-sha-256認証を利用する場合、Pgpool-IIはそれらのパスワードを復号化するために復号鍵が必要となります。全サーバで復号鍵ファイルをPgpool-IIの起動ユーザpostgres(Pgpool-II 4.1以降)のホームディレクトリ配下に作成します。(Pgpool-II 4.0 以前のバージョンでは、デフォルトではrootユーザでPgpool-IIを起動する)
[全サーバ]# su - postgres [全サーバ]$ echo '任意の文字列' > ~/.pgpoolkey [全サーバ]$ chmod 600 ~/.pgpoolkey
「pg_enc -m -k /path/to/.pgpoolkey -u ユーザ名 -p」 コマンドを実行すると、ユーザ名とAES256で暗号化したパスワードのエントリがpool_passwdに登録されます。 pool_passwd がまだ存在しなければ、pgpool.confと同じディレクトリ内に作成されます。
[全サーバ]# su - postgres [全サーバ]$ pg_enc -m -k ~/.pgpoolkey -u pgpool -p db password: [pgpoolユーザのパスワード] [全サーバ]$ pg_enc -m -k ~/.pgpoolkey -u postgres -p db password: [postgresユーザのパスワード] # cat /etc/pgpool-II/pool_passwd pgpool:AESheq2ZMZjynddMWk5sKP/Rw== postgres:AESHs/pWL5rtXy2IwuzroHfqg==
デフォルトではwatchdog機能が無効のため、server1、server2及びserver3でwatchdogを有効にします。
use_watchdog = on
アクティブ機が立ち上げる仮想IPをdelegate_IPに指定します。仮想 IP はまだ使われていないIPアドレスを指定してください。server1、server2及びserver3の共通の設定です。
delegate_IP = '192.168.137.150'
仮想IPの起動/停止、ARPリクエストの送信を行う設定パラメータif_up_cmd、if_down_cmd、arping_cmdに、ネットワーク環境に合わせてネットワークインターフェース名を設定します。 今回の例で使ったネットワークインターフェースは「enp0s8」となっています。 if_up/down_cmdやarping_cmdを実行するにはroot権限が必要となりますので、 一般ユーザが実行できるようにip/arpingコマンドにsetuidを設定するか、 Pgpool-II起動ユーザ、デフォルトではpostgresユーザ (Pgpool-II 4.1以降) がパスワードなしにsudoを実行できるように設定する必要があります。
注意: RPMからインストールした場合、postgresユーザがパスワードなしにsudoを介してip/arpingを実行できるように設定済みです。
postgres ALL=NOPASSWD: /sbin/ip postgres ALL=NOPASSWD: /usr/sbin/arping
ここでは、sudoを介して実行するように設定します。
if_up_cmd = '/usr/bin/sudo /sbin/ip addr add $_IP_$/24 dev enp0s8 label enp0s8:0' if_down_cmd = '/usr/bin/sudo /sbin/ip addr del $_IP_$/24 dev enp0s8' arping_cmd = '/usr/bin/sudo /usr/sbin/arping -U $_IP_$ -w 1 -I enp0s8'
注意: /etc/sudoersで「Defaults requiretty」を設定している場合は、pgpoolの起動ユーザがttyなしでif_up_cmd、 if_down_cmd及びarping_cmdコマンドを実行できるように設定する必要があります。
ipコマンドやarpingコマンドのパスがデフォルトのパスと異なる場合、環境に合わせてif_cmd_pathやarping_pathを設定しておいてください。 ただし、 if_up/down_cmd及びarping_cmdに指定したコマンドが"/"で始まる場合、 フルパスとみなしif_cmd_path及びarping_pathの設定を無視します。
if_cmd_path = '/sbin' arping_path = '/usr/sbin'
各watchdogが稼働するサーバ情報を設定しておきます。pgpool_portXには項8.2.6.3のportに設定されているポート番号を指定します。
hostname0 = 'server1' # Host name or IP address of pgpool node # for watchdog connection # (change requires restart) wd_port0 = 9000 # Port number for watchdog service # (change requires restart) pgpool_port0 = 9999 # Port number for pgpool # (change requires restart) hostname1 = 'server2' wd_port1 = 9000 pgpool_port1 = 9999 hostname2 = 'server3' wd_port2 = 9000 pgpool_port2 = 9999
Watchdog死活監視の設定では、死活監視の方法を指定するwd_lifecheck_method、 監視間隔(秒)を指定するwd_intervalを設定します。 この設定例では、死活監視の方法はheartbeatを用います。
wd_lifecheck_method = 'heartbeat' # Method of watchdog lifecheck ('heartbeat' or 'query' or 'external') # (change requires restart) wd_interval = 10 # lifecheck interval (sec) > 0 # (change requires restart)
wd_lifecheck_methodがheartbeatに設定されている場合、 heartbeat通信用の各Pgpool-IIサーバ情報を設定しておきます。
heartbeat_hostname0 = 'server1' # Host name or IP address used # for sending heartbeat signal. # (change requires restart) heartbeat_port0 = 9694 # Port number used for receiving/sending heartbeat signal # Usually this is the same as heartbeat_portX. # (change requires restart) heartbeat_device0 = '' # Name of NIC device (such like 'eth0') # used for sending/receiving heartbeat # signal to/from destination 0. # This works only when this is not empty # and pgpool has root privilege. # (change requires restart) heartbeat_hostname1 = 'server2' heartbeat_port1 = 9694 heartbeat_device1 = '' heartbeat_hostname2 = 'server3' heartbeat_port2 = 9694 heartbeat_device2 = ''
wd_lifecheck_methodがheartbeatに設定されている場合、 障害と判断する秒数を指定するwd_heartbeat_deadtime、 ハートビート信号の送信間隔(秒)を指定するwd_heartbeat_keepaliveを設定します。
wd_heartbeat_keepalive = 2 # Interval time of sending heartbeat signal (sec) # (change requires restart) wd_heartbeat_deadtime = 30 # Deadtime interval for heartbeat signal (sec) # (change requires restart)
Watchdog プロセスが異常終了した場合に、旧アクティブ機に仮想IPが残ったまま、新アクティブ機で同じ仮想IPを起動してしまう可能性があります。 それを防ぐためにwd_escalation_commandに、新アクティブ機以外のPgpool-IIノードの仮想IPを停止させるスクリプトを設定します。
wd_escalation_command = '/etc/pgpool-II/escalation.sh' # Executes this command at escalation on new active pgpool. # (change requires restart)
サンプルスクリプト escalation.sh は /etc/pgpool-II/配下にインストールされています。
[全サーバ]# cp -p /etc/pgpool-II/escalation.sh{.sample,} [全サーバ]# chown postgres:postgres /etc/pgpool-II/escalation.sh
サーバのホスト名、仮想IP、仮想IPを設定するネットワークインターフェース名を環境に合わせて変更してください。
[全サーバ]# vi /etc/pgpool-II/escalation.sh ... PGPOOLS=(server1 server2 server3) VIP=192.168.137.150 DEVICE=enp0s8 ...
注意: Watchdogノードの数が偶数の場合は、enable_consensus_with_half_votesパラメータをonにする必要があります。
注意: use_watchdog = onの場合は、pgpoolノード番号をpgpool_node_idに設定する必要があります。 詳細は項8.2.5を参照ください。
Pgpool-II 4.2以降、ログ収集プロセスが追加されました。 ここでは、ログ収集プロセス(logging_collector)を有効にします。
log_destination = 'stderr' logging_collector = on log_directory = '/var/log/pgpool_log' log_filename = 'pgpool-%Y-%m-%d_%H%M%S.log' log_truncate_on_rotation = on log_rotation_age = 1d log_rotation_size = 10MB
すべてのサーバでログファイルを格納するディレクトリを作成します。
[全サーバ]# mkdir /var/log/pgpool_log/ [全サーバ]# chown postgres:postgres /var/log/pgpool_log/
ここで、server1のpgpool.confの設定は完了です。 server1のpgpool.confを他のノード(server2、server3)にコピーします。
[server1]# scp -p /etc/pgpool-II/pgpool.conf root@server2:/etc/pgpool-II/pgpool.conf [server1]# scp -p /etc/pgpool-II/pgpool.conf root@server3:/etc/pgpool-II/pgpool.conf
Pgpool-IIの設定が完了したら、次にPgpool-IIを起動します。Pgpool-IIを起動する前に、バックエンドのPostgreSQLをあらかじめ起動する必要があります。また、PostgreSQLを停止する場合、Pgpool-IIを先に停止する必要があります。
Pgpool-IIの起動
前述の事前設定の章でPgpool-IIの自動起動が設定済なので、ここでシステム全体を再起動するか、以下のコマンドを実行してください。
# systemctl start pgpool.service
Pgpool-IIの停止
# systemctl stop pgpool.service
これから、動作確認を行います。server1で以下のコマンドでPostgreSQLを起動します。
[server1]# su - postgres [server1]$ /usr/pgsql-13/bin/pg_ctl start -D $PGDATA
server1、server2、server3で以下のコマンドでPgpool-IIを起動します。
# systemctl start pgpool.service
まず、Pgpool-IIのオンラインリカバリ機能を利用し、スタンバイサーバを構築します。pcp_recovery_nodeコマンドで実行されるrecovery_1st_stage_commandパラメータに指定したrecovery_1st_stageとpgpool_remote_startスプリクトが実行されるので、この 2つのスクリプトが現在稼働中のプライマリサーバserver1のデータベースクラスタの下に存在することを確認します。
# pcp_recovery_node -h 192.168.137.150 -p 9898 -U pgpool -n 1 Password: pcp_recovery_node -- Command Successful # pcp_recovery_node -h 192.168.137.150 -p 9898 -U pgpool -n 2 Password: pcp_recovery_node -- Command Successful
server2とserver3のPostgreSQLがスタンバイとして起動されていることを確認します。
# psql -h 192.168.137.150 -p 9999 -U pgpool postgres -c "show pool_nodes" Password for user pgpool: node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay | replication_state | replication_sync_state | last_status_change ---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------+-------------------+------------------------+--------------------- 0 | server1 | 5432 | up | 0.333333 | primary | 0 | false | 0 | | | 2019-08-06 11:13:17 1 | server2 | 5432 | up | 0.333333 | standby | 0 | true | 0 | streaming | async | 2019-08-06 11:13:25 2 | server3 | 5432 | up | 0.333333 | standby | 0 | false | 0 | streaming | async | 2019-08-06 11:14:20 (3 rows)
pcp_watchdog_infoでPgpool-IIのwatchdogの情報を確認します。最初に起動したPgpool-IIが「LEADER」になります。
# pcp_watchdog_info -h 192.168.137.150 -p 9898 -U pgpool Password: 3 YES server1:9999 Linux server1 server1 server1:9999 Linux server1 server1 9999 9000 4 LEADER #最初に起動されたサーバがLEADERになる server2:9999 Linux server2 server2 9999 9000 7 STANDBY #スタンバイとして稼働 server3:9999 Linux server3 server3 9999 9000 7 STANDBY #スタンバイとして稼働
アクティブであるserver1のPgpool-IIを停止し、server2またはserver3がスタンバイからアクティブに昇格することを確認します。server1を停止する方法はPgpool-IIを停止する、またはマシンをシャットダウンします。ここでは、Pgpool-IIを停止します。
[server1]# systemctl stop pgpool.service # pcp_watchdog_info -p 9898 -h 192.168.137.150 -U pgpool Password: 3 YES server2:9999 Linux server2 server2 server2:9999 Linux server2 server2 9999 9000 4 LEADER #server2がアクティブに昇格 server1:9999 Linux server1 server1 9999 9000 10 SHUTDOWN #server1が停止された server3:9999 Linux server3 server3 9999 9000 7 STANDBY #スタンバイとして稼働
先ほど停止したPgpool-IIを再起動し、スタンバイとして起動したことを確認します。
[server1]# systemctl start pgpool.service [server1]# pcp_watchdog_info -p 9898 -h 192.168.137.150 -U pgpool Password: 3 YES server2:9999 Linux server2 server2 server2:9999 Linux server2 server2 9999 9000 4 LEADER server1:9999 Linux server1 server1 9999 9000 7 STANDBY server3:9999 Linux server3 server3 9999 9000 7 STANDBY
psqlで仮想IPに接続し、バックエンドの情報を確認します。
# psql -h 192.168.137.150 -p 9999 -U pgpool postgres -c "show pool_nodes" Password for user pgpool: node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay | replication_state | replication_sync_state | last_status_change ---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------+-------------------+------------------------+--------------------- 0 | server1 | 5432 | up | 0.333333 | primary | 0 | false | 0 | | | 2019-08-06 11:13:17 1 | server2 | 5432 | up | 0.333333 | standby | 0 | true | 0 | streaming | async | 2019-08-06 11:13:25 2 | server3 | 5432 | up | 0.333333 | standby | 0 | false | 0 | streaming | async | 2019-08-06 11:14:20 (3 rows)
次にプライマリであるserver1のPostgreSQLを停止し、フェイルオーバするかどうか確認してみます。
[server1]$ pg_ctl -D /var/lib/pgsql/13/data -m immediate stop
ノード1を停止後、フェイルオーバが発生し、server2がプライマリに昇格したことを確認します。
# psql -h 192.168.137.150 -p 9999 -U pgpool postgres -c "show pool_nodes" Password for user pgpool: node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay | replication_state | replication_sync_state | last_status_change ---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------+-------------------+------------------------+--------------------- 0 | server1 | 5432 | down | 0.333333 | standby | 0 | false | 0 | | | 2019-08-06 11:36:03 1 | server2 | 5432 | up | 0.333333 | primary | 0 | true | 0 | | | 2019-08-06 11:36:03 2 | server3 | 5432 | up | 0.333333 | standby | 0 | false | 0 | streaming | async | 2019-08-06 11:36:15 (3 rows)
server3が新しいプライマリserver2のスタンバイとして起動されています。
[server3]# psql -h server3 -p 5432 -U pgpool postgres -c "select pg_is_in_recovery()" pg_is_in_recovery ------------------- t [server2]# psql -h server2 -p 5432 -U pgpool postgres -c "select pg_is_in_recovery()" pg_is_in_recovery ------------------- f [server2]# psql -h server2 -p 5432 -U pgpool postgres -c "select * from pg_stat_replication" -x -[ RECORD 1 ]----+------------------------------ pid | 11059 usesysid | 16392 usename | repl application_name | server3 client_addr | 192.168.137.103 client_hostname | client_port | 48694 backend_start | 2019-08-06 11:36:07.479161+09 backend_xmin | state | streaming sent_lsn | 0/75000148 write_lsn | 0/75000148 flush_lsn | 0/75000148 replay_lsn | 0/75000148 write_lag | flush_lag | replay_lag | sync_priority | 0 sync_state | async reply_time | 2019-08-06 11:42:59.823961+09
次に、Pgpool-IIのオンラインリカバリ機能を利用し、先ほど停止した旧プライマリサーバをスタンバイとして復旧させます。pcp_recovery_nodeコマンドで実行されるrecovery_1st_stage_commandパラメータに指定したrecovery_1st_stageとpgpool_remote_startスプリクトが現在稼働中のプライマリサーバserver2のデータベースクラスタの下に存在することを確認します。
# pcp_recovery_node -h 192.168.137.150 -p 9898 -U pgpool -n 0 Password: pcp_recovery_node -- Command Successful
ノード1がスタンバイとして起動されたことを確認します。
# psql -h 192.168.137.150 -p 9999 -U pgpool postgres -c "show pool_nodes" Password for user pgpool: node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay | replication_state | replication_sync_state | last_status_change ---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------+-------------------+------------------------+--------------------- 0 | server1 | 5432 | up | 0.333333 | standby | 0 | false | 0 | streaming | async | 2019-08-06 11:48:05 1 | server2 | 5432 | up | 0.333333 | primary | 0 | false | 0 | | | 2019-08-06 11:36:03 2 | server3 | 5432 | up | 0.333333 | standby | 0 | true | 0 | streaming | async | 2019-08-06 11:36:15 (3 rows)
以上で、動作確認が完了です。