【PostgreSQL】pgpool-Ⅱでレプリケーション、インストールと設定
PostgreSQLでレプリケーションするにはpgpool-Ⅱというミドルウェアで簡単にできるということなのでインストールと設定をメモ。
参考になるサイトは下記
【データベース夏の陣】PostgreSQLには絶対!pgpool-II
(仮タイトル)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を起動するときは「非デーモンモード」で起動しないとログを出力しない