【PostgreSQL】pgpool-Ⅱでレプリケーション、インストールと設定

PostgreSQLでレプリケーションするにはpgpool-Ⅱというミドルウェアで簡単にできるということなのでインストールと設定をメモ。

参考になるサイトは下記

【データベース夏の陣】PostgreSQLには絶対!pgpool-II

pukiwiki:pgpoolAdmin/install

(仮タイトル)pgpool-IIによるレプリケーションとオンラインリカバリ

まずはPostgreSQLをインストール。やり方は前の記事を参考に。

pgpoolはここからダウンロード。

解凍とコンパイル
# tar xzvf pgpool-II-2.2.tar.gz
# cd  pgpool-II-2.2
# ./configure
# make
# make install

オンラインリカバリのためのライブラリもインストール
# su postgres 
$ cd /opt/software/pgpool-II-2.2/sql/pgpool-recovery/
$ make
$ make install
$ psql -c "\i /usr/local/pgsql/share/contrib/pgpool-recovery.sql" template1

make installで権限がない場合は/usr/local/pgsqlの権限をまるっと変える
# chown postgres –R /usr/local/pgsql

設定ファイルをコピーする
# cd /usr/local/etc/
# cp pgpool.conf.sample pgpool.conf
# cp pcp.conf.sample pcp.conf

pcp.confに記述するパスワードを取得(pgpoolAdminのログインパスワード)
# pg_md5 –p
password: (パスワードを入力)

pcp.confに取得したバスワードを記述する
# vi pcp.conf

pgpool管理ツールpgpoolAdminをここからダウンロードする。

解凍
# tar xzvf pgpoolAdmin-2.2.tar.gz

解凍したディレクトリをweb公開しているディレクトリに配置しても良し。apacheの設定ファイルに新たにエイリアスを記述しても良し。

#
#pgpoolAdmin
#
Alias /pgpool_admin "/opt/software/pgpoolAdmin-2.2"
<Directory "/opt/software/pgpoolAdmin-2.2">
   AllowOverride All
   Order allow,deny
   Allow from all
</Directory>

apache(lampp)を再起動
# /etc/rc.d/init.d/lampp restart

権限を設定
# cd pgpoolAdmin-2.2/
# chown apache conf/pgmgt.conf.php
# chmod 664 conf/pgmgt.conf.php

設定ファイルの権限を設定
# cd /usr/local/etc/
# chown apache pgpool.conf pcp.conf
# chmod 644 pgpool.conf pcp.conf

これで設定は完了。ブラウザでインストールディレクトリにアクセスする

http://<サーバ名>/pgpool_admin/install/index.php

テンプレートディレクトリを作る
# mkdir templates_c
# chmod 777 templates_c

インストールが完了したらinstallディレクトリを削除する。
# cd /opt/software/pgpoolAdmin-2.2/
# rm -rf install/

これでトップページへ移動して「pgpool起動」を押すとpgpoolが起動・・・すると思いきや。起動せず。

pgpool start failed. pgpool.pid not found

とエラーがでる。

pgpool.pidを作成するときに権限がなくてエラーになっているみたいなので、権限を設定する
# cd /var/run/
# mkdir pgpool
# chmod 777 pgpool

pgpool.conf設定で設定可能な「pidファイルの名前」を/tmp/pgpool.pidに変えてもいけると思うけど、これで解決。

次はレプリケーションの設定

「pgpool.conf設定」にアクセスしてBackendsの「追加」をクリック。

new backend_hostname : localhost
new backend_port : 5432
new backend_weight : 1
new backend_data_directory : /usr/local/pgsql/data

で更新。もう一度追加を押してもう一つのPostgreSQLを指定

new backend_hostname : 192.168.0.32
new backend_port : 5432
new backend_weight : 1
new backend_data_directory : /usr/local/pgsql/data

その他の設定

listen_addresses : *
replication_mode : true
reset_query_list : DISCARD ALL
replication_stop_on_mismatch : true

PostgreSQL 8.3以上ではreset_query_listをDISCARD ALLにしておくのがおすすめらしい。参考

replication_stop_on_mismatchをonにすると、同期ができていなくてもとりあえず動く。どっちかが死んでも動き続けてほしいのでtrueに。

これでトップページへ移動してpgpool再起動。ノード情報が出ていれば問題なし。

試しにpsqlでアクセスしてsql文を発行してみる。
# psql –p 9999

・・・とここで、

psql: server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.

と怒られた。レプリケーションモードでは認証モードがmd5を利用できないらしい。参考

localhostのpg_hba.confを次のように変更。

#host    all         all         127.0.0.1/32          trust
host    all         all         127.0.0.1/32          password

別サーバのpg_hba.confは次のように変更。

host    all             all     192.168.0.0/24          password
host    all             all     192.168.1.0/24          password

PostgreSQLのサーバとpgpoolを再起動。

試しにcreatedbしてみる。
# createdb -p 9999 testdb

できた。

PgAdmin3で接続するときは、もちろんポートは9999。ファイヤーウォールをあけておくのを忘れずに。参考

例:pg_dumpしたデータを戻すとき

# psql -p 9999 -e testdb < /tmp/testdb20090410.sql

データベースは同じデータが書き込まれているけど、PgAdmin3でアクセスすると下記のエラーが。

ERROR:  kind mismatch among backends. Possible last query was: "SET DateStyle=ISO;SELECT oid, pg_encoding_to_char(encoding) AS encodin
message contents do not agree with length in message type "E"
server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.

うまくマスタとスレーブで同期がとれなくなっているみたい。

これを解決するためにオンラインリカバリ(PostgreSQLを止めることなく破損したDBを同期してリカバリ)を設定。

今回はマスタ(192.168.0.31)→スレーブ(192.168.0.32)の場合のみ

マスタ(192.168.0.31)で作業。archive_modeを有効にする
# su postgres
$ cd /usr/local/pgsql/data
$ mkdir archive_log
$ vi postgresql.conf

archive_mode = on
archive_command = 'cp "%p" /usr/local/pgsql/data/archive_log/"%f"'

サーバ再起動
$ exit
# /etc/rc.d/init.d/postgresql restart

スレーブ(192.168.0.32)にアクセスして受け入れ準備
# mkdir /usr/local/pgsql/data/archive_log
# chown postgres -R /usr/local/pgsql/

マスタ(192.168.0.31)で作業。さっきも書いたここを参考にオンラインリカバリ用のシェルスクリプトを用意。

$ vi /usr/local/pgsql/data/recovery_1st_stage.sh

#! /bin/bash

PSQL=/usr/local/pgsql/bin/psql

MASTER_BASEDIR=$1
RECOVERY_HOST=$2
RECOVERY_BASEDIR=$3

# ベースバックアップの開始 
$PSQL -c "SELECT pg_start_backup('pgpool-recovery')" postgres

# リカバリ先用のrecovry.confファイル生成
echo "restore_command = 'cp $RECOVERY_BASEDIR/archive_log/%f %p'" > $MASTER_BASEDIR/recovery.conf

# リカバリ先のデータベースクラスタを念のためにバックアップ
ssh -T $RECOVERY_HOST rm -rf $RECOVERY_BASEDIR.bk
ssh -T $RECOVERY_HOST mv -f  $RECOVERY_BASEDIR{,.bk}

# データベースクラスタ=ベースバックアップをリカバリ先に転送
rsync -az -e ssh $MASTER_BASEDIR/ $RECOVERY_HOST:$RECOVERY_BASEDIR/

ssh -T $RECOVERY_HOST cp -f  $RECOVERY_BASEDIR.bk/postgresql.conf $RECOVERY_BASEDIR
ssh -T $RECOVERY_HOST rm -f  $RECOVERY_BASEDIR/postmaster.pid

# リカバリ先に転送したので、不要になったrecovery.confを削除
rm -f $MASTER_BASEDIR/recovery.conf

# ベースバックアップの終了
$PSQL -c "SELECT pg_stop_backup()" postgres

$ vi /usr/local/pgsql/data/recovery_2nd_stage.sh

#! /bin/bash

PSQL=/usr/local/pgsql/bin/psql

MASTER_BASEDIR=$1
RECOVERY_HOST=$2
RECOVERY_BASEDIR=$3

# 最新のアーカイブログを保存
$PSQL -c 'SELECT pg_switch_xlog()' postgres

# 最新のアーカイブログをリカバリ先に転送
rsync -az -e ssh $MASTER_BASEDIR/archive_log/ $RECOVERY_HOST:$RECOVERY_BASEDIR/archive_log/

$ vi /usr/local/pgsql/data/pgpool_remote_start

#! /bin/sh

PGCTL=/usr/local/pgsql/bin/pg_ctl

RECOVERY_HOST=$1
RECOVERY_BASEDIR=$2

# リカバリ先のPostgreSQLを起動
ssh -T $RECOVERY_HOST $PGCTL -w -D $RECOVERY_BASEDIR start 2>/dev/null 1> /dev/null < /dev/null &

権限の設定

# cd /usr/local/pgsql/data/
# chmod 755 recovery_1st_stage.sh
# chmod 755 recovery_2nd_stage.sh
# chmod 755 pgpool_remote_start

pgpoolのOnline Recoveryの項目に追加

recovery_user : postgres
recovery_password : (設定したパスワード)
recovery_1st_stage_command : recovery_1st_stage.sh
recovery_2nd_stage_command : recovery_2nd_stage.sh
recovery_timeout : 90

これでpgpoolを再起動。

あとスクリプトの中でSSHで別サーバにアクセスしてコマンドを実行するので、その(パスワードなしでスレーブにアクセスするための)設定。マスタ(192.168.0.31)で作業。

# su postgres
$ cd
$ ssh-keygen -t dsa # パスフレーズは空白
$ scp ~/.ssh/id_dsa.pub 192.168.0.32:~/
$ ssh 192.168.0.32
$ cat id_dsa.pub >> ~/.ssh/authorized_keys2
$ rm –f id_dsa.pub
$ chmod 600 ~/.ssh/authorized_keys2

cat id_dsa.pub >> ~/.ssh/authorized_keys2で怒られる場合はスレーブ(192.168.0.32)で
$ ssh-keygen -t dsa
を実行しておく。

以上で準備完了。

いざオンラインリカバリを実行。

pgpoolのノード1を切断しておいて
$ pcp_recovery_node 100 127.0.0.1 9898 postgres (設定したパスワード) 1

を実行。

・・・失敗。

pgpool.logには下記のようなエラーが。

2009-04-12 20:15:16 ERROR: pid 8924: check_postmaster_started: remote host start up did no
t finish in 90 sec.
2009-04-12 20:15:16 ERROR: pid 8924: start_recovery: check start failed

スレーブ(192.168.0.32)のPostgreSQLを止めておくのを忘れてた。

スレーブ(192.168.0.32)を元に戻してもう一回実行。

できた。

わーい。

スレーブ(192.168.0.32)のpg_hba.confを上書きしてしまうみたいなので、これを修正してPostgreSQLを再起動。

PgAdmin3でも正常に表示。

これでマスタのサーバを止めずにリカバリが可能に。

※サーバを止めていいなら、dataをそのままコピーすれば良い(と思う)。

最後に起動スクリプトをコピーして再起動後も自動で立ち上がるようにしておく。
# cd /opt/software/pgpool-II-2.2/
# cp redhat/pgpool.init  /etc/rc.d/init.d/pgpool
# chkconfig --add pgpool
# chkconfig pgpool on

環境に合わせてスクリプトを修正
# vi /etc/rc.d/init.d/pgpool
PGPOOLENGINE=/usr/local/bin
PGPOOLCONF=/usr/local/etc/pgpool.conf

スクリプト起動しようとすると失敗したので、調べてみると権限がダメらしい
# chmod 777 /var/run/pgpool

再起動して確認
# reboot

オンラインリカバリまでやろうとすると簡単ではなかった。

 

<2010/01/15 追記>
pgpool-II-2.3.1でインストールしたので上記内容を修正。あとポイント

  • pgpoolを起動するときは「非デーモンモード」で起動しないとログを出力しない