PG-REXでPacemakerによるPostgreSQLのHAクラスタ構成を構築しよう

この記事では、PacemakerによるPostgreSQLの高可用性ソリューションPG-REXの概要と構築手順について紹介します。

# PG-REXとは

PG-REX (ピージーレックスと読む) はPacemakerによるPostgreSQLの高可用性ソリューションです。あくまでソリューションなので、PG-REXという名前のソフトはなく、マニュアルに従って構築、運用するシステムをPG-REXと呼びます。

# PG-REXの構成要素

PG-REXの構成要素は以下です。

| 名前 | 開発元 | 入手先 | 説明 |
|-|-|-|-|
| [PG-REX利用マニュアル](https://github.com/ossc-db/PG-REX-docs) | [NTT OSSセンタ](http://www.oss.ecl.ntt.co.jp/ossc/) | 最新版は[GitHub](https://github.com/ossc-db/PG-REX-tools/releases)、古い版はOSDNミラー ([IIJ](https://ftp.iij.ad.jp/pub/osdn.jp/pg-rex/)、[JAIST](https://ftp.jaist.ac.jp/pub/osdn.net/pg-rex/)) | PG-REXの構築や運用などについて書かれたマニュアル |
| [PG-REX運用補助ツール](https://github.com/ossc-db/PG-REX-tools) | 同上 | 同上 | PG-REXの起動や停止、高速スイッチオーバなど、運用しやすくするツール |
| [Pacemaker](https://clusterlabs.org/projects/pacemaker/) | [ClusterLabs](https://clusterlabs.org/) | High Availabilityリポジトリ、RHELの場合はHigh Availability Add-Onが必要 | HAクラスタソフト、狭義にはクラスタリソースマネージャ、広義にはほかの関連ソフトを含めてそう呼ぶ |
| [Pacemaker追加パッケージ](https://github.com/linux-ha-japan/pm_extra_tools) | [Linux-HA Japan](https://linux-ha-japan.github.io/) | 最新版は[GitHub](https://github.com/linux-ha-japan/pm_extra_tools/releases)、古い版はOSDNミラー ([IIJ](https://ftp.iij.ad.jp/pub/osdn.jp/linux-ha/)、[JAIST](https://ftp.jaist.ac.jp/pub/osdn.net/linux-ha/)) | リソース定義生成ツール、PostgreSQL/HULFT用リソースエージェントを含む |
| [PostgreSQL](https://www.postgresql.org/) | PostgreSQL Global Development Group | [PostgreSQLリポジトリ](https://www.postgresql.org/download/linux/redhat/) | リレーショナルデータベース管理システム |

# PG-REXのシステム構成

PG-REXの標準的なシステム構成は以下です。

![PG-REXのシステム構成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160683/a252bcf2-93bb-4613-9d54-e24430918142.png)

PostgreSQLはプライマリ、スタンバイからなるレプリケーション構成です。プライマリは参照と更新、スタンバイは参照のみを受けつけます。プライマリで更新されたデータはデータ転送用LANを通じてスタンバイに複製されます。各ノードへの接続はサービス提供用LAN上の仮想IPを通じて透過的に行われます。

Pacemakerはインターコネクト用LANをつうノード間で連携して、PostgreSQLや仮想IPなどのリソースを監視します。リソースの障害を検知すると別ノードに切り替えます。これをフェイルオーバと呼びます。ただ、ノード間の通信が途絶えると、相手ノードに障害が発生したと見なし、同じリソースを両ノードで起動して、スプリットブレンと呼ばれる競合状態になる可能性があります。

そうしたスプリットブレインを防ぐため、障害の発生したノードを強制的にクラスタから切り離します。これをフェンシングと呼び、とくにサーバ再起動、停止を伴うものをSTONITHと呼びます。STONITHはハードや仮想環境によっていろいろな方式があって、IPMIはハードで行う一般的な方式の１つです。

# PG-REXとほかの構成との違い

PG-REXとほかのPacemakerによるPostgreSQLのHAクラスタ構成とのおもな違いは以下です。

<dl>
  <dt>PG-REX独自ツールの使用が必要</dt>
  <dd>とくにリソース定義はMS Excelで環境定義書を編集して、独自ツールで変換、反映する必要があります。</dd>
  <dt>同期レプリケーションのみに対応</dt>
  <dd>非同期レプリケーションのほか、共有ディスクやDRBDにも対応していません。</dd>
  <dt>STONITHの設定が必要</dt>
  <dd>STONITHはIPMI以外の方式でも構いません。</dd>
  <dt>ノード間の通信経路が3本以上必要</dt>
  <dd>少なくともサービス提供用、インターコネクト用、データ転送・インターコネクト兼用に分けて、インターコネクト用は冗長化する必要があります。</dd>
  <dt>2ノードのみに対応</dt>
  <dd>ノード数が定足数 (クォーラム) を満たさず、スプリットブレイン時に多数決できません。</dd>
</dl>

# PG-REXの構築

PG-REXの構築手順はマニュアルに書いてあります。マニュアルはPG-REXの配布物に含まれていて、[こちら](https://github.com/ossc-db/PG-REX-tools/releases)からダウンロードできます。tar.gzファイル内のzipファイルに入っていて、日本語ファイル名のMS Word形式です。

* :file_folder: pg-rex17-1.0-1.tar.gz
  * :file: README.txt
  * :file_folder: PG-REX17-1.0.doc.zip
    * :file: PG-REX17利用マニュアル_第1.0.0版(公開用利用者マニュアル).docx
    * :file: PG-REX17環境定義書_第1.0版.xlsx
  * :file: Net_OpenSSH-0.62-1.el9.x86_64.rpm
  * :file: pg-rex_operation_tools_script-17.0-1.el9.noarch.rpm

Rocky Linux 9上でPacemaker 2.1、PostgreSQL 17、STONITHにIPMIを使って、PG-REXを構築する手順は以下です。IPMIは基本的にオンプレ環境でサーバにIPMI対応の制御チップが必要です。IPMIが使えなければ、ハードや仮想環境に応じた方式を設定する必要があります。

ちなみに、WSL2上のVirtualBoxでPG-REXを構築するAnsibleプレイブックを[こちら](https://github.com/tom-sato/ansible-pg_rex)で公開していて、そちらではVirtualBMCを使ってIPMI経由で仮想マシンを制御しています。

### Pacemakerのインストール

1. Pacemakerをインストールします。pcsはPacemaker設定ツール、fence-agents-allはフェンスエージェントをまとめたパッケージです。

   ```shell-session:両ノードで実行
   # dnf -y --enablerepo=highavailability install pacemaker pcs fence-agents-all
   Rocky Linux 9 - High Availability                67 kB/s | 258 kB     00:03
   メタデータの期限切れの最終確認: 0:00:02 前の 2025年04月20日 14時31分37秒 に実施しました。
   依存関係が解決しました。
   (省略)
     unbound-libs-1.16.2-8.el9_5.1.x86_64
   
   完了しました!
   ```

1. pcsdを起動して、自動起動を有効化します。pcsdはpcsのコマンドを処理するデーモンです。

   ```shell-session:両ノードで実行
   # systemctl start pcsd
   # systemctl enable pcsd
   Created symlink /etc/systemd/system/multi-user.target.wants/pcsd.service → /usr/lib/systemd/system/pcsd.service.
   ```

1. haclusterユーザのパスワードを設定します。haclusterユーザはpcsdでノード間の認証に使うユーザです。パスワードは両ノードで同じにする必要があります。

   ```shell-session:いずれかのノードで実行
   # passwd hacluster
   Changing password for user hacluster.
   New password: (パスワードを入力)
   Retype new password: (パスワードを再入力)
   passwd: all authentication tokens updated successfully.
   ```

1. pcsdでノード間の認証を行います。各ノードのホスト名、運用管理用IPを指定します。最初にhaclusterユーザのユーザ名、パスワードを入力します。

   ```shell-session:両ノードで実行
   # pcs host auth node-1 addr=192.168.60.101 node-2 addr=192.168.60.102
   Username: hacluster
   Password: (パスワードを入力)
   node-2: Authorized
   node-1: Authorized
   ```

1. Pacemakerの設定を行って、内部プロセスのクラッシュ時に再起動せず、即フェンシングするようにします。行頭の数字は行番号を表します。

   ```shell-session:両ノードで実行
   # vi /etc/sysconfig/pacemaker
      179  PCMK_fail_fast="yes"
   ```

1. logindの設定を行って、フェンシングを高速化するため、電源ボタンによるサーバ停止処理を無効化し、設定を反映するため、logindを再起動します。

   ```shell-session:両ノードで実行
   # vi /etc/systemd/logind.conf
       25  HandlePowerKey=ignore
   # systemctl restart systemd-logind
   ```

### PostgreSQLのインストール

1. PostgreSQLリポジトリをインストールします。

   ```shell-session:両ノードで実行
   # dnf -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
   メタデータの期限切れの最終確認: 0:06:43 前の 2025年04月20日 14時30分58秒 に実施しました。
   pgdg-redhat-repo-latest.noarch.rpm               22 kB/s |  12 kB     00:00
   依存関係が解決しました。
   (省略)
     pgdg-redhat-repo-42.0-50PGDG.noarch
   
   完了しました!
   ```

1. PostgreSQLをインストールします。

   ```shell-session:両ノードで実行
   # dnf -y install postgresql17-server postgresql17-contrib
   PostgreSQL common RPMs for RHEL / Rocky / AlmaL 1.2 kB/s | 659  B     00:00
   PostgreSQL common RPMs for RHEL / Rocky / AlmaL 1.1 MB/s | 2.4 kB     00:00
   GPG 鍵 0x08B40D20 をインポート中:
   (省略)
     postgresql17-server-17.4-1PGDG.rhel9.x86_64
   
   完了しました!
   ```

1. PostgreSQLのデータディレクトリ、WALディレクトリ、アーカイブディレクトリを作成して、PostgreSQLのスーパーユーザpostgresのみ読み書き可能にします。

   ```shell-session:両ノードで実行
   # mkdir -p /dbfp/pgdata/data /dbfp/pgwal/pg_wal /dbfp/pgarch/arc1
   # chown -R postgres:postgres /dbfp
   # chmod -R 700 /dbfp
   ```

1. postgresユーザに切り替わります。

   ```shell-session:両ノードで実行
   # su - postgres
   ```

1. postgresユーザの環境変数を設定して、設定を反映します。

   ```shell-session:両ノードで実行
   $ vi ~/.pgsql_profile
   export PATH=/usr/pgsql-17/bin:$PATH
   export MANPATH=/usr/pgsql-17/share/man:$MANPATH
   export PGDATA=/dbfp/pgdata/data
   $ . ~/.pgsql_profile
   ```

1. データベースクラスタを作成します。途中でデータベース上のpostgresユーザに設定するパスワードを入力します。

   ```shell-session:プライマリで実行
   $ initdb -E UTF8 -k --no-locale -W -X /dbfp/pgwal/pg_wal
   データベースシステム内のファイルの所有者はユーザー"postgres"となります。
   このユーザーをサーバープロセスの所有者とする必要があります。
   
   データベースクラスタはロケール"C"で初期化されます。
   デフォルトのテキスト検索構成は english に設定されます。
   
   データページのチェックサムは有効です。
   
   新しいスーパーユーザーのパスワードを入力してください: (パスワードを入力)
   再入力してください: (パスワードを再入力)
   
   ディレクトリ/dbfp/pgdata/dataの権限を設定しています ... ok
   ディレクトリ/dbfp/pgwal/pg_walの権限を設定しています ... ok
   サブディレクトリを作成しています ... ok
   動的共有メモリの実装を選択しています ... posix
   デフォルトの"max_connections"を選択しています ... 100
   デフォルトの"shared_buffers"を選択しています ... 128MB
   デフォルトの時間帯を選択しています ... Asia/Tokyo
   設定ファイルを作成しています ... ok
   ブートストラップスクリプトを実行しています ... ok
   ブートストラップ後の初期化を実行しています ... ok
   データをディスクに同期しています ... ok
   
   initdb: 警告: ローカル接続に対して"trust"認証を有効にします
   initdb: ヒント: pg_hba.confを編集する、もしくは、次回initdbを実行する時に -A オプション、あるいは --auth-local および --auth-host オプションを使用することで変更できます。
   
   成功しました。以下のようにしてデータベースサーバーを起動できます:
   
       pg_ctl -D /dbfp/pgdata/data -l ログファイル start
   
   ```

1. PostgreSQLの設定を行います。行頭の数字は行番号を表します。

   ```shell-session:プライマリで実行
   $ vi /dbfp/pgdata/data/postgresql.conf
       60  listen_addresses = '*'
       64  port = 5432
       67  superuser_reserved_connections = 10
       97  password_encryption = scram-sha-256
      221  wal_level = replica
      226  synchronous_commit = on
      268  archive_mode = always
      273  archive_command = '/bin/cp %p /dbfp/pgarch/arc1/%f'
      329  max_wal_senders = 10
      331  max_replication_slots = 10
      333  wal_keep_size = 512MB
      335  wal_sender_timeout = 20s
      356  hot_standby = on
      358  max_standby_archive_delay = -1
      361  max_standby_streaming_delay = -1
      368  hot_standby_feedback = on
      370  wal_receiver_timeout = 20s
      817  restart_after_crash = off
   ```

1. データベースサーバを一時的に起動して、レプリケーション接続用ユーザrepuserを作成し、パスワードを設定します。

   ```shell-session:プライマリで実行
   $ pg_ctl start
   サーバーの起動完了を待っています....2025-04-20 15:57:34.740 JST [41657] LOG:  redirecting log output to logging collector process
   2025-04-20 15:57:34.740 JST [41657] HINT:  Future log output will appear in directory "log".
   完了
   サーバー起動完了
   $ psql
   psql (17.4)
   "help"でヘルプを表示します。
   
   postgres=# CREATE ROLE repuser LOGIN REPLICATION;
   CREATE ROLE
   postgres=# \password repuser
   ユーザー"repuser"の新しいパスワードを入力してください: (パスワードを入力)
   もう一度入力してください: (パスワードを再入力)
   postgres=# \q
   $ pg_ctl stop
   サーバー停止処理の完了を待っています....完了
   サーバーは停止しました
   ```

1. クライアント認証の設定を行って、サービス提供用LANを通じたすべての接続と、データ転送用LANを通じたレプリケーション接続をパスワード認証で受けつけるようにします。

   ```shell-session:プライマリで実行
   $ vi /dbfp/pgdata/data/pg_hba.conf
      127  host    all             all             192.168.56.0/24         scram-sha-256
      128  host    replication     repuser         192.168.57.101/32       scram-sha-256
      129  host    replication     repuser         192.168.57.102/32       scram-sha-256
   ```

1. パスワードファイルを作成して、データ転送用LANを通じたレプリケーション接続はパスワード不要にし、postgresユーザのみ読み書き可能にします。

   ```shell-session:両ノードで実行
   $ vi ~/.pgpass
   192.168.57.111:5432:replication:repuser:reppasswd
   (ノード1の場合)
   192.168.57.102:5432:replication:repuser:reppasswd
   (ノード2の場合)
   192.168.57.101:5432:replication:repuser:reppasswd
   $ chmod 600 ~/.pgpass
   ```

1. rootユーザに戻ります。

   ```shell-session:両ノードで実行
   $ exit
   logout
   ```

### IPMIの動作確認

1. IPMI用IPに接続して、電源の状態を取得できるか確認します。

   ```shell-session:いずれかのノードで実行
   # ipmitool -I lanplus -H 172.23.135.101 -U Administrator -P adminpasswd chassis power status
   Chassis Power is on
   # ipmitool -I lanplus -H 172.23.135.102 -U Administrator -P adminpasswd chassis power status
   Chassis Power is on
   ```

### Pacemaker追加パッケージのインストール

1. Pacemaker追加パッケージをインストールします。

   ```shell-session:両ノードで実行
   # dnf -y install https://github.com/linux-ha-japan/pm_extra_tools/releases/download/pm_extra_tools-1.6/pm_extra_tools-1.6-1.el9.noarch.rpm
   メタデータの期限切れの最終確認: 3:01:32 前の 2025年04月20日 14時39分56秒 に実施しました。
   pm_extra_tools-1.6-1.el9.noarch.rpm              87 kB/s | 150 kB     00:01
   依存関係が解決しました。
   (省略)
     pm_extra_tools-1.6-1.el9.noarch
   
   完了しました!
   ```

### PG-REX運用補助ツールのインストール

1. PG-REXの配布物に含まれるパッケージを両ノードに転送します。

1. パッケージをインストールします。ほかに運用補助ツールが内部的に使うlsof、perl-File-Compareもインストールします。

   ```shell-session:両ノードで実行
   # dnf -y install pg-rex_operation_tools_script-17.0-1.el9.noarch.rpm \
     Net_OpenSSH-0.62-1.el9.x86_64.rpm lsof perl-File-Compare
   メタデータの期限切れの最終確認: 0:12:36 前の 2025年04月20日 20時35分45秒 に実施しました。
   依存関係が解決しました。
   ================================================================================
   (省略)
     pg-rex_operation_tools_script-17.0-1.el9.noarch
   
   完了しました!
   ```

1. 運用補助ツールの設定を行います。D_LAN_IPAddressパラメータにはデータ転送用IPをカンマ区切りで、IC_LAN_IPAddressパラメータにはインターコネクト用IPを系統ごとにカッコで囲んでカンマ区切りで指定します。

   ```shell-session:両ノードで実行
   # vi /etc/pg-rex_tools.conf
     1  D_LAN_IPAddress = 192.168.57.101,192.168.57.102
     5  IC_LAN_IPAddress = (192.168.58.101,192.168.58.102),(192.168.59.101,192.168.59.102)
     9  Archive_dir = /dbfp/pgarch/arc1
    18  PGPATH = /usr/pgsql-17/bin
    22  PEER_NODE_SSH_PASS_MODE = nopass
    34  BACKUP_NODE_SSH_PASS_MODE = nopass
   ```

1. 運用補助ツールは内部的にデータ転送LANを通じてSSH接続しますが、その際、接続するか聞かれて処理が止まらないように、接続先の公開鍵を取得して、登録します。

   ```shell-session:両ノードで実行
   (ノード1の場合)
   # ssh-keyscan 192.168.57.102 >> ~/.ssh/known_hosts
   (ノード2の場合)
   # ssh-keyscan 192.168.57.101 >> ~/.ssh/known_hosts
   ```

1. 運用補助ツールの内部的なSSH接続時にパスワードを入力しないで済むように、rootユーザの秘密鍵と公開鍵を生成して、公開鍵を接続先に登録します。

   ```shell-session:両ノードで実行
   # ssh-keygen
   Generating public/private rsa key pair.
   Enter file in which to save the key (/root/.ssh/id_rsa): (何も入力せず、Enterキーを入力)
   Enter passphrase (empty for no passphrase): (何も入力せず、Enterキーを入力)
   Enter same passphrase again: (何も入力せず、Enterキーを入力)
   Your identification has been saved in /root/.ssh/id_rsa
   Your public key has been saved in /root/.ssh/id_rsa.pub
   The key fingerprint is:
   SHA256:yK5kF+s79hzY83owMV6BpCSNpx15JY0O2daKRQuMZVA root@node-1
   The key's randomart image is:
   +---[RSA 3072]----+
   |    oOE*+*.      |
   |    o+OoBo+      |
   |     +.O.. .     |
   |    ..o.= .      |
   |      +.S+       |
   |     . =+        |
   |    o = +o       |
   |   o +o. +.      |
   |    ..o++o.      |
   +----[SHA256]-----+
   (ノード1の場合)
   # ssh-copy-id node-2
   (ノード2の場合)
   # ssh-copy-id node-1
   /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
   The authenticity of host 'node-2 (192.168.56.102)' can't be established.
   ED25519 key fingerprint is SHA256:6ppZrEbtEpqZlR/l62uD+1gX2u1hxkEIRV8YbA82bWU.
   This host key is known by the following other names/addresses:
       ~/.ssh/known_hosts:3: 192.168.57.102
   Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
   /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
   /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
   root@node-2's password: (パスワードを入力)
   
   Number of key(s) added: 1
   
   Now try logging into the machine, with:   "ssh 'node-2'"
   and check to make sure that only the key(s) you wanted were added.
   
   ```

### リソースの設定

1. PG-REXの配布物に含まれる環境定義書をMS Excelで編集して、CSV形式で保存し、プライマリに転送します。

   <details>
     <summary>記入例</summary>
      
     * Primitiveリソース
       * ipaddr-primary
         * ip: 192.168.56.111 (プライマリ接続用仮想IP)
         * nic: eth1
         * cidr_netmask: 24
       * ipaddr-replication
         * ip: 192.168.57.111 (レプリケーション接続用仮想IP)
         * nic: eth2
         * cidr_netmask: 24 
       * ipaddr-standby
         * ip: 192.168.56.112 (スタンバイ接続用仮想IP)
         * nic: eth1
         * cidr_netmask: 24
       * pgsql
         * pgctl: /usr/pgsql-17/bin/pg_ctl
         * psql: /usr/pgsql-17/bin/psql
         * pgdata: /dbfp/pgdata/data
         * pgport: 5432
         * node_list: node-1 node-2
         * master_ip: 192.168.57.111 (レプリケーション接続用仮想IP)
         * restore_command: /bin/cp /dbfp/pgarch/arc1/%f %p
         * repuser: repuser
       * ping
         * host_list: 10.0.2.2 (デフォルトゲートウェイIP)
     * STONITHリソース 
       * fence1-ipmilan
         * pcmk_host_list: node-1
         * ip: 172.23.135.101 (IPMI接続用IP)
         * username: Administrator (IPMI接続用ユーザ名)
         * password: adminpasswd (IPMI接続用パスワード)
       * fence2-ipmilan
         * pcmk_host_list: node-2
         * ip: 172.23.135.102 (IPMI接続用IP)
         * username: Administrator (IPMI接続用ユーザ名)
         * password: adminpasswd (IPMI接続用パスワード)
     * リソース配置制約 (ノード)
       * fence1-ipmilan
         * avoids: node-1
       * fence1-ipmilan
         * avoids: node-2
   </details>

1. 環境定義書をCIBと呼ばれるXML形式に変換します。

   ```shell-session:プライマリで実行
   # pm_pcsgen ./pm_pcsgen_env.csv
   pm_pcsgen_env.xml (CIB), pm_pcsgen_env.sh (PCS) を出力しました。
   ```

### PG-REXの起動

1. プライマリを起動します。環境定義書から変換したXMLファイルを指定します。

   ```shell-session:プライマリで実行
   # pg-rex_primary_start ./pm_pcsgen_env.xml
   1. Pacemaker および Corosync が停止していることを確認
   ...[OK]
   2. 稼働中の Primary が存在していないことを確認
   ...[OK]
   3. 起動禁止フラグの存在を確認
   ...[OK]
   4. HAクラスタ の作成
   Destroying cluster on hosts: 'node-1', 'node-2'...
   node-1: Successfully destroyed cluster
   node-2: Successfully destroyed cluster
   Requesting remove 'pcsd settings' from 'node-1', 'node-2'
   node-1: successful removal of the file 'pcsd settings'
   node-2: successful removal of the file 'pcsd settings'
   Sending 'corosync authkey', 'pacemaker authkey' to 'node-1', 'node-2'
   node-1: successful distribution of the file 'corosync authkey'
   node-1: successful distribution of the file 'pacemaker authkey'
   node-2: successful distribution of the file 'corosync authkey'
   node-2: successful distribution of the file 'pacemaker authkey'
   Sending 'corosync.conf' to 'node-1', 'node-2'
   node-1: successful distribution of the file 'corosync.conf'
   node-2: successful distribution of the file 'corosync.conf'
   Cluster has been successfully set up.
   ...[OK]
   5. Pacemaker 起動
   Starting Cluster...
   Waiting for node(s) to start...
   Started
   ...[OK]
   6. リソース定義 xml ファイルの反映
   CIB updated
   ...[OK]
   Warning: If node(s) 'node-2' are not powered off or they do have access to shared resources, data corruption and/or cluster failure may occur
   Warning: If node 'node-2' is not powered off or it does have access to shared resources, data corruption and/or cluster failure may occur
   Quorum unblocked
   Waiting for nodes canceled
   7. Primary の起動確認
   ...[OK]
   ノード(node-1)が Primary として起動しました
   ```

1. スタンバイを起動します。途中でスタンバイの起動方法を聞かれるので、b (ベースバックアップを取得して起動) を入力します。

   ```shell-session:スタンバイで実行
   # pg-rex_standby_start
   1. Pacemaker および Corosync が停止していることを確認
   ...[OK]
   2. 稼働中の Primary が存在していることを確認
   ...[OK]
   3. 起動禁止フラグが存在しないことを確認
   ...[OK]
   4. DB クラスタの状態を確認
   4.1 現在のDBクラスタのまま起動が可能か確認
   DB クラスタが存在していません
   ...[NG]
   4.2 巻き戻しを実行することで起動が可能か確認
   DB クラスタが存在していません
   ...[NG]
   4.3 ベースバックアップを取得することが可能か確認
   ...[OK]
   
   以下の方法で起動が可能です
   b) ベースバックアップを取得してStandbyを起動
   q) Standbyの起動を中止する
   起動方法を選択してください(b/q) b
   5. IC-LAN が接続されていることを確認
   ...[OK]
   6. Primary からベースバックアップ取得
   NOTICE:  all required WAL segments have been archived
   23192/23192 kB (100%), 1/1 テーブル空間
   ...[OK]
   7. Primary のアーカイブディレクトリと同期
   000000010000000000000002.partial
   00000002.history
   000000020000000000000003.00000028.backup
   000000010000000000000001
   000000020000000000000002
   000000020000000000000003
   ...[OK]
   8. Standby の起動 (アーカイブリカバリ対象 WAL セグメント数: 1)
   Starting Cluster...
   ...[OK]
   9. Standby の起動確認
   ...[OK]
   ノード(node-2)が Standby として起動しました
   ```

1. クラスタが正常に稼働しているか確認します。

   ```shell-session:いずれかのノードで実行
   # pcs status
   Cluster name: pgrex_cluster
   Cluster Summary:
     * Stack: corosync (Pacemaker is running)
     * Current DC: node-1 (version 2.1.8-3.el9-3980678f0) - partition with quorum
     * Last updated: Sun Apr 20 23:08:51 2025 on node-1
     * Last change:  Sun Apr 20 23:08:25 2025 by root via root on node-1
     * 2 nodes configured
     * 11 resource instances configured
   
   Node List:
     * Online: [ node-1 node-2 ]
   
   Full List of Resources:
     * Clone Set: pgsql-clone [pgsql] (promotable):
       * Promoted: [ node-1 ]
       * Unpromoted: [ node-2 ]
     * Resource Group: primary-group:
       * ipaddr-primary    (ocf:heartbeat:IPaddr2):         Started node-1
       * ipaddr-replication        (ocf:heartbeat:IPaddr2):         Started node-1
     * ipaddr-standby      (ocf:heartbeat:IPaddr2):         Started node-2
     * Clone Set: ping-clone [ping]:
       * Started: [ node-1 node-2 ]
     * Clone Set: storage-mon-clone [storage-mon]:
       * Started: [ node-1 node-2 ]
     * fence1-ipmilan      (stonith:fence_ipmilan):         Started node-2
     * fence2-ipmilan      (stonith:fence_ipmilan):         Started node-1
   
   Daemon Status:
     corosync: active/disabled
     pacemaker: active/disabled
     pcsd: active/enabled
   ```

これで、PG-REXの構築は完了です。

# 終わりに

この記事では、PG-REXの概要と構築手順について紹介しました。PostgreSQLやPacemakerは使ったことがあっても、PG-REXはあまり知らなかった人もいると思いますが、この記事を通じてPG-REXもPacemakerによるPostgreSQLのHAクラスタ構成で、いくつか制限はあるものの、基本は同じだと知ってもらえるとよいです。

PG-REXにはほかにも高速スイッチオーバやアーカイブ削除の独自ツールがあって、マニュアルに運用や障害対応についても書いてあるので、今後、時間があればそちらも紹介したいと思います。