<!-- doc/src/sgml/example-cluster.sgml -->

<sect1 id="example-cluster">
 <title><productname>Pgpool-II</productname> + Watchdogの構築の例</title>
 <para>
  ここでは、ストリーミングレプリケーション構成の<productname>PostgreSQL</productname>を<productname>Pgpool-II</productname>で管理するシステムの構成例を示します。
  この設定例では、3台の<productname>Pgpool-II</productname>を使って<productname>PostgreSQL</productname>（プライマリ1台、スタンバイ2台）を管理し、単一障害点やスプリットブレインの起きない堅牢なクラスタを運用することが可能です。
 </para>
 <para>
  この設定例では<emphasis><productname>PostgreSQL</productname> 18</emphasis>を使っています。
 </para>
 <sect2 id="example-cluster-requirement">
  <title>前提条件</title>
  <para>
   <productname>Pgpool-II</productname>サーバと<productname>PostgreSQL</productname>サーバが
   同じサブネットにあることを前提とします。
  </para>
 </sect2>

 <sect2 id="example-cluster-structure">
  <title>全体構成</title>
  <para>
   今回は、Linuxサーバを3台用意し、それぞれのホスト名は<literal>server1</literal>、<literal>server2</literal>、<literal>server3</literal>とします。
   使用するOSはすべて<emphasis>Rocky Linux 10</emphasis>とします。
   それぞれのサーバに<productname>PostgreSQL</productname>と<productname>Pgpool-II</productname>をインストールします。
   3台の<productname>PostgreSQL</productname>がストリーミングレプリケーション構成になります。全体構成図は以下の通りです。
  </para>
  <para>
   <figure>
    <title>全体構成図</title>
    <mediaobject>
     <imageobject>
      <imagedata fileref="cluster_40.gif">
     </imageobject>
    </mediaobject>
   </figure>
  </para>
  <note>
   <para>
    「Leader」「Standby」「Primary」「Standby」といった役割は固定されているものではなく、運用と共に変化することがあります。
   </para>
  </note>

  <table id="example-cluster-table-ip">
   <title>ホスト名とIPアドレス</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>ホスト名</entry>
      <entry>IPアドレス</entry>
      <entry>仮想IP</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>server1</entry>
      <entry>192.168.100.51</entry>
      <entry morerows="2">192.168.100.50</entry>
     </row>
     <row>
      <entry>server2</entry>
      <entry>192.168.100.52</entry>
     </row>
     <row>
      <entry>server3</entry>
      <entry>192.168.100.53</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <table id="example-cluster-table-postgresql-config">
   <title>PostgreSQLのバージョンと設定情報</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>項目</entry>
      <entry>値</entry>
      <entry>説明</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>PostgreSQLバージョン</entry>
      <entry>18.0</entry>
      <entry>-</entry>
     </row>
     <row>
      <entry>ポート番号</entry>
      <entry>5432</entry>
      <entry>-</entry>
     </row>
     <row>
      <entry>$PGDATA</entry>
      <entry>/var/lib/pgsql/18/data</entry>
      <entry>-</entry>
     </row>
     <row>
      <entry>アーカイブモード</entry>
      <entry>無効</entry>
      <entry>-</entry>
     </row>
     <row>
      <entry>レプリケーションスロット</entry>
      <entry>有効</entry>
      <entry>本設定例では、フェイルオーバやオンラインリカバリの時に実行されるスクリプトで、自動的にレプリケーションスロットを削除/作成しています。
これらのスクリプトでは、backend_hostnameXに指定したホスト名をレプリケーションスロット名として使用しています。
スクリプトの詳細については<xref linkend="example-cluster-table-sample-scripts">を参照してください。</entry>
     </row>
     <row>
      <entry>同期/非同期レプリケーション</entry>
      <entry>非同期</entry>
      <entry>-</entry>
     </row>
    </tbody>
   </tgroup>
  </table>


  <table id="example-cluster-table-pgpool-config">
   <title>Pgpool-IIのバージョンと設定情報</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>項目</entry>
      <entry>値</entry>
      <entry>説明</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>Pgpool-IIバージョン</entry>
      <entry>4.7.0</entry>
      <entry>-</entry>
     </row>
     <row>
      <entry morerows='3'>ポート番号</entry>
      <entry>9999</entry>
      <entry>Pgpool-IIが接続を受け付けるポート番号</entry>
     </row>
     <row>
      <entry>9898</entry>
      <entry>PCPプロセスが接続を受け付けるポート番号</entry>
     </row>
     <row>
      <entry>9000</entry>
      <entry>Watchdogが接続を受け付けるポート番号</entry>
     </row>
     <row>
      <entry>9694</entry>
      <entry>Watchdogのハートビート信号を受信するUDPポート番号</entry>
     </row>
     <row>
      <entry>設定ファイル</entry>
      <entry>/etc/pgpool-II/pgpool.conf</entry>
      <entry>Pgpool-IIの設定ファイル</entry>
     </row>
     <row>
      <entry>Pgpool-II起動ユーザ</entry>
      <entry>postgres (Pgpool-II 4.1以降)</entry>
	  <entry>Pgpool-II 4.0以前のバージョンでは、デフォルトではrootでPgpool-IIを起動する</entry>
     </row>
     <row>
      <entry>Pgpool-II動作モード</entry>
      <entry>ストリーミングレプリケーションモード</entry>
      <entry>-</entry>
     </row>
     <row>
      <entry>Watchdog機能</entry>
      <entry>有効</entry>
      <entry>ハートビート方式</entry>
     </row>
    </tbody>
   </tgroup>
  </table>

  <table id="example-cluster-table-sample-scripts">
   <title>RPMに含まれるサンプルスクリプト</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>機能</entry>
      <entry>スクリプト</entry>
      <entry>説明</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry morerows='1'>自動フェイルオーバ</entry>
      <entry><ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/failover.sh.sample">/etc/pgpool-II/sample_scripts/failover.sh.sample</ulink></entry>
      <entry>フェイルオーバを実行するスクリプト。<xref linkend="GUC-FAILOVER-COMMAND">で使用します。</entry>
     </row>
     <row>
      <entry><ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/follow_primary.sh.sample">/etc/pgpool-II/sample_scripts/follow_primary.sh.sample</ulink></entry>
      <entry>上記フェイルオーバスクリプトが実行された後に、新しいプライマリサーバとスタンバイサーバを同期させるスクリプト。<xref linkend="GUC-FOLLOW-PRIMARY-COMMAND">で使用します。 PostgreSQLサーバが2台の場合はこのスクリプトの設定は不要です。</entry>
     </row>
     <row>
      <entry morerows='1'>オンラインリカバリ</entry>
      <entry><ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/recovery_1st_stage.sample">/etc/pgpool-II/sample_scripts/recovery_1st_stage.sample</ulink></entry>
      <entry>スタンバイサーバをリカバリするスクリプト。<xref linkend="GUC-RECOVERY-1ST-STAGE-COMMAND">で使用します。</entry>
     </row>
     <row>
      <entry><ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/pgpool_remote_start.sample">/etc/pgpool-II/sample_scripts/pgpool_remote_start.sample</ulink></entry>
      <entry>上記<xref linkend="GUC-RECOVERY-1ST-STAGE-COMMAND">が実行された後に、スタンバイノードを起動させるスクリプト。</entry>
     </row>
     <row>
      <entry morerows='1'>Watchdog</entry>
      <entry><ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/escalation.sh.sample">/etc/pgpool-II/sample_scripts/escalation.sh.sample</ulink></entry>
      <entry>
       任意の設定。Pgpool-IIのリーダー/スタンバイ切り替え時に、旧Watchdogリーダープロセスの異常終了によって旧Watchdogリーダーで仮想IPが起動したまま、新しいリーダーノードで仮想IPが起動されることを防ぐために、新しいリーダー以外で起動している仮想IPを停止するスクリプト。<xref linkend="guc-wd-escalation-command">で使用します。
      </entry>
     </row>
    </tbody>
   </tgroup>
  </table>
  <para>
  上記各種スクリプトはRPMパッケージに同梱されており、必要に応じてカスタマイズできます。
  </para>
 </sect2>

 <sect2 id="example-cluster-installation">
  <title>インストール</title>
  <para>
   この設定例ではYUMを使用して<productname>PostgreSQL</productname>および<productname>Pgpool-II</productname>をインストールします。
  </para>
  <para>
   <productname>PostgreSQL</productname>のインストールは<productname>PostgreSQL</productname>コミュニティのリポジトリを使います。
  </para>
  <programlisting>
[全サーバ]# dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-10-x86_64/pgdg-redhat-repo-latest.noarch.rpm
[全サーバ]# dnf -qy module disable postgresql
[全サーバ]# dnf install -y postgresql18-server
  </programlisting>

  <para>
   <productname>Pgpool-II</productname>のインストールは<productname>Pgpool-II</productname>開発コミュニティが提供するYumリポジトリを用いてインストールします。
  </para>
  <para>
   <productname>Pgpool-II</productname>関連のパッケージは<productname>PostgreSQL</productname>コミュニティのリポジトリにもあるため、
   <productname>PostgreSQL</productname>コミュニティのリポジトリから<productname>Pgpool-II</productname>をインストールしないように<filename>/etc/yum.repos.d/pgdg-redhat-all.repo</filename>にexclude設定を追加します。
  </para>
  <programlisting>
[全サーバ]# vi /etc/yum.repos.d/pgdg-redhat-all.repo
  </programlisting>
  <para>
   以下は、<filename>/etc/yum.repos.d/pgdg-redhat-all.repo</filename>の設定例です。
  </para>
  <programlisting>
[pgdg-common]
...
exclude=pgpool*


[pgdg18]
...
exclude=pgpool*

[pgdg17]
...
exclude=pgpool*

[pgdg16]
...
exclude=pgpool*

[pgdg15]
...
exclude=pgpool*

[pgdg14]
...
exclude=pgpool*

[pgdg13]
...
exclude=pgpool*
  </programlisting>

  <para>
   <productname>Pgpool-II</productname>をインストールします。
   Rocky Linux 10で<productname>PgPool-II</productname>をインストールするには、依存関係を満たすためにEPELリポジトリの有効化とlibmemcached-awesome-develが必要です。
  </para>
  <programlisting>
[全サーバ]# dnf install -y https://www.pgpool.net/yum/rpms/4.7/redhat/rhel-10-x86_64/pgpool-II-release-4.7-1.noarch.rpm
[全サーバ]# dnf install -y epel-release
[全サーバ]# dnf install -y libmemcached-awesome-devel
[全サーバ]# dnf install -y pgpool-II-pg18-*
  </programlisting>
  <para>
   <literal>Rocky Linux 9</literal>を使用する場合、<literal>epel</literal>リポジトリではなく、<literal>crb</literal>リポジトリを、
   <literal>Rocky Linux 8</literal>を使用する場合は<literal>powertools</literal>リポジトリを有効化してください。
  </para>
  <programlisting>
[全サーバ]# dnf install -y --enablerepo=crb pgpool-II-pg18-*
  </programlisting>
 </sect2>

 <sect2 id="example-cluster-pre-setup">
  <title>事前設定</title>
  <para>
  Pgpool-IIの設定の前に、以下の設定を行ってください。
  </para>

  <sect3 id="example-cluster-before-starting-ssh">
   <title>SSH公開鍵認証の設定</title>
    <para>
     自動フェイルオーバ、オンラインリカバリ機能を利用するには、すべての<productname>Pgpool-II</productname>ノード間で<literal>postgres</literal>ユーザ（Pgpool-IIのデフォルトの起動ユーザ。Pgpool-II 4.0以前、デフォルトの起動ユーザは<literal>root</literal>）として双方向にSSH公開鍵認証（パスワードなし）で接続できるように設定する必要があります。 
    </para>
    <para>
    </para>
    <para>
     まず、全サーバで以下のコマンドを実行し、SSH鍵ファイルを作成します。
     この設定例では生成される鍵ファイル名は<literal>id_rsa_pgpool</literal>とします。
    </para>
    <programlisting>
[全サーバ]# su - postgres
[全サーバ]$ mkdir ~/.ssh && chmod 700 ~/.ssh
[全サーバ]$ ssh-keygen -t rsa -f ~/.ssh/id_rsa_pgpool
    </programlisting>
    <para>
     次に、公開鍵<literal>id_rsa_pgpool.pub</literal>を各サーバの<filename>/var/lib/pgsql/.ssh/authorized_keys</filename>ファイルに追加します。
    </para>
    <para>
     設定後、<literal>postgres</literal>ユーザで<command>ssh postgres@serverX -i ~/.ssh/id_rsa_pgpool</command>コマンドを実行し、パスワードなしでログインできることを確認してください。
    </para>

    <note>
     <para>
      公開鍵認証によるログインに失敗した場合には、以下を確認してください。
      <itemizedlist>
       <listitem>
        <para>
         <filename>/etc/ssh/sshd_config</filename>で公開鍵認証が許可されていることを確認します。
        </para>
       </listitem>
      </itemizedlist>
      <programlisting>
PubkeyAuthentication yes
      </programlisting>
      <itemizedlist>
       <listitem>
        <para>
         SELinuxを有効化している場合は、SSH公開鍵認証(パスワードなし)が失敗する可能性があるので、すべてのサーバで以下のコマンドを実行する必要があります。
        </para>
       </listitem>
      </itemizedlist>
      <programlisting>
[全サーバ]# su - postgres
[全サーバ]$ restorecon -Rv ~/.ssh
      </programlisting>
     </para>
    </note>
  </sect3>

  <sect3 id="example-cluster-before-starting-firewall">
   <title>firewallの設定</title>
   <para>
    <productname>Pgpool-II</productname>や<productname>PostgreSQL</productname>に接続する際には、ファイアーウォールによって目的のポートが開けられていなければなりません。
    <systemitem>Rocky Linux 10/RHEL 10</systemitem>の場合、以下のように設定します。
   </para>
   <programlisting>
[全サーバ]# 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
   </programlisting>
  </sect3>

  <sect3 id="example-cluster-before-starting-primary">
   <title>プライマリのセットアップ</title>
    <para>
     <literal>server1</literal>で<productname>PostgreSQL</productname>プライマリサーバのセットアップを行います。
    </para>
    <para>
     まず、データベースクラスタの初期化を行います。
     <productname>PostgreSQL</productname> 18ではデータベースクラスタのデフォルトの作成先は<filename>/var/lib/pgsql/18/data</filename>で、<literal>postgres</literal>ユーザの設定ファイル<filename>~/.bash_profile</filename>で環境変数<varname>PGDATA</varname>に指定されています。
     必要に応じて変更してください。
    </para>
    <para>
     <command>initdb</command>コマンドを実行して、データベースクラスタの初期化を行います。
     必要に応じて、<literal>--encoding</literal>や<literal>--locale</literal><ulink url="https://www.postgresql.org/docs/18/app-initdb.html">オプション</ulink>を指定して、データベースのエンコーディングやロケールを設定してください。
    </para>
    <programlisting>
[root@server1 ~]# su - postgres
[postgres@server1 ~]$ /usr/pgsql-18/bin/initdb
    </programlisting>

    <para>
     次に<literal>server1</literal>で設定ファイル<filename>$PGDATA/postgresql.conf</filename>を以下のように編集します。
     <application>pg_rewind</application>を使うために<varname>wal_log_hints</varname>を有効にします。
    </para>
    <programlisting>
[postgres@server1 ~]$ vi $PGDATA/postgresql.conf
listen_addresses = '*'
wal_log_hints = on
    </programlisting>
    <para>
     最後に、<literal>server1</literal>で<productname>PostgreSQL</productname>を起動します。
    </para>
   <programlisting>
[postgres@server1 ~]$ /usr/pgsql-18/bin/pg_ctl start
    </programlisting>
  </sect3>

  <sect3 id="example-cluster-before-starting-standby">
   <title>スタンバイのセットアップ</title>
   <para>
    スタンバイサーバをセットアップする方法としては、次のような複数の方法があります。
    <itemizedlist>
     <listitem>
      <para>
       <productname>Pgpool-II</productname>のオンラインリカバリ機能（<xref linkend="runtime-online-recovery">）を使用して、スタンバイサーバを自動的にセットアップします。
      </para>
     </listitem>
     <listitem>
      <para>
       スタンバイで<command>pg_basebackup</command>を実行して、プライマリのデータディレクトリのバックアップを生成します。
      </para>
     </listitem>
    </itemizedlist>
   </para>
   <note>
    <para>
     オンラインリカバリを使用せず手動でスタンバイをセットアップする場合は次の注意点があります。
     <itemizedlist>
      <listitem>
       <para>
        手動でレプリケーションスロットを作成する必要があります。
       </para>
      </listitem>
     </itemizedlist>
     <itemizedlist>
      <listitem>
       <para>
        pg_basebackup を実行する際には -R オプションを指定しないでください。<varname>primary_conninfo</varname>、 <varname>recovery_target_timeline</varname>、 <varname>primary_slot_name</varname> は <filename>postgresql.auto.conf</filename> ではなく、<filename>$PGDATA/myrecovery.conf</filename> に記載し、<filename>postgresql.conf</filename> に以下を追記してください。
       </para>
      </listitem>
     </itemizedlist>
     <programlisting>
include_if_exists = 'myrecovery.conf'
     </programlisting>
    </para>
   </note>
   <para>
    この設定例では、<productname>Pgpool-II</productname>の構成が完了した後に、<xref linkend="example-cluster-verify-standby">で<productname>Pgpool-II</productname>のオンラインリカバリを使用してスタンバイサーバをセットアップします。
   </para>
  </sect3>

  <sect3 id="example-cluster-before-starting-users">
   <title>PostgreSQLユーザの作成</title>
    <para>
     <productname>Pgpool-II</productname>が<productname>PostgreSQL</productname>のユーザを使用してPostgreSQLへ接続し、ヘルスチェックやレプリケーション遅延チェックを行います。
     セキュリティ上の理由で、この設定例ではスーパーユーザを使わず、レプリケーション遅延チェックとヘルスチェック専用のユーザ<literal>pgpool</literal>を作成します。
     また、レプリケーション専用のユーザ<literal>repl</literal>を作成します。
     オンラインリカバリ機能を利用するにはスーパーユーザ権限が必要なので、ここでは<literal>postgres</literal>ユーザを使用します。
    </para>
    <para>
     <productname>Pgpool-II</productname> 4.0から<acronym>scram-sha-256</acronym>認証が利用できるようになりました。
     この設定例では、<acronym>scram-sha-256</acronym>認証方式を利用します。
     まず、<literal>password_encryption = 'scram-sha-256'</literal>に変更してから、ユーザを登録します。
    </para>

    <table id="example-cluster-user">
     <title>PostgreSQLユーザ</title>
     <tgroup cols="3">
      <thead>
       <row>
        <entry>ユーザ名</entry>
        <entry>パスワード</entry>
        <entry>備考</entry>
       </row>
      </thead>
      <tbody>
       <row>
        <entry>repl</entry>
        <entry>repl</entry>
        <entry>PostgreSQLのレプリケーション専用ユーザ</entry>
       </row>
       <row>
        <entry>pgpool</entry>
        <entry>pgpool</entry>
        <entry>
         Pgpool-IIのレプリケーション遅延チェック(<xref linkend="GUC-SR-CHECK-USER">)、
         ヘルスチェック専用ユーザ(<xref linkend="GUC-HEALTH-CHECK-USER">)
        </entry>
       </row>
       <row>
        <entry>postgres</entry>
        <entry>postgres</entry>
        <entry>オンラインリカバリの実行ユーザ</entry>
       </row>
      </tbody>
     </tgroup>
    </table>

    <programlisting>
[postgres@server1 ~]$ psql
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
    </programlisting>

    <para>
     <xref linkend="SQL-SHOW-POOL-NODES">コマンドで<literal>replication_stat</literal>カラムと<literal>replication_sync_state</literal>カラムを表示するには、<literal>pgpool</literal>ユーザは<productname>PostgreSQL</productname>のスーパーユーザであるか、<literal>pg_monitor</literal>グループに所属する必要があります(<productname>Pgpool-II</productname> 4.1以降)。
     以下のコマンドで<literal>pgpool</literal>ユーザをそのグループに所属させます。
    </para>
    <programlisting>
postgres=# GRANT pg_monitor TO pgpool;
postgres=# \q
    </programlisting>

    <note>
     <para>
      <xref linkend="guc-detach-false-primary">(<productname>Pgpool-II</productname> 4.1以降)を利用する予定がある場合、"pgpool" ロールは<productname>PostgreSQL</productname>のスーパーユーザであるか、<literal>pg_monitor</literal>グループに所属する必要があります。
     </para>
    </note>

    <para>
     この設定例では、<productname>Pgpool-II</productname>サーバと<productname>PostgreSQL</productname>バックエンドサーバが同じサブネットワークにあることを想定し、各ユーザが<acronym>scram-sha-256</acronym>認証方式で接続するように、<filename>$PGDATA/pg_hba.conf</filename>を編集しておきます。
    </para>
    <programlisting>
[postgres@server1 ~]$ vi $PGDATA/pg_hba.conf
(以下を追加)
host    all             pgpool          samenet                 scram-sha-256
host    all             postgres        samenet                 scram-sha-256
host    replication     repl            samenet                 scram-sha-256
    </programlisting>
  </sect3>

  <sect3 id="example-cluster-before-starting-pgpass">
   <title>.pgpassの作成</title>
    <para>
     パスワード入力なしで、ストリーミングレプリケーションや<application>pg_rewind</application>を実行するために、すべてのサーバで<literal>postgres</literal>ユーザのホームディレクトリ<filename>/var/lib/pgsql</filename>に<filename>.pgpass</filename>を作成し、パーミッションを600に設定しておきます。
    </para>
    <programlisting>
[postgres@server1 ~]$ vi ~/.pgpass
server1:5432:replication:repl:&lt;replユーザのパスワード&gt;
server2:5432:replication:repl:&lt;replユーザのパスワード&gt;
server3:5432:replication:repl:&lt;replユーザのパスワード&gt;
server1:5432:postgres:postgres:&lt;postgresユーザのパスワード&gt;
server2:5432:postgres:postgres:&lt;postgresユーザのパスワード&gt;
server3:5432:postgres:postgres:&lt;postgresユーザのパスワード&gt;

[postgres@server1 ~]$ chmod 600 ~/.pgpass
    </programlisting>
    <para>
     server2およびserver3のpostgresユーザのホームディレクトリにコピーします。
    </para>
    <programlisting>
[postgres@server1 ~]$ scp -i ~/.ssh/id_rsa_pgpool -p ~/.pgpass postgres@server2:
[postgres@server1 ~]$ scp -i ~/.ssh/id_rsa_pgpool -p ~/.pgpass postgres@server3:
    </programlisting>
  </sect3>
 </sect2>

 <sect2 id="pcp-authentication">
  <title>PCP接続認証の設定</title>
  <para>
   PCPコマンドを使用するには、<literal>username:encryptedpassword</literal>形式のPCPユーザ名とmd5暗号化パスワードを<filename>pcp.conf</filename>に登録する必要があります。
  </para>
  <para>
   この設定例では、PCPユーザ名を<literal>pgpool</literal>、パスワードを<literal>pgpool_password</literal>に設定します。
   必要に応じて、ユーザ名とパスワードを変更してください。
  </para>
  <para>
   以下のように、pg_md5を使用して、pcpユーザpgpoolの暗号化されたパスワードエントリを作成します。
  </para>
  <programlisting>
[postgres@server1 ~]$ echo 'pgpool:'`pg_md5 pgpool_password` &gt;&gt; /etc/pgpool-II/pcp.conf

[postgres@server1 ~]$ cat /etc/pgpool-II/pcp.conf
# USERID:MD5PASSWD
pgpool:4aa0cb9673e84b06d4c8a848c80eb5d0
  </programlisting>
  <para>
   後述の<filename>follow_primary.sh</filename>のスクリプトでパスワード入力なしで<literal>PCP</literal>コマンドを実行する必要があるので、<productname>Pgpool-II</productname>の起動ユーザ（postgresユーザ）のホームディレクトリに<filename>.pcppass</filename>を作成します。
  </para>
  <programlisting>
[postgres@server1 ~]$ echo 'localhost:9898:pgpool:pgpool_password' &gt; ~/.pcppass
[postgres@server1 ~]$ chmod 600 ~/.pcppass
  </programlisting>
   <para>
    server2およびserver3のpostgresユーザのホームディレクトリにコピーします。
   </para>
   <programlisting>
[postgres@server1 ~]$ scp -i ~/.ssh/id_rsa_pgpool -p ~/.pcppass postgres@server2:
[postgres@server1 ~]$ scp -i ~/.ssh/id_rsa_pgpool -p ~/.pcppass postgres@server3:
[postgres@server1 ~]$ exit
  </programlisting>
 </sect2>

 <sect2 id="example-cluster-pgpool-node-id">
  <title>pgpool_node_idファイルの作成</title>
  <para>
   <productname>Pgpool-II</productname> 4.2以降、すべての設定パラメータがすべてのホストで同一になりました。
   <application>Watchdog</application>機能が有効になっている場合、どの設定がどのホストであるかを区別するには、
   <filename>pgpool_node_id</filename>ファイルの設定が必要になります。
   <filename>pgpool_node_id</filename>ファイルを作成し、
   そのファイルにpgpool(watchdog)ホストを識別するためのノード番号(0、1、2など)を追加します。
  </para>
  <itemizedlist>
   <listitem>
    <para>
     <literal>server1</literal>
    </para>
    <programlisting>
[root@server1 ~]# echo 0 &gt; /etc/pgpool-II/pgpool_node_id
[root@server1 ~]# cat /etc/pgpool-II/pgpool_node_id
0
    </programlisting>
   </listitem>
   <listitem>
    <para>
     <literal>server2</literal>
    </para>
    <programlisting>
[root@server2 ~]# echo 1 &gt; /etc/pgpool-II/pgpool_node_id
[root@server2 ~]# cat /etc/pgpool-II/pgpool_node_id
1
    </programlisting>
   </listitem>
   <listitem>
    <para>
     <literal>server3</literal>
    </para>
    <programlisting>
[root@server3 ~]# echo 2 &gt; /etc/pgpool-II/pgpool_node_id
[root@server3 ~]# cat /etc/pgpool-II/pgpool_node_id
2
    </programlisting>
   </listitem>
  </itemizedlist>
 </sect2>

 <sect2 id="example-cluster-pgpool-config">
  <title><productname>Pgpool-II</productname>の設定</title>
   <para>
    RPMからインストールした場合、<productname>Pgpool-II</productname>の設定ファイル
    <filename>pgpool.conf</filename>は<filename>/etc/pgpool-II</filename>にあります。
   </para>
  <para>
   <productname>Pgpool-II</productname> 4.2以降、すべての設定パラメーターがすべてのホストで同一になったので、
   どれか一つのノード上で<filename>pgpool.conf</filename>を編集し、
   編集した<filename>pgpool.conf</filename>ファイルを他のpgpoolノードにコピーすれば良いです。
  </para>

  <sect3 id="example-cluster-pgpool-config-config-file">
   <title>クラスタリングモード</title>
   <para>
    <productname>Pgpool-II</productname>にはいくつかのクラスタリングモードがあり、
    クラスタリングモードを設定するには<xref linkend="GUC-BACKEND-CLUSTERING-MODE">というパラメータを使用します。
    この設定例では、ストリーミングレプリケーションモードを使用します。
   </para>
   <programlisting>
[root@server1 ~]# vi /etc/pgpool-II/pgpool.conf 
backend_clustering_mode = streaming_replication
   </programlisting>
  </sect3>

  <sect3 id="example-cluster-pgpool-config-listen-addresses">
   <title>listen_addresses</title>
   <para>
    <productname>Pgpool-II</productname>およびPCPが全てのIPアドレスから接続を受け付けるように、以下のパラメータを<literal>'*'</literal>に設定します。
   </para>
   <programlisting>
listen_addresses = '*'
pcp_listen_addresses = '*'
   </programlisting>
  </sect3>

  <sect3 id="example-cluster-pgpool-config-port">
   <title>port</title>
   <para>
    <productname>Pgpool-II</productname>が接続を受け付けるために監視するポート番号を指定します。
   </para>
   <programlisting>
port = 9999
   </programlisting>
  </sect3>

  <sect3 id="example-cluster-pgpool-config-sr-check">
   <title>ストリーミングレプリケーションのチェック</title>
   <para>
    レプリケーションの遅延チェックユーザ<xref linkend="GUC-SR-CHECK-USER">に<literal>pgpool</literal>ユーザを設定します。
    この設定例では、<xref linkend="GUC-SR-CHECK-PASSWORD">は<filename>pgpool.conf</filename>に指定せず、
    <xref linkend="GUC-POOL-PASSWD">ファイルに作成します。
    作成方法については後述の<xref linkend="example-cluster-pgpool-config-auth">を参照ください。
    <productname>Pgpool-II</productname> 4.0から、<xref linkend="GUC-SR-CHECK-PASSWORD">が空の場合、
    <productname>Pgpool-II</productname>は空のパスワードを使用する前に
    まず<xref linkend="GUC-POOL-PASSWD">ファイルから<xref linkend="GUC-SR-CHECK-USER">に
    指定したユーザのパスワードを取得できるか試みます。
   </para>
   <programlisting>
sr_check_user = 'pgpool'
sr_check_password = ''
   </programlisting>
  </sect3>

  <sect3 id="example-cluster-pgpool-config-health-check">
   <title>ヘルスチェック</title>
   <para>
    自動フェイルオーバのため、ヘルスチェックを有効にします。
    <xref linkend="GUC-HEALTH-CHECK-PERIOD">のデフォルト値が0で、これはヘルスチェックが無効であることを意味します。
    また、ネットワークが不安定な場合には、バックエンドが正常であるにも関わらず、
    ヘルスチェックに失敗し、フェイルオーバや縮退運転が発生してしまう可能性があります。
    そのようなヘルスチェックの誤検知を防止するため、ヘルスチェックのリトライ回数を
    <literal>health_check_max_retries = 3</literal> に設定しておきます。
    <xref linkend="GUC-HEALTH-CHECK-USER">、<xref linkend="GUC-HEALTH-CHECK-PASSWORD">は
    前述の<xref linkend="GUC-SR-CHECK-USER">、<xref linkend="GUC-SR-CHECK-PASSWORD">と同様に設定します。
   </para>
   <programlisting>
health_check_period = 5
health_check_timeout = 30
health_check_user = 'pgpool'
health_check_password = ''
health_check_max_retries = 3
   </programlisting>
  </sect3>

  <sect3 id="example-cluster-pgpool-config-backend-settings">
   <title>バックエンドの設定</title>
   <para>
    また、バックエンド情報を前述の<literal>server1</literal>、<literal>server2</literal>
    及び<literal>server3</literal>の設定に従って設定しておきます。
    複数バックエンドノードを定義する場合、以下の<literal>backend_*</literal>などのパラメータ名の
    末尾にノードIDを表す数字を付加することで複数のバックエンドを指定することができます。
   </para>
   <programlisting>
backend_hostname0 = 'server1'
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/var/lib/pgsql/18/data'
backend_flag0 = 'ALLOW_TO_FAILOVER'

backend_hostname1 = 'server2'
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/var/lib/pgsql/18/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'

backend_hostname2 = 'server3'
backend_port2 = 5432
backend_weight2 = 1
backend_data_directory2 = '/var/lib/pgsql/18/data'
backend_flag2 = 'ALLOW_TO_FAILOVER'
   </programlisting>

   <para>
    <xref linkend="SQL-SHOW-POOL-NODES">コマンドで<productname>Pgpool-II</productname> 4.1で追加された
    <literal>replication_stat</literal>カラムと<literal>replication_sync_state</literal>カラムを表示するには、
    <xref linkend="GUC-BACKEND-APPLICATION-NAME">パラメータを設定する必要があります（Pgpool-II 4.1以降）。
    ここではそれぞれのホスト名を設定します。
    <varname>backend_application_nameX</varname>に設定された値が、<varname>primary_conninfo</varname>の<varname>application_name</varname>に設定された値と一致していることを確認してください。
      <programlisting>
backend_application_name0 = 'server1'
backend_application_name1 = 'server2'
backend_application_name2 = 'server3'
      </programlisting>
   </para>
  </sect3>

  <sect3 id="example-cluster-pgpool-config-failover">
   <title>フェイルオーバの設定</title>
   <para>
    <productname>PostgreSQL</productname>バックエンドノードがダウンした時に実行するスクリプトを
    <xref linkend="GUC-FAILOVER-COMMAND">に設定します。
    また、<productname>PostgreSQL</productname>サーバが3台の場合、
    プライマリノードのフェイルオーバ後に新しいプライマリからスタンバイをリカバリするために
    <xref linkend="GUC-FOLLOW-PRIMARY-COMMAND">も設定する必要があります。
    <xref linkend="GUC-FOLLOW-PRIMARY-COMMAND">はプライマリノードのフェイルオーバ後に実行されます。
    <productname>PostgreSQL</productname>サーバが2台の場合、<xref linkend="GUC-FOLLOW-PRIMARY-COMMAND">の設定は不要です。
   </para>
   <note>
    <para>
     <productname>Pgpool-II</productname> 4.3で追加された<xref linkend="PCP-PROMOTE-NODE">の
     <option>switchover</option>オプションでスイッチオーバを行う時に、
     古いプライマリを自動でスタンバイにする場合は<productname>PostgreSQL</productname>サーバが2台であっても、
     <xref linkend="GUC-FOLLOW-PRIMARY-COMMAND">の設定が必要になります。
    </para>
   </note>
   <para>
    それぞれの実行スクリプトの引数は、それぞれ実行時に<productname>Pgpool-II</productname>
    によってバックエンドの具体的な情報に置き換えられます。
    各引数の意味は<xref linkend="GUC-FAILOVER-COMMAND">および<xref linkend="GUC-FOLLOW-PRIMARY-COMMAND">をご参照ください。
   </para>
   <programlisting>
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'
   </programlisting>
   <note>
    <para>
     <emphasis>%N</emphasis>、<emphasis>%S</emphasis>は<productname>Pgpool-II</productname> 4.1で追加された引数です。
     <productname>Pgpool-II</productname> 4.0または以前のバージョンを利用している場合、
     これらの引数を指定できないので、ご注意ください。
    </para>
   </note>
   <para>
    サンプルスクリプト<ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/failover.sh.sample">failover.sh</ulink>及び
    <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/follow_primary.sh.sample">follow_primary.sh</ulink>は
    <filename>/etc/pgpool-II/</filename>配下にインストールされていますので、これらのファイルをコピーして作成します。
   </para>
   <programlisting>
[root@server1 ~]# cp -p /etc/pgpool-II/sample_scripts/failover.sh.sample /etc/pgpool-II/failover.sh
[root@server1 ~]# cp -p /etc/pgpool-II/sample_scripts/follow_primary.sh.sample /etc/pgpool-II/follow_primary.sh
[root@server1 ~]# chown postgres:postgres /etc/pgpool-II/{failover.sh,follow_primary.sh}
   </programlisting>
   <para>
    基本的には<emphasis>PGHOME</emphasis>を環境に合わせて変更すれば、動作します。
   </para>
   <programlisting>
[root@server1 ~]# vi /etc/pgpool-II/failover.sh
...
PGHOME=/usr/pgsql-18
...

[root@server1 ~]# vi /etc/pgpool-II/follow_primary.sh
...
PGHOME=/usr/pgsql-18
...
   </programlisting>
   <para>
    <filename>follow_primary.sh</filename>で<varname>PCP_USER</varname>に指定されているユーザが<filename>pcp.conf</filename>に登録されていることを確認してください。
    この設定例では、前述の<xref linkend="PCP-AUTHENTICATION">セクションですでに登録済みです。
   </para>
   <programlisting>
[root@server1 ~]# vi /etc/pgpool-II/follow_primary.sh
...
PCP_USER=pgpool
...
   </programlisting>
   <note>
    <para>
     <filename>follow_primary.sh</filename>スクリプトはテーブルスペースに対応していません。
     テーブルスペースを使っている場合は、スクリプトを自分で変更する必要があります。
    </para>
   </note>
  </sect3>

  <sect3 id="example-cluster-pgpool-config-online-recovery">
   <title>オンラインリカバリの設定</title>
   <para>
    続いて、オンラインリカバリ（<xref linkend="runtime-online-recovery">）を実行する<productname>PostgreSQL</productname>ユーザ及びオンラインリカバリ時に呼び出されるスクリプトを設定します。
    オンラインリカバリで実行される<function>pgpool_recovery</function>関数は
    <productname>PostgreSQL</productname>のスーパーユーザ権限が必要なため、<varname>recovery_user</varname>に<emphasis>スーパーユーザ</emphasis>を指定しなければなりません。
    ここでは、<literal>postgres</literal>ユーザを指定します。
   </para>
   <para>
    この設定例では<xref linkend="GUC-RECOVERY-PASSWORD">を空のままにし、<xref linkend="GUC-POOL-PASSWD">にエントリを作成します。<xref linkend="GUC-POOL-PASSWD">にエントリを作成する方法については、<xref linkend="example-cluster-pgpool-config-auth">を参照してください。
   </para>
   <programlisting>
recovery_user = 'postgres'
recovery_password = ''
recovery_1st_stage_command = 'recovery_1st_stage'
   </programlisting>
   <para>
    オンラインリカバリ用のサンプルスクリプト<ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/recovery_1st_stage.sample">recovery_1st_stage</ulink>
    及び<ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/pgpool_remote_start.sample">pgpool_remote_start</ulink>は
    <filename>/etc/pgpool-II/</filename>配下にインストールされていますので、
    これらのファイルをプライマリサーバ(<literal>server1</literal>)のデータベースクラスタ配下に配置します。
   </para>
   <programlisting>
[root@server1 ~]# su - postgres -c "cp -p /etc/pgpool-II/sample_scripts/recovery_1st_stage.sample \$PGDATA/recovery_1st_stage"
[root@server1 ~]# su - postgres -c "cp -p /etc/pgpool-II/sample_scripts/pgpool_remote_start.sample \$PGDATA/pgpool_remote_start"
   </programlisting>
   <para>
    基本的には<emphasis>PGHOME</emphasis>を環境に合わせて変更すれば、動作します。
   </para>
   <programlisting>
[root@server1 ~]# vi /var/lib/pgsql/18/data/recovery_1st_stage
...
PGHOME=/usr/pgsql-18
...

[root@server1 ~]# vi /var/lib/pgsql/18/data/pgpool_remote_start
...
PGHOME=/usr/pgsql-18
...
   </programlisting>

   <para>
    また、オンラインリカバリ機能を使用するには、<function>pgpool_recovery</function>、<function>pgpool_remote_start</function>、<function>pgpool_switch_xlog</function>の各関数をあらかじめ<xref linkend="guc-recovery-database">で指定されたデータベース（デフォルトは<literal>'postgres'</literal>です）に作成しておく必要があります。
    <literal>server1</literal>上で以下のコマンドを実行し、これらの関数を<literal>postgres</literal>に作成します。
    <xref linkend="guc-recovery-database">にデフォルト以外の値が設定されている場合は、<literal>postgres</literal>をその設定値に置き換えてください。
   </para>
   <programlisting>
[root@server1 ~]# psql -U postgres postgres -c "CREATE EXTENSION pgpool_recovery"
   </programlisting>
   <note>
    <para>
     <filename>recovery_1st_stage</filename>スクリプトはテーブルスペースに対応していません。
     テーブルスペースを使っている場合は、スクリプトを自分で変更する必要があります。
    </para>
   </note>
  </sect3>

  <sect3 id="example-cluster-pgpool-config-auth">
   <title>クライアント認証の設定</title>
   <para>
    <link linkend="EXAMPLE-CLUSTER-PRE-SETUP">事前設定</link>の章で、
    <productname>Pgpool-II</productname>と<productname>PostgreSQL</productname>の間に
    認証方式を<acronym>scram-sha-256</acronym>に設定しました。
    この設定例では、クライアントと<productname>Pgpool-II</productname>の間でも
    <acronym>scram-sha-256</acronym>認証方式を利用し接続するように設定します。
    <productname>Pgpool-II</productname>のクライアント認証の設定ファイルは
    <filename>pool_hba.conf</filename>と呼ばれ、RPMパッケージからインストールする場合、
    デフォルトでは<filename>/etc/pgpool-II</filename>配下にインストールされます。
    デフォルトでは<filename>pool_hba.conf</filename>による認証は無効になっているので、
    <filename>pgpool.conf</filename>では以下の設定をonに変更します。
   </para>
   <programlisting>
enable_pool_hba = on
   </programlisting>
   <para>
    <filename>pool_hba.conf</filename>のフォーマットは<productname>PostgreSQL</productname>の
    <filename>pg_hba.conf</filename>とほとんど同じです。
    <literal>pgpool</literal>と<literal>postgres</literal>ユーザの認証方式を<acronym>scram-sha-256</acronym>に設定します。
    この設定例では、<productname>Pgpool-II</productname>に接続しているアプリケーションが同じサブネット内にあると想定しています。
   </para>
   <programlisting>
[root@server1 ~]# vi /etc/pgpool-II/pool_hba.conf 
(以下を追加)
host    all         pgpool           samenet          scram-sha-256
host    all         postgres         samenet          scram-sha-256
   </programlisting>
   <note>
    <para>
     <productname>Pgpool-II</productname> 4.0の場合、<filename>pgpool.conf</filename>ファイル内の<xref linkend="guc-health-check-password">、<xref linkend="guc-sr-check-password">、<xref linkend="guc-wd-lifecheck-password">、<xref linkend="guc-recovery-password">には<acronym>AES256</acronym>暗号化形式、平文形式しか指定できないので、ご注意ください。
    </para>
   </note>
   <para>
    <productname>Pgpool-II</productname>のクライアント認証で用いるデフォルトのパスワードファイル名は<filename>pool_passwd</filename>です。
    <acronym>scram-sha-256</acronym>認証を利用する場合、<productname>Pgpool-II</productname>はそれらのパスワードを復号化するために復号鍵が必要となります。
    復号鍵ファイルを<productname>Pgpool-II</productname>の起動ユーザ<literal>postgres</literal>（<productname>Pgpool-II</productname> 4.0以前のバージョンでは<literal>root</literal>）のホームディレクトリ配下に作成し、<literal>server2</literal>および<literal>server3</literal>にコピーします。
   </para>
   <programlisting>
[root@server1 ~]# su - postgres -c "echo '任意の文字列' > ~/.pgpoolkey"
[root@server1 ~]# su - postgres -c "chmod 600 ~/.pgpoolkey"
[root@server1 ~]# su - postgres -c "scp -i ~/.ssh/id_rsa_pgpool -p ~/.pgpoolkey postgres@server2:"
[root@server1 ~]# su - postgres -c "scp -i ~/.ssh/id_rsa_pgpool -p ~/.pgpoolkey postgres@server3:"
   </programlisting>
   <para>
    <command>pg_enc -m -k /path/to/.pgpoolkey -u username -p</command>を実行すると、ユーザ名と<acronym>AES256</acronym>で暗号化したパスワードのエントリが<xref linkend="GUC-POOL-PASSWD">に登録されます。
    <xref linkend="GUC-POOL-PASSWD"> がまだ存在しなければ、<filename>pgpool.conf</filename>と同じディレクトリ内に作成されます。
   </para>
   <programlisting>
[root@server1 ~]# pg_enc -m -k /var/lib/pgsql/.pgpoolkey -u pgpool -p
db password: (pgpoolユーザのパスワードを入力)
trying to read key from file /var/lib/pgsql/.pgpoolkey

[root@server1 ~]# pg_enc -m -k /var/lib/pgsql/.pgpoolkey -u postgres -p
db password: (postgresユーザのパスワードを入力)
trying to read key from file /var/lib/pgsql/.pgpoolkey

[root@server1 ~]# cat /etc/pgpool-II/pool_passwd 
pgpool:AESheq2ZMZjynddMWk5sKP/Rw==
postgres:AESHs/pWL5rtXy2IwuzroHfqg==
   </programlisting>
  </sect3>

  <sect3 id="example-cluster-pgpool-config-watchdog">
   <title>Watchdogの設定</title>
   <para>
    デフォルトでは<application>Watchdog</application>機能が無効になっているため、<application>Watchdog</application>を有効にします。
   </para>
   <programlisting>
use_watchdog = on
   </programlisting>
   <para>
    <productname>Pgpool-II</productname>リーダーノードが立ち上げる仮想IPを<varname>delegate_ip</varname>に指定します。
    仮想IPはまだ使われていないIPアドレスを指定してください。
   </para>
   <programlisting>
delegate_ip = '192.168.100.50'
   </programlisting>

   <para>
    仮想IPの起動/停止、<command>ARP</command>リクエストの送信を行う設定パラメータ
    <xref linkend="GUC-IF-UP-CMD">、<xref linkend="GUC-IF-DOWN-CMD">、<xref linkend="GUC-ARPING-CMD">に、ネットワーク環境に合わせてネットマスクおよびネットワークインターフェース名を設定します。
    この設定例で使用しているネットワークインターフェースは<literal>enp0s8</literal>となります。
    <varname>if_up/down_cmd</varname>や<varname>arping_cmd</varname>を実行するにはroot権限が必要となりますので、
    一般ユーザで実行できるように<command>ip/arping</command>コマンドに<literal>setuid</literal>を設定するか、<productname>Pgpool-II</productname>起動ユーザ、デフォルトでは<literal>postgres</literal>ユーザ (<productname>Pgpool-II</productname> 4.1以降) がパスワードなしに<command>sudo</command>を実行できるように設定する必要があります。
   </para>
   <note>
    <para>
     RPMからインストールした場合、<literal>postgres</literal>ユーザがパスワードなしに
     <command>sudo</command>を介して<command>ip/arping</command>を実行できるように設定済みです。
     <programlisting>
postgres ALL=NOPASSWD: /sbin/ip
postgres ALL=NOPASSWD: /usr/sbin/arping
     </programlisting>
    </para>
   </note>
   <para>
    ここでは、<command>sudo</command>を介して実行するように設定します。
   </para>
    <programlisting>
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'
    </programlisting>
   <note>
    <para>
     <filename>/etc/sudoers</filename>で「Defaults requiretty」を設定している場合は、
     <productname>Pgpool-II</productname>の起動ユーザが<literal>tty</literal>なしで
     <varname>if_up_cmd</varname>、<varname>if_down_cmd</varname>
     及び<varname>arping_cmd</varname>コマンドを実行できるように設定する必要があります。
    </para>
   </note>

   <para>
    <command>ip</command>コマンドや<command>arping</command>コマンドのパスがデフォルトのパスと異なる場合、
    環境に合わせて<xref linkend="GUC-IF-CMD-PATH">や<xref linkend="GUC-ARPING-PATH">を設定しておいてください。
    ただし、<varname>if_up/down_cmd</varname>及び<varname>arping_cmd</varname>に指定したコマンドが"/"で始まる場合、
    フルパスとみなし<varname>if_cmd_path</varname>及び<varname>arping_path</varname>の設定を無視します。
   </para>
   <programlisting>
if_cmd_path = '/sbin'
arping_path = '/usr/sbin'
   </programlisting>
   <para>
    各<application>Watchdog</application>が稼働するサーバ情報を設定しておきます。
    <varname>pgpool_portX</varname>には<xref linkend="example-cluster-pgpool-config-port">の
    <varname>port</varname>に設定されているポート番号を指定します。
   </para>
   <programlisting>
hostname0 = 'server1'
wd_port0 = 9000
pgpool_port0 = 9999

hostname1 = 'server2'
wd_port1 = 9000
pgpool_port1 = 9999

hostname2 = 'server3'
wd_port2 = 9000
pgpool_port2 = 9999
   </programlisting>

   <para>
    <application>Watchdog</application>死活監視の設定では、
    死活監視の方法を指定する<xref linkend="guc-wd-lifecheck-method">、
    監視間隔(秒)を指定する<xref linkend="guc-wd-interval">を設定します。
    この設定例では、死活監視の方法は<literal>heartbeat</literal>を用います。
   </para>

   <programlisting>
wd_lifecheck_method = 'heartbeat'
wd_interval = 10
   </programlisting>
   <para>
    <xref linkend="guc-wd-lifecheck-method">が<literal>heartbeat</literal>に設定されている場合、
    heartbeat通信用の各<productname>Pgpool-II</productname>サーバ情報を設定しておきます。
   </para>
   <programlisting>
heartbeat_hostname0 = 'server1'
heartbeat_port0 = 9694
heartbeat_device0 = ''

heartbeat_hostname1 = 'server2'
heartbeat_port1 = 9694
heartbeat_device1 = ''

heartbeat_hostname2 = 'server3'
heartbeat_port2 = 9694
heartbeat_device2 = ''
   </programlisting>
   <para>
    <xref linkend="guc-wd-lifecheck-method">が<literal>heartbeat</literal>に設定されている場合、
    障害と判断する秒数を指定する<xref linkend="guc-wd-heartbeat-deadtime">、
    ハートビート信号の送信間隔(秒)を指定する<xref linkend="guc-wd-heartbeat-keepalive">を設定します。
   </para>
   <programlisting>
wd_heartbeat_keepalive = 2
wd_heartbeat_deadtime = 30
   </programlisting>
   <para>
    <application>Watchdog</application>プロセスが異常終了した場合に、
    旧リーダーノードで仮想IPが残ったまま、新しいリーダーノードで同じ仮想IPが起動されてしまう可能性があります。
     それを防ぐために<xref linkend="guc-wd-escalation-command">に、新しいリーダー以外の<literal>Pgpool-II</literal>ノードで仮想IPを停止するスクリプトを設定します。
    この設定は任意の設定です。
   </para>
    <programlisting>
wd_escalation_command = '/etc/pgpool-II/escalation.sh'
   　</programlisting>
   <para>
    サンプルスクリプト<ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/escalation.sh.sample">escalation.sh</ulink>は
    <filename>/etc/pgpool-II/</filename>配下にインストールされています。
   </para>
    <programlisting>
[root@server1 ~]# cp -p /etc/pgpool-II/sample_scripts/escalation.sh.sample /etc/pgpool-II/escalation.sh
[root@server1 ~]# chown postgres:postgres /etc/pgpool-II/escalation.sh
    </programlisting>

   <para>
    サーバのホスト名、仮想IP、仮想IPを設定するネットワークインターフェース名を環境に合わせて変更してください。
   </para>
   <programlisting>
[root@server1 ~]# vi /etc/pgpool-II/escalation.sh
...
PGPOOLS=(server1 server2 server3)
VIP=192.168.100.50
DEVICE=enp0s8
CIDR_NETMASK=24
...
   </programlisting>

   <note>
    <para>
     <application>Watchdog</application>ノードの数が偶数の場合は、
     <xref linkend="guc-enable-consensus-with-half-votes">パラメータをonにする必要があります。
    </para>
   </note>
   <note>
    <para>
     <literal>use_watchdog = on</literal>の場合は、<productname>Pgpool-II</productname>ノード番号を<filename>pgpool_node_id</filename>に設定する必要があります。
     詳細は<xref linkend="example-cluster-pgpool-node-id">を参照ください。
    </para>
   </note>
  </sect3>

  <sect3 id="example-cluster-pgpool-config-log">
   <title>ログの設定</title>
   <para>
    <productname>Pgpool-II</productname> 4.2以降、ログ収集プロセスが追加されました。
    RPM パッケージを使用してインストールした場合、ログ収集プロセス(<literal>logging_collector</literal>)はデフォルトで有効になっています。
    ログファイルはデフォルトで<filename>/var/log/pgpool_log</filename>に出力されます。
    要件に合わせて、ログ関連の設定パラメータを適切に調整してください。
   </para>
   <programlisting>
log_destination = 'stderr'
logging_collector = on
log_directory = '/var/log/pgpool'
log_filename = 'pgpool-%a.log'
log_truncate_on_rotation = on
log_rotation_age = 1d
   </programlisting>
   <para>
    これで、<literal>server1</literal>における<productname>Pgpool-II</productname>の設定は完了です。
    最後に、設定ファイルを他のサーバ<literal>server2</literal>および<literal>server3</literal>にコピーします。
   </para>
   <programlisting>
[root@server1 ~]# scp -p /etc/pgpool-II/{*.conf,*.sh,pool_passwd} server2:/etc/pgpool-II/
[root@server1 ~]# ssh server2 "chown postgres:postgres /etc/pgpool-II/{*.conf,*.sh,pool_passwd}"
[root@server1 ~]# scp -p /etc/pgpool-II/{*.conf,*.sh,pool_passwd} server3:/etc/pgpool-II/
[root@server1 ~]# ssh server3 "chown postgres:postgres /etc/pgpool-II/{*.conf,*.sh,pool_passwd}"
   </programlisting>
  </sect3>
 </sect2>

 <sect2 id="example-cluster-verify">
  <title>動作確認</title>
  <para>
   これから、動作確認を行います。
  </para>
  <sect3 id="example-cluster-start-stop">
   <title>Pgpool-IIの起動と停止</title>
   <itemizedlist>
    <listitem>
     <para>
      <productname>Pgpool-II</productname>の起動
     </para>
     <para>
      <productname>Pgpool-II</productname>を起動します。
     </para>
     <para>
      <productname>Pgpool-II</productname>を起動する前に、<productname>PostgreSQL</productname>をあらかじめ起動する必要があります。
      <productname>PostgreSQL</productname>プライマリサーバがまだ起動していない場合は、まず次のコマンドを実行して<productname>PostgreSQL</productname>起動します。
     </para>
     <programlisting>
[root@server1 ~]# su - postgres -c "/usr/pgsql-18/bin/pg_ctl start"
     </programlisting>
     <para>
      <literal>server1</literal>、<literal>server2</literal>および<literal>server3</literal>で以下のコマンドを実行し、<productname>Pgpool-II</productname>を起動します。
     </para>
     <programlisting>
[全サーバ]# systemctl start pgpool.service
     </programlisting>
    </listitem>
    <listitem>
     <para>
      <productname>Pgpool-II</productname>の停止
     </para>
     <para>
      <productname>Pgpool-II</productname>を停止するときに、以下のコマンドを実行して<productname>Pgpool-II</productname>を停止します。
     </para>
     <para>
      また、<productname>PostgreSQL</productname>を停止する場合は、<productname>Pgpool-II</productname>を先に停止する必要があります。
      <productname>Pgpool-II</productname>が起動している状態でPostgreSQLを停止する、想定外のフェイルオーバが起きてしまうので、ご注意ください。
     </para>
     <programlisting>
[全サーバ]# systemctl stop pgpool.service
     </programlisting>
    </listitem>
   </itemizedlist>
  </sect3>

  <sect3 id="example-cluster-verify-standby">
   <title>PostgreSQLスタンバイサーバの作成</title>
   <para>
    まず、<productname>Pgpool-II</productname>のオンラインリカバリ機能を利用し、<literal>server2</literal>と<literal>server3</literal>をスタンバイサーバとして構築し、<productname>Pgpool-II</productname>管理下に追加します。
   </para>
   <para>
    仮想IP経由で<productname>Pgpool-II</productname>に接続し、バックエンドノードのステータスを確認します。 
    下記の結果のように、プライマリサーバが<literal>server1</literal>で起動しており、<literal>server2</literal>と<literal>server3</literal>は「down」状態になっています。
   </para>
   <programlisting>
[いずれかのサーバ]# psql -h 192.168.100.50 -p 9999 -U pgpool postgres -c "show pool_nodes"
Password for user 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       | server1  | 5432 | up     | up        | 0.333333  | primary | primary | 0          | true              | 0                 |                   |                        | 2023-11-10 15:30:14
 1       | server2  | 5432 | down   | down      | 0.333333  | standby | unknown | 0          | false             | 0                 |                   |                        | 2023-11-10 15:30:14
 2       | server3  | 5432 | down   | down      | 0.333333  | standby | unknown | 0          | false             | 0                 |                   |                        | 2023-11-10 15:30:14
(3 rows)
   </programlisting>
   <para>
    オンラインリカバリ機能を使用するには、<command>pcp_recovery_node</command>コマンドを実行します。
    <command>pcp_recovery_node</command>コマンドで<filename>recovery_1st_stage</filename>と<filename>pgpool_remote_start</filename>スクリプトが実行されるので（<filename>recovery_1st_stage</filename>は<varname>recovery_1st_stage_command</varname>パラメータに設定したスクリプト）、この2つのスクリプトが現在稼働中のプライマリサーバ<literal>server1</literal>のデータベースクラスタに存在することを確認してください。
   </para>
   <programlisting>
[いずれかのサーバ]# pcp_recovery_node -h 192.168.100.50 -p 9898 -U pgpool -n 1
Password:
pcp_recovery_node -- Command Successful

[いずれかのサーバ]# pcp_recovery_node -h 192.168.100.50 -p 9898 -U pgpool -n 2
Password:
pcp_recovery_node -- Command Successful
   </programlisting>
   <para>
    <literal>server2</literal>と<literal>server3</literal>の<productname>PostgreSQL</productname>がスタンバイとして起動していることを確認します。
   </para>
   <programlisting>
[いずれかのサーバ]# psql -h 192.168.100.50 -p 9999 -U pgpool postgres -c "show pool_nodes"
Password for user 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       | server1  | 5432 | up     | up        | 0.333333  | primary | primary | 0          | false             | 0                 |                   |                        | 2023-11-10 15:30:14
 1       | server2  | 5432 | up     | up        | 0.333333  | standby | standby | 0          | true              | 0                 | streaming         | async                  | 2023-11-10 16:32:33
 2       | server3  | 5432 | up     | up        | 0.333333  | standby | standby | 0          | false             | 0                 | streaming         | async                  | 2023-11-10 16:33:08
(3 rows)
   </programlisting>
  </sect3>

  <sect3 id="example-cluster-verify-watchdog">
   <title>Watchdogリーダー/スタンバイの切り替え</title>
   <para>
    <command>pcp_watchdog_info</command>で<productname>Pgpool-II</productname>
    の<application>Watchdog</application>の情報を確認します。
    最初に起動した<productname>Pgpool-II</productname>がリーダーになります。
   </para>
   <programlisting>
[いずれかのサーバ]# pcp_watchdog_info -h 192.168.100.50 -p 9898 -U pgpool
Password:
3 3 YES server1:9999 Linux server1 server1

server1:9999 Linux server1 server1 9999 9000 4 LEADER 0 MEMBER  # 最初に起動したPgpool-IIがリーダーになる
server2:9999 Linux server2 server2 9999 9000 7 STANDBY 0 MEMBER # スタンバイとして稼働している
server3:9999 Linux server3 server3 9999 9000 7 STANDBY 0 MEMBER # スタンバイとして稼働している
   </programlisting>
   <para>
    リーダーである<literal>server1</literal>の<productname>Pgpool-II</productname>を停止し、<literal>server2</literal>または<literal>server3</literal>のどちらかがリーダーになることを確認します。
    <literal>server1</literal>の<productname>Pgpool-II</productname>を停止するには<productname>Pgpool-II</productname>を停止するか、マシンをシャットダウンします。ここでは、<productname>Pgpool-II</productname>を停止します。
   </para>
   <programlisting>
[root@server1 ~]# systemctl stop pgpool.service

[root@server1 ~]# pcp_watchdog_info -p 9898 -h 192.168.100.50 -U pgpool
Password:
3 3 YES server2:9999 Linux server2 server2

server2:9999 Linux server2 server2 9999 9000 4 LEADER 0 MEMBER    # server2がリーダーに昇格
server1:9999 Linux server1 server1 9999 9000 10 SHUTDOWN 0 MEMBER # server1が停止している
server3:9999 Linux server3 server3 9999 9000 7 STANDBY 0 MEMBER   # server3がタンバイとして稼働している
   </programlisting>
   <para>
    先ほど停止した<productname>Pgpool-II</productname>を再起動し、スタンバイとして起動していることを確認します。
   </para>
   <programlisting>
[root@server1 ~]# systemctl start pgpool.service

[root@server1 ~]# pcp_watchdog_info -p 9898 -h 192.168.100.50 -U pgpool
Password: 
3 3 YES server2:9999 Linux server2 server2

server2:9999 Linux server2 server2 9999 9000 4 LEADER 0 MEMBER
server1:9999 Linux server1 server1 9999 9000 7 STANDBY 0 MEMBER
server3:9999 Linux server3 server3 9999 9000 7 STANDBY 0 MEMBER
   </programlisting>
  </sect3>

  <sect3 id="example-cluster-verify-failover">
   <title>自動フェイルオーバ</title>
   <para>
    <command>psql</command>で仮想IP経由で<productname>Pgpool-II</productname>に接続し、バックエンドの情報を確認します。
   </para>
   <programlisting>
[いずれかのサーバ]# psql -h 192.168.100.50 -p 9999 -U pgpool postgres -c "show pool_nodes"
Password for user 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       | server1  | 5432 | up     | up        | 0.333333  | primary | primary | 0          | false             | 0                 |                   |                        | 2023-11-10 15:30:14
 1       | server2  | 5432 | up     | up        | 0.333333  | standby | standby | 0          | false             | 0                 | streaming         | async                  | 2023-11-10 16:32:33
 2       | server3  | 5432 | up     | up        | 0.333333  | standby | standby | 0          | true              | 0                 | streaming         | async                  | 2023-11-10 16:33:08
(3 rows)
   </programlisting>
   <para>
    次にプライマリである<literal>server1</literal>の<productname>PostgreSQL</productname>を停止し、
    フェイルオーバするかどうか確認してみます。
   </para>
   <programlisting>
[root@server1 ~]# su - postgres -c "/usr/pgsql-18/bin/pg_ctl -m immediate stop"
   </programlisting>
   <para>
    <literal>ノード1</literal>を停止した後に、フェイルオーバが発生し、<literal>server2</literal>が
    プライマリに昇格したことを確認します。
   </para>
   <programlisting>
[いずれかのサーバ]# psql -h 192.168.100.50 -p 9999 -U pgpool postgres -c "show pool_nodes"
Password for user 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       | server1  | 5432 | down   | down      | 0.333333  | standby | unknown | 0          | false             | 0                 |                   |                        | 2023-11-10 17:05:40
 1       | server2  | 5432 | up     | up        | 0.333333  | primary | primary | 0          | false             | 0                 |                   |                        | 2023-11-10 17:05:40
 2       | server3  | 5432 | up     | up        | 0.333333  | standby | standby | 0          | true              | 0                 | streaming         | async                  | 2023-11-10 17:05:51
(3 rows)
   </programlisting>

   <para>
    <literal>server3</literal>が新しいプライマリ<literal>server2</literal>のスタンバイとして起動していることを確認します。
   </para>

   <programlisting>
[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              | 7198
usesysid         | 16385
usename          | repl
application_name | server3
client_addr      | 192.168.100.53
client_hostname  |
client_port      | 40916
backend_start    | 2023-11-10 17:10:03.067241+00
backend_xmin     |
state            | streaming
sent_lsn         | 0/12000260
write_lsn        | 0/12000260
flush_lsn        | 0/12000260
replay_lsn       | 0/12000260
write_lag        |
flush_lag        |
replay_lag       |
sync_priority    | 0
sync_state       | async
reply_time       | 2023-11-10 17:17:23.886477+00
   </programlisting>
  </sect3>

  <sect3 id="example-cluster-verify-online-recovery">
   <title>オンラインリカバリ</title>
   <para>
    次に、<productname>Pgpool-II</productname>のオンラインリカバリ機能を利用し、
    先ほど停止した旧プライマリサーバをスタンバイとして復旧させます。
    <command>pcp_recovery_node</command>コマンドで<filename>recovery_1st_stage</filename>と<filename>pgpool_remote_start</filename>スクリプトが実行されるので（<filename>recovery_1st_stage</filename>は<varname>recovery_1st_stage_command</varname>パラメータに設定したスクリプト）、この2つのスクリプトが現在稼働中のプライマリサーバ<literal>server2</literal>のデータベースクラスタに存在することを確認してください。
   </para>
   <programlisting>
[いずれかのサーバ]# pcp_recovery_node -h 192.168.100.50 -p 9898 -U pgpool -n 0
Password:
pcp_recovery_node -- Command Successful
   </programlisting>
   <para>
    <literal>server1</literal>がスタンバイとして起動していることを確認します。
   </para>
   <programlisting>
[any server]# psql -h 192.168.100.50 -p 9999 -U pgpool postgres -c "show pool_nodes"
Password for user 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       | server1  | 5432 | up     | up        | 0.333333  | standby | standby | 0          | true              | 0                 | streaming         | async                  | 2023-11-10 17:22:03
 1       | server2  | 5432 | up     | up        | 0.333333  | primary | primary | 0          | false             | 0                 |                   |                        | 2023-11-10 17:05:40
 2       | server3  | 5432 | up     | up        | 0.333333  | standby | standby | 0          | falas             | 0                 | streaming         | async                  | 2023-11-10 17:05:51
(3 rows)
   </programlisting>
   <para>
    以上で、動作確認が完了です。
   </para>
  </sect3>
 </sect2>
</sect1>
