「pgpool-II」でオンラインリカバリの手順
2011年12月14日「pgpool-II」でオンラインリカバリの手順
pgpool-IIの新機能である、「オンラインリカバリ」を検証した手順メモ。
【環境】
以下の環境でテストしました
| サービス | ホスト | バージョン | OS |
| pgpool-II | 192.168.11.145 | pgpool-II-3.0.5 | CentOS5.6 |
| postgresql0(ノード0) | 192.168.11.145 | postgresql-8.1.23-1 | CentOS5.6 |
| postgresql1(ノード1) | 192.168.11.146 | postgresql-8.1.23-1 | CentOS5.6 |
各サービスはインストール済みであるとします
参考: PostgreSQL用クラスタリングツール「pgpool-II」のインストール
【ノード0と1の共通設定】
アーカイブディレクトリの作成
$ sudo su – postgres
postgres$ initdb -D /var/lib/pgsql/data
設定ファイルの変更
$ sudo vim /var/lib/pqsql/data/postgresql.conf
… 以下を変更
listen_addresses = ‘*’
archive_command = ‘cp %p /usr/local/pgsql/data/archive_log/%f’$ sudo vim /var/lib/pgsql/data/pg_hba.conf
…以下を追加
host all all 192.168.11.0/24 trust
オンラインリカバリ用Shellの作成
$ sudo su – postgres
$ cd /var/lib/pgsql/data
$ vim recovery_1st_stage.sh
\#!/bin/bashPSQL=/usr/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 -acz -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$ vim recovery_2nd_stage.sh
\#! /bin/bashPSQL=/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/$ vim pgpool_remote_start
\#!/bin/shPGCTL=/usr/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 &
パーミッション設定
chmod 755 recovery_1st_stage.sh recovery_2nd_stage.sh pgpool_remote_start
【pgpool設定】
pool_hba.confの設定
$ sudo vim /usr/local/etc/pool_hba.conf
… 以下を追加
host all all 192.168.11.0/24 trust
pgpool.confの設定
$ sudo vim /usr/local/etc/pgpool.conf
… 以下を変更
\# – online recovery –
\# online recovery user
recovery_user = ‘postgres’\# online recovery password
recovery_password = ”\# execute a command in first stage.
recovery_1st_stage_command = ‘recovery_1st_stage.sh’\# execute a command in second stage.
recovery_2nd_stage_command = ‘recovery_2nd_stage.sh’
【サービス起動】
ノード0と、ノード1でPostgresqlを起動する
$ sudo /etc/rc.d/init.d/postgresql start
【sshキーの作成】
ノード0で、以下を実行
$ sudo su – postgres
postgres $ ssh-keygen -t dsa
postgres $ scp ~/.ssh/id_dsa.pub 192.168.11.146:~/
postgres $ ssh 192.168.1.101
postgres@postgres1 $ cat id_dsa.pub >> ~/.ssh/authorized_keys2
postgres@postgres1 $ rm id_dsa.pub
ノード1で、以下を実行
$ sudo su – postgres
postgres $ ssh-keygen -t dsa
postgres $ scp ~/.ssh/id_dsa.pub 192.168.1.100:~/
postgres $ ssh 192.168.1.100
postgres@postgres0 $ cat id_dsa.pub >> ~/.ssh/authorized_keys2
postgres@postgres0 $ rm id_dsa.pub
それぞれのノードから、相手先ノードへパスフレーズなしでSSHできることを確認する
【C言語関数のインストール】
各ノードで、以下のコマンドを実行
pgpool-recoveryのインストール
$ cd /usr/local/src
$ sudo wget http://pgfoundry.org/frs/download.php/3164/pgpool-II-3.0.5.tar.gz
$ sudo tar zxf pgpool-II-3.0.5.tar.gz
$ cd pgpool-II-3.0.5/sql/pgpool-recovery
$ make install$ sudo cp pgpool-recovery.so /usr/lib/pgsql
$ sudo cp /pgpool-recovery.sql /usr/share/pgsql/
$ psql -U postgres -c “\i /usr/share/pgsql/pgpool-recovery.sql” template1
【オンラインリカバリの実行】
- データベース作成
$ createdb -p 9999 bench -U postgres
- ノード1を停止する
$ sudo su – postgres
postgres$ pg_ctl -D /var/lib/pgsql/data -m immediate stop
- 片系ノード稼働中に、DBの変更を行う
$ pgbench -i -p 9999 bench
- 以下のコマンドで、オンラインリカバリを実行する
pcp_recovery_node timeout hostname port# username password
例(ノード0→ノード1へのオンラインリカバリ):
pcp_recovery_node 10 192.168.11.146 9898 postgres password 1
- 確認
$ psql -U postgres -h 192.168.11.145
$ psql -U postgres -h 192.168.11.146
【問題点】
以下のトラブルが未解決
- オンラインリカバリ後、リカバリした側のPostgresqlがpidファイルなしで起動している
- /etc/rc.d/init.d/postgresql restartなどが利用できなくなっている
といった問題点をのこしつつも、オンラインリカバリには成功
【参考】
ノード0:pg_hba.conf
\# TYPE DATABASE USER CIDR-ADDRESS METHOD
\# “local” is for Unix domain socket connections only
\#local all all ident sameuser
local all all trust
\# IPv4 local connections:
\#host all all 127.0.0.1/32 ident sameuser
host all all 127.0.0.1/32 trust
host all all 192.168.11.0/24 trust
host template1 nobody 192.168.11.0/24 trust
\# IPv6 local connections:
\#host all all ::1/128 ident sameuser
ノード0:postgresql.conf
\# – Connection Settings –
listen_addresses = ‘‘ # what IP address(es) to listen on;
# comma-separated list of addresses;
# defaults to ‘localhost’, ‘‘ = all
port = 5432
max_connections = 100
\# – Archiving –archive_command = ‘cp %p /usr/local/pgsql/data/archive_log/%’ # command to use to archive a logfile
pgpool:pgpool.conf
\# Host name or IP address to listen on: ‘‘ for all, ” for no TCP/IP
\# connections
listen_addresses = ‘‘\# Port number for pgpool
port = 9999\# Port number for pgpool communication manager
pcp_port = 9898\# Logging directory
logdir = ‘/var/log/pgpool’\# pid file name
pid_file_name = ‘/var/run/pgpool/pgpool.pid’\# Replication mode
replication_mode = true\# Load balancing mode, i.e., all SELECTs are load balanced.
load_balance_mode = true\# If there’s a disagreement with the packet kind sent from backend,
\# then degenrate the node which is most likely “minority”. If false,
\# just force to exit this session.
replication_stop_on_mismatch = true\# Health check timeout. 0 means no timeout.
health_check_timeout = 20\# Health check period. 0 means no health check.
health_check_period = 30\# Health check user
health_check_user = ‘nobody’\# If true, trigger fail over when writing to the backend communication
\# socket fails. This is the same behavior of pgpool-II 2.2.x or
\# earlier. If set to false, pgpool will report an error and disconnect
\# the session.
fail_over_on_backend_error = true\# If true, automatically locks a dummy row or a table with INSERT
\# statements to keep SERIAL data consistency. If the data does not have
\# SERIAL data type, no lock will be issued. An /INSERT LOCK/ comment
\# has the same effect. A /NO INSERT LOCK/ comment disables the effect.
insert_lock = true\# system DB info
system_db_hostname = ‘localhost’
system_db_port = 5432
system_db_dbname = ‘pgpool’
system_db_schema = ‘pgpool_catalog’
system_db_user = ‘pgpool’
system_db_password = ”\# backend_hostname, backend_port, backend_weight
\# here are examples
backend_hostname0 = ‘192.168.11.145’
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = ‘/var/lib/pgsql/data’
backend_hostname1 = ‘192.168.11.146’
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = ‘/var/lib/pgsql/data’\# – online recovery –
\# online recovery user
recovery_user = ‘postgres’\# online recovery password
recovery_password = ”\# execute a command in first stage.
recovery_1st_stage_command = ‘recovery_1st_stage.sh’\# execute a command in second stage.
recovery_2nd_stage_command = ‘recovery_2nd_stage.sh’\# maximum time in seconds to wait for the recovering node’s postmaster
\# start-up. 0 means no wait.
\# this is also used as a timer waiting for clients disconnected before
\# starting 2nd stage
recovery_timeout = 90
pgpool:pg_hba.conf
\# TYPE DATABASE USER CIDR-ADDRESS METHOD
\# “local” is for Unix domain socket connections only
local all all trust
\# IPv4 local connections:
host all all 127.0.0.1/32 trust
host all all 192.168.11.0/24 trust
pgpool:pcp.conf
\# USERID:MD5PASSWD
postgres:e8a48653851e28c69d0506508fb27fc5