keepalived + ホットスタンバイで障害時でもPostgreSQLを自動継続してみる 構築編

今回構築する環境は正常時は下記のようにプライマリーでサービスを
提供してホットスタンバイには接続をしないようにします。

障害時にVIPを自動で切り替え、ホットスタンバイをプライマリーに
昇格させてサービスを自動継続させます。


【環境】
プライマリー CentOS5.5 PostgreSQL9.0 IP:192.168.14.101/24
ホットスタンバイ CentOS5.5 PostgreSQL9.0 IP:192.168.14.102/24


【構築手順】
1.互いのサーバにpostgresユーザは鍵ファイルでSSHできるようにします。
下記URLの参考情報を参照
http://d.hatena.ne.jp/bose999/20100924/1285287421


2.PostgreSQLをホットスタンバイ状態で構築し、2台ともPostgreSQLを停止します。
下記URLの参考情報を参照
http://d.hatena.ne.jp/bose999/20100924/1285290937


※両サーバでの作業

# /etc/init.d/postgresql-9.0 stop


3.レプリケーションの設定をします。
3.1.ホットスタンバイのレプリケーションの準備をします。
※ホットスタンバイでの作業

# rm -rf /var/lib/pgsql/9.0/data
# mkdir /var/lib/pgsql/9.0/archive
# chown -R postgres:postgres /var/lib/pgsql/9.0/archive


3.2.プライマリーの設定を行い、ホットスタンバイへファイルコピーします。
※プライマリーでの作業

# vi /var/lib/pgsql/9.0/data/postgresql.conf
# vi /var/lib/pgsql/9.0/data/pg_hba.conf
# vi /home/postgres/rsync.sh
# chmod 755 /home/postgres/rsync.sh
# su - postgres
$ crontab -e
$ exit
logout
# scp -r /var/lib/pgsql/9.0/data 192.168.14.102:/var/lib/pgsql/9.0/


3.3.ホットスタンバイのレプリケーションの設定をします。
※ホットスタンバイでの作業

# vi /var/lib/pgsql/9.0/data/postgresql.conf
# vi /var/lib/pgsql/9.0/data/pg_hba.conf
# vi /var/lib/pgsql/9.0/data/recovery.conf
# chown -R postgres:postgres /var/lib/pgsql/9.0/data


◯プライマリーのファイルの内容
プライマリーのpostgresql.conf
デフォルトからの変更点のみ抜粋

listen_addresses = '*'
wal_level = hot_standby
archive_mode = on
archive_command = 'cp %p /var/lib/pgsql/9.0/archive/%f'
max_wal_senders = 5
wal_keep_segments = 100
hot_standby = on


プライマリーのpg_hba.conf

# TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD
local   all             all                                     md5
host    replication     postgres        192.168.14.102/32       md5
host    all             all             192.168.14.101/32       md5
host    all             all             192.168.11.0/24         md5


プライマリーのpostgresユーザのcrontab

*/3 * * * * /home/postgres/rsync.sh


プライマリーのcrontabに設定したシェルスクリプト
/home/postgres/rsync.sh

#!/bin/sh
#ホットスタンバイにtrigger_fileかrecovery.doneが存在しなければrsyncする
scp 192.168.14.102:/var/lib/pgsql/9.0/data/trigger_file /tmp/trigger_file
scp 192.168.14.102:/var/lib/pgsql/9.0/data/recovery.done /tmp/trigger_file
if [ ! -e /tmp/trigger_file ]; then
  rsync -az -e ssh /var/lib/pgsql/9.0/archive/ 192.168.14.102:/var/lib/pgsql/9.0/archive/
fi


◯ホットスタンバイのファイルの内容
ホットスタンバイのpostgresql.conf
デフォルトからの変更点のみ抜粋

listen_addresses = '*'
wal_level = hot_standby
archive_mode = on
archive_command = 'cp %p /var/lib/pgsql/9.0/archive/%f'
max_wal_senders = 5
wal_keep_segments = 100


ホットスタンバイのpg_hba.conf

# TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD
local   all             all                                     md5
host    replication     postgres        192.168.14.101/32       md5
host    all             all             192.168.14.102/32       md5
host    all             all             192.168.11.0/24         md5


ホットスタンバイのrecovery.conf

primary_conninfo = 'host=192.168.14.101 port=5432 user=postgres password=postgres'
standby_mode = 'on'
restore_command = 'cp /var/lib/pgsql/9.0/archive/%f %p'
trigger_file = '/var/lib/pgsql/9.0/data/trigger_file'


4.keepalivedのインストールと設定
4.1.プライマリーにkeepalivedRPMを作ってインストールし設定を行う。
※プライマリーでの作業

# cd $HOME
# yum -y install make kernel kernel-devel rpm-build openssl-devel
# wget http://www.keepalived.org/software/keepalived-1.1.20.tar.gz
# tar zxvf keepalived-1.1.20.tar.gz
# cd ./keepalived-1.1.20
# chown -R root:root /root/keepalived-1.1.20
# ./configure
# cp $HOME/keepalived-1.1.20.tar.gz /usr/src/redhat/SOURCES/
# rpmbuild -ba ./keepalived.spec
# cd /usr/src/redhat/RPMS/x86_64
# rpm -ivh ./keepalived-1.1.20-5.x86_64.rpm
# vi /etc/keepalived/keepalived.conf
# vi /home/postgres/kick_alive_chk.sh
# vi /home/postgres/aliv_chk.sh
# chown postgres:postgres /home/postgres/kick_alive_chk.sh
# chown postgres:postgres /home/postgres/alive_chk.sh
# chmod 755 /home/postgres/kick_alive_chk.sh
# chmod 755 /home/postgres/alive_chk.sh
# vi /etc/sysconfig/iptables
# /etc/init.d/iptables restart


4.2.ホットスタンバイにkeepalivedRPMを作ってインストールし設定を行う。
※ホットスタンバイでの作業

# cd $HOME
# yum -y install make kernel kernel-devel rpm-build openssl-devel
# wget http://www.keepalived.org/software/keepalived-1.1.20.tar.gz
# tar zxvf keepalived-1.1.20.tar.gz
# cd ./keepalived-1.1.20
# chown -R root:root $HOME/keepalived-1.1.20
# ./configure
# cp $HOME/keepalived-1.1.20.tar.gz /usr/src/redhat/SOURCES/
# rpmbuild -ba ./keepalived.spec
# cd /usr/src/redhat/RPMS/x86_64
# rpm -ivh ./keepalived-1.1.20-5.x86_64.rpm
# vi /etc/keepalived/keepalived.conf
# vi /home/postgres/change_primary.sh
# chown postgres:postgres /home/postgres/change_primary.sh
# chmod 755 /home/postgres/change_primary.sh
# vi /etc/sysconfig/iptables
# /etc/init.d/iptables restart


keepalivedのログについては下記参照。
http://d.hatena.ne.jp/bose999/20100912/1284258023


4.3.プライマリーでサービスの設定をし、起動する。
※プライマリーでの作業

# chkconfig --level 345 keepalived on
# chkconfig --list | grep keepalived
keepalived     	0:off	1:off	2:off	3:on	4:on	5:on	6:off
# /etc/init.d/postgresql-9.0 start
# /etc/init.d/keepalived start
 →必ずPostgreSQLを先に起動します。
 keepalivedの設定ファイルで指定したPostgreSQLの
 監視シェルが誤動作をしてしまうのを防ぐためです。


4.4.ホットスタンバイでサービスの設定をし、起動する。
※ホットスタンバイでの作業

# chkconfig --level 345 keepalived on
# chkconfig --list | grep keepalived
keepalived     	0:off	1:off	2:off	3:on	4:on	5:on	6:off
# /etc/init.d/postgresql-9.0 start
# /etc/init.d/keepalived start


◯プライマリーのファイルの内容
/etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
   notification_email {
   }
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 105
    priority 100
    advert_int 1
    virtual_ipaddress {
        192.168.14.100/24
    }
    notify_master "/home/postgres/kick_alive_chk.sh"
}


プライマリーサーバ用サービス継続チェックシェル起動シェル
kick_alive_chk.sh

#!/bin/sh

CHECK_SHELL=/home/postgres/alive_chk.sh

#チェック用シェルが起動されていたらkillする
CHEK_SHELL_PS=`ps -ef | grep $CHECK_SHELL | grep -v grep`
if [ -n "$CHEK_SHELL_PS" ] ; then
    for PID in `echo $CHEK_SHELL_PS | awk '{print $2}'` ; do
        echo "kill -9 $PID"
        /bin/kill -9 $PID
    done
fi

$CHECK_SHELL &
exit


プライマリーサーバ用サービス継続チェック用シェル
alive_chk.sh
keepalived起動時に起動させてPostgreSQLの異常停止時にkeepalivedを停止させる

#!/bin/sh

#監視開始直後のチェック無視時間
sleep 5

#PostgreSQL接続ユーザ
POSTGRESQL_USER=postgres

#PostgreSQL接続ユーザパスワード
POSTGRESQL_PASS=postgres

#PostgreSQL接続先(サービスを提供している仮想IP)
POSTGRESQL_IP=192.168.14.100

#STOPフラグ
STOP_FLAG=0

#STOPフラグしきい値
STOP_FLAG_LIMIT=5

while true ; do

    #監視インターバル
    sleep 5

    ALIVE_STRING=""
    ALIVE_STRING=`PGPASSWORD=$POSTGRESQL_PASS /usr/bin/psql -h $POSTGRESQL_IP -U $POSTGRESQL_USER -c "select 1;" | grep 1 | sed -e '$d'`

    if [ -z $ALIVE_STRING ]  ; then
         STOP_FLAG=`expr $STOP_FLAG + 1`
    else
         STOP_FLAG=0
    fi

    if [ "$STOP_FLAG" = "$STOP_FLAG_LIMIT" ] ; then
        echo "stop keepalived"
        /etc/rc.d/init.d/keepalived stop
        exit
    fi
done


◯ホットスタンバイのファイルの内容
/etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
   notification_email {
   }
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 105
    priority 100
    advert_int 1
    virtual_ipaddress {
        192.168.14.100/24
    }
    notify_master "/home/postgres/change_primary.sh"
}


ホットスタンバイ用IP切り替え後プライマリー化シェル
change_primary.sh

#!/bin/sh
touch /var/lib/pgsql/9.0/data/trigger_file


◯両方共通のファイルの内容
/etc/sysconfig/iptables
PostgreSQLvrrpを通過させないと行けない。

# Firewall configuration written by system-config-securitylevel
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p 50 -j ACCEPT
-A RH-Firewall-1-INPUT -p 51 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 5432 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A RH-Firewall-1-INPUT -p vrrp -m state --state NEW -j ACCEPT
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT


以上でkeepalivedによるVRRP監視とシェルによる
PostgreSQLの監視と切り替えが設定できました。


VRRPが伝播出来ない場合、
プライマリーのPostgreSQLSQLを発行できない場合に
keepalivedがホットスタンバイ側にIPを変更し、
トリガーファイルを設定してプライマリーを切替てくれます。


この仕組は必ず下記の事を守ってください。
keepalivedの誤動作を防ぐためにも下記の手順が必要です。
・サーバを落とす際はホットスタンバイを先にシャットダウンして
 プライマリーをシャットダウンして下さい。
・サーバを起動する際はプライマリーを起動した後に
 ホットスタンバイを起動して下さい。