Heartbeat scrpits for pgpool 

1. このプログラムとは

Heartbeat 2.0以降にはCRM(Cluster Resource Manager)を使うことでサービス監視を
含むリソース管理を行ってくれるため、容易に高可用性サービスを立ち上げることが
可能になります。これとPostgreSQLのレプリケーションを実現するpgpoolを組み合わ
せることで、PostgreSQLサービスの冗長化をより簡単に行うことが出来ます。

サービス図：

                              +---------+   +----------+
                             /|[pgpool] |---|PostgreSQL|
+------+     +----------+   / +---------+   +----------+
|client| --> |Virtual IP| --             \
+------+     +----------+   \ +---------+ \ +----------+
                             \|(pgpool) |  -|PostgreSQL|
                              +---------+   +----------+


本プログラムはHeartbeatと連携してpgpoolを高可用性対応するため、以下のコードが
含まれています。

- Heartbeat 2.0以降で利用できるOCF形式のpgpool管理スクリプト
- 管理スクリプト内で使用する監視プログラム

2. インストール

このプログラムを利用するためには少なくとも２台のマシンと、それぞれに以下のものが
インストールされている必要があります。

-PostgreSQL(http://www.postgresql.org/) のクライアント
psqlのみを必要とします。インストール時に環境変数PATHで参照可能な位置に配置してく
ださい。

-perl(http://www.perl.com/)
perl 5以上とGetOpt::Longを必要とします。
-pgpool(http://pgpool.projects.postgresql.org/)
インストール時に環境変数PATHで参照可能な位置に配置してください。設定ファイルにつ
いては指定しない場合インストール時のデフォルト位置になります。


-heartbeat 2.0以降(http://www.linux-ha.org/)

また、このホストに入っている必要はありませんが、以下のソフトウェアも必要になります。

-PostgreSQL 

接続監視する関係上、pgpoolが接続する先としてのPostgreSQLサーバーが必要になります。
これには、以下の条件があります。

--pgpoolが稼働しているサーバーから指定データベースへの指定ユーザーからの接続に対する
trust認証が許されていること。この時指定データベースとユーザー名は

　　-pgpool.confのhealth_check_userが有効な場合、ユーザー名として、また同時にdatabase名としても利用されます。標準のpgpoolの場合、nobodyと言う名称のロール及びデータベースが必要です。

　　-有効な値がない場合、postgresユーザ/template1データベースが利用されます。



2.2 インストール手順

基本的なプログラム、pgpool起動と監視スクリプトは以下の通りでインストール
できます。pgpool,psqlを環境変数で参照できる形にしておいてください。

# ./configure
# cd src
# make
# make install

この時、OCF仕様のスクリプト"pgpool"が/usr/lib/orf/resource.d/heartbeat/以下に、
監視スクリプトpgpool.monitorがpgpoolと同じディレクトリにコピーされます。

2.3 heartbeatの設定
heartbeat上でpgpoolを稼働させるためにはheartbeat側の設定が必要になります。

-ha.cf
crmを利用します。以下の一行を設定してください。

crm	true

-cib.xml
cib.xmlはheartbeatでcrmを利用するために必要なファイルで、通常/var/lib/heartbeat/crm/以下に配置されています。サンプルとして1仮想IPアドレス、アクティブ/スタンバイのpgpool構成を行うcib.xmlを以下に示します。

<cib generated="true" admin_epoch="0" have_quorum="true" num_peers="2" ccm_transition="4" cib_feature_revision="1.2" crm_feature_set="1.0.4" debug_source="sync_our_cib" dc_uuid="cf40f895-0e3c-4847-b8b3-6ae1fad7921f" last_written="Mon Jul 24 07:25:00 2006" epoch="42" num_updates="1521">
   <configuration>
     <crm_config>
       <cluster_property_set id="deafult">
         <attributes>
           <nvpair id="symmetric_cluster" name="symmetric_cluster" value="true"/>
           <nvpair id="no_quorum_policy" name="no_quorum_policy" value="stop"/>
           <nvpair id="default_resource_stickiness" name="default_resource_stickiness" value="0"/>
           <nvpair id="stonith_enabled" name="stonith_enabled" value="false"/>
           <nvpair id="stop_orphan_resources" name="stop_orphan_resources" value="false"/>
           <nvpair id="stop_orphan_actions" name="stop_orphan_actions" value="true"/>
           <nvpair id="remove_after_stop" name="remove_after_stop" value="false"/>
           <nvpair id="short_resource_names" name="short_resource_names" value="true"/>
           <nvpair id="transition_idle_timeout" name="transition_idle_timeout" value="5min"/>
           <nvpair id="is_managed_default" name="is_managed_default" value="true"/>
         </attributes>
       </cluster_property_set>
     </crm_config>
     <nodes>
       <node id="cf40f895-0e3c-4847-b8b3-6ae1fad7921f" uname="node1" type="normal"/>
       <node id="3e919e96-e476-4d3e-be05-0048b9e12a56" uname="node2" type="normal"/>
     </nodes>
     <resources>
       <group id="group_1">
         <primitive class="ocf" id="IPaddr_1" provider="heartbeat" type="IPaddr">
           <operations>
             <op id="IPaddr_1_mon" interval="5s" name="monitor" timeout="5s"/>
           </operations>
           <instance_attributes>
             <attributes>
               <nvpair id="IPaddr_1_attr_0" name="ip" value="192.168.0.3"/>
             </attributes>
           </instance_attributes>
         </primitive>
         <primitive class="ocf" id="pgpool_2" provider="heartbeat" type="pgpool">
           <operations>
             <op id="pgpool_2_mon" interval="30s" name="monitor" timeout="20s"/>
           </operations>
         </primitive>
       </group>
     </resources>
     <constraints>
       <rsc_location id="rsc_location_group_1" rsc="group_1">
         <rule id="prefered_location_group_1" score="100">
           <expression attribute="#uname" id="prefered_location_group_1_expr" operation="eq" value="node1"/>
         </rule>
       </rsc_location>
     </constraints>
   </configuration>
 </cib>

この設定ファイル例によりpgpoolを管理できるようになります。この中で書き換える項目は以下の通りになります。

-ノード名
　サンプル中node1,node2と示されているのがノード名になります。ここではha.cfで指定してあるファイルと同じ名称を指定してください。

-IPアドレス
　サンプル中で192.168.0.3と示されているのが仮想IPアドレスです。ここに指定することでpgpoolが稼働中のホストに当該IPアドレスが割り振られます。

-設定ファイルの格納場所(任意)
  設定ファイルの格納場所がデフォルト以外の場合、instance_attributes項目に以下のキーと、値としてそのファイル名を指定することで設定できます。

ファイル名	,	指定するキー	,	備考
pgpool.conf	,	pgpoolconf	,	
pool_hba.conf	,	hbaconf		,	pgpool 3.2以降で有効
pcp.conf	,	pcpconf		,	pgpool-IIでのみ有効

  なお、この設定はpgpool 1.1以降でのみ有効です。

-ログファイルの出力先
　設定ファイルの格納場所と同様、ログファイルの出力先を指定することも可能です。logfileをキーに、対応するファイル名を
値として記述することで指定場所にリダイレクト出力するようになります。なお、ログファイル出力時は-d、デバッグオプションが
自動的に付与されます。




　以下に、実際の設定例を示します。ここでは、先の設定ファイルのpgpool設定部分
のみを記述しますので、随時置き換えてください。

 <primitive class="ocf" id="pgpool_2" provider="heartbeat"
type="pgpool">
   <operations>
     <op id="pgpool_2_mon" interval="30s" name="monitor"
timeout="20s"/>
   </operations>
   <instance_attributes id="4e369437-b6ac-4f47-96bd-029f7e4a95fc">
     <attributes>
       <nvpair id="pgpool_2_attr_1" name="pgpoolconf"
				value="/path/to/pgpool.conf"/>
       <nvpair id="pgpool_2_attr_2" name="hbaconf"
				value="/path/to/pool_hba.conf"/>
       <nvpair id="pgpool_2_attr_3" name="pcpconf"
				value="/path/to/pcp.conf"/>
       <nvpair id="pgpool_2_attr_4" name="logfile"
                                        value="/path/to/logfile"/>
    </attributes>
   </instance_attributes>
 </primitive>



　この記述が終了したらファイルをheartbeatが利用する全てのサーバーに配置します。cib.xmlはサーバー間で全く同じである必要があります。なお、記述の検証にはheartbeatに付属しているcrm_verifyコマンドが使えます。

crm_verify -VX /opt/powergres/hb/var/lib/heartbeat/crm/cib.xml

　最後に全てが終わったら起動して確認します。

# service heartbeat start

そのあとheartbeat自体の起動が終了まで数分待ち、psにてpgpoolが起動することを確認することが出来れば完了です。

2.3 active-active 構成について

pgpool-HA
1.1以降では、複数の設定ファイルが記述できるため、Active-Active構成を取ることが可能になります。
以下に、/usr/local/pgsql/etc/pgpool-host1.conf と
/usr/local/pgsql/etc/pgpool-host2.conf で示される構成を、192.168.0.3 と
192.168.0.4 の２種類のIPで実行する場合の例を示します。

    <nodes>
       <node id="cf40f895-0e3c-4847-b8b3-6ae1fad7921f" uname="node1" type="normal"/>
       <node id="3e919e96-e476-4d3e-be05-0048b9e12a56" uname="node2" type="normal"/>
     </nodes>
     <resources>
       <group id="group_1">
         <primitive class="ocf" id="IPaddr_1" provider="heartbeat" type="IPaddr">
           <operations>
             <op id="IPaddr_1_mon" interval="5s" name="monitor" timeout="5s"/>
           </operations>
           <instance_attributes id="4e369437-b5ac-4f47-96bd-029f7e4a95fc">
             <attributes>
               <nvpair id="IPaddr_1_attr_0" name="ip" value="192.168.0.3"/>
             </attributes>
           </instance_attributes>
         </primitive>
         <primitive class="ocf" id="pgpool_2" provider="heartbeat"
type="pgpool">
           <operations>
             <op id="pgpool_2_mon" interval="30s" name="monitor"
timeout="20s"/>
           </operations>
           <instance_attributes id="4e369437-b6ac-4f47-96bd-029f7e4a95fc">
             <attributes>
               <nvpair id="pgpool_2_attr_0" name="pgpoolconf" value="/usr/local/pgsql/etc/pgpool-vip1.conf"/>
               <nvpair id="pgpool_2_attr_1" name="hbaconf" value="/usr/local/pgsql/etc/pool_hba.conf"/>
             </attributes>
           </instance_attributes>
         </primitive>
       </group>
       <group id="group_2">
         <primitive class="ocf" id="IPaddr_3" provider="heartbeat" type="IPaddr">
           <operations>
             <op id="IPaddr_3_mon" interval="5s" name="monitor" timeout="5s"/>
           </operations>
           <instance_attributes id="5e369437-b5ac-4f47-96bd-029f7e4a95fc">
             <attributes>
               <nvpair id="IPaddr_3_attr_0" name="ip" value="192.168.0.4"/>
             </attributes>
           </instance_attributes>
         </primitive>
         <primitive class="ocf" id="pgpool_4" provider="heartbeat"
type="pgpool">
           <operations>
             <op id="pgpool_4_mon" interval="30s" name="monitor"
timeout="20s"/>
           </operations>
           <instance_attributes id="5e369437-b6ac-4f47-96bd-029f7e4a95fc">
             <attributes>
               <nvpair id="pgpool_4_attr_0" name="pgpoolconf" value="/usr/local/pgsql/etc/pgpool-vip2.conf"/>
               <nvpair id="pgpool_4_attr_1" name="hbaconf" value="/usr/local/pgsql/etc/etc/pool_hba.conf"/>
             </attributes>
           </instance_attributes>
         </primitive>
       </group>
     </resources>
     <constraints>
       <rsc_location id="rsc_location_group_1" rsc="group_1">
         <rule id="prefered_location_group_1" score="100">
           <expression attribute="#uname" id="prefered_location_group_1_expr"
operation="eq" value="node1"/>
         </rule>
       </rsc_location>
       <rsc_location id="rsc_location_group_2" rsc="group_2">
         <rule id="prefered_location_group_2" score="100">
           <expression attribute="#uname" id="prefered_location_group_2_expr"
operation="eq" value="node2"/>
         </rule>
       </rsc_location>
     </constraints>


3. 利用方法

本ソリューションの起動及び終了はheartbeat経由で自動で行われます。順序としては以下の通りになります。

- PostgreSQLを起動

pgpoolで利用するPostgreSQLを起動します。

- heartbeatを起動

heartbeatを起動します。起動する場合はサービスとして

#service heartbeat start

と利用します。しばらくするとpgpoolが利用可能になります。この後、psql等で接続するためにはcib.xmlで指定したIPアドレスとpgpoolで指定したポートを指定します。例えば先ほどのサンプルの場合

psql -h 192.168.0.3 -p 9999

と実行すれば接続できます。

終了させる場合は、全く逆に全てのサーバーでheartbeatを終了させてください。heartbeatの終了のためには以下の通りのコマンドを実行します。

# service heartbeat stop

4. FAQ

-接続できない
以下の項目を確認してください。

--heartbeatが起動しているか。

起動していない場合、heartbeatのインストールか設定ファイルに問題があります。

--heartbeatが起動していて、psの出力の中にcrmdが存在しているか

crmdが立ち上がってない、終了した場合にはcib.xmlファイルの内容にエラーがある可能性があります。特に前回実行時の内容を署名していますので、.sigファイルが当該ディレクトリに存在している場合にはエラーになります。そのため、書き換えた場合には*.sigファイルを消去し、再度実行してみてください。

--pgpoolが起動しているか。

起動していない場合、pgpoolが単独で実行できるかどうかを確認してください。また、設定ファイルの内容も確認して下さい。

--PostgreSQLが起動しているか。

起動していない場合は立ち上げてください。

--浮動IPに対してping等でアクセスできるか。

アクセスできない場合には設定ファイルを再度確認してください。


なお、一度全てのホストでheartbeatを終了/起動させることで実行できることがあります。

-PGClusterのロードバランサーの冗長化に使えるか？
技術的には可能ですが、現在その設定に必要な内容が不足しているため、利用することは出来ません。このためには以下の作業が必要です。

--pgpoolファイルを書き換え、pglbを起動終了させるようにする
--pgpoolファイルを書き換え、設定ファイル無しにポート番号等を指定するようにする。


5. 制限事項
・本プログラムに置ける監視はpgpoolの稼働チェック(pidファイルとSQL発行)のみです。
それ以外の異常状態（起動して、SQL文も受け付けるが異常が発生しているような場合など）には対応できません。
・PostgreSQL に対する管理は行っていません。
・PostgreSQL が全く起動していない状態は異常であるとみなし、フェイルオーバーし続けますが、これは現段階の仕様です。
・PostgreSQL がクラッシュした場合のリカバリは別途手動で行う必要があります。この方法についてはpgpoolに準じます。
・ロックの問題、now()関数、OIDといったpgpoolの技術的制限事項が解消するわけ ではありません。
・pgpoolが複数インストールされている場合の挙動は、インストール時の$PATHに依存して決定します。他の種類のバイナリは管理できません。
・pgpool-II監視はpsqlで行われます。pcpを利用した監視はまだサポートされていません。

6. 著作権
本プログラムは谷田　豊盛（ゆたか） (tanida@sraoss.co.jp)がSRA OSS,Inc.日本支社の後援の元作成し、pgpool global development groupに寄贈されました。ライセンスはpgpoolに準じますが、詳細は付属のCOPYINGファイルを参照ください。


