作業系統:CentOS7
Postgresql版本:10.10
Pgpool-II版本:4.0.6
端口
9999:對外提供服務
9000:watch_dog
9898:pcp
9694:watch_dog心跳檢查
備注:下文的安裝步驟中,【】包圍的部分需根據自己的環境來配置
背景
項目上有實作資料庫高可用的需求,Postgresql本身支援資料同步和手動failover。即,一個雙機熱備的Postgresql叢集,主節點當機時,整個叢集隻能對外提供讀服務,而無法提供寫服務,隻有手動執行promote指令晉升備節點為主節點,才能恢複資料庫服務的正常。以下是Postgresql官方文檔的引文:
PostgreSQL does not provide the system software required to identify a
failure on the primary and notify the standby database server.
Pgpool通過其WatchDog的虛拟IP和健康檢查功能實作了自動故障切換。本文使用master-slave模式搭建叢集,不使用replication_mode的原因是該模式下的online recovery存在限制,Pgpool官網引文如下:
There is a restriction in the online recovery in replication_mode. If
Pgpool-II itself is installed on multiple hosts, online recovery does
not work correctly, because Pgpool-II has to stop all the clients
during the 2nd stage of online recovery. If there are several
Pgpool-II hosts, only one of them will have received the online
recovery command and will block the connections from clients.
為實作分區容錯,本文使用3個節點搭建叢集,每個節點安裝Pgpool-II和Postgresql資料庫,資料庫為1主2備。
注意:Pgpool-II和Postgresql叢集對于主節點使用的術語不同,Pgpool-II的主節點稱為Master,Postgresql的主節點稱為Primary;備節點使用的術語相同,都為standby。
步驟
1 安裝并配置PostgreSQL
在所有節點安裝PostgreSQL,但僅需要在節點1配置并啟動PostgreSQL,然後使用pcp_recovery_node功能初始化并啟動節點2、3上的Postgresql服務,注意不要讓PostgreSQL開機自啟。參考PG資料庫安裝。
2 配置/etc/hosts
增加DNS配置,供recovery_1st_stage使用
【節點1的IP】 【節點1的主機名】
【節點2的IP】 【節點2的主機名】
【節點3的IP】 【節點3的主機名】
3 配置ssh免密通信
Pgpool的failover配置中使用的failover.sh、follow_master.sh,以及online recovery配置中使用的recovery_1st_stage、pgpool_remote_start腳本中,都涉及通過ssh進行遠端操作。
需要配置root使用者到postgres使用者(包括本機的postgres使用者)的單向,以及postgres使用者之間的雙向免密通信。
3.1 設定postgres使用者的密碼
su
passwd postgres
3.2 在目前節點執行以下語句,生成密鑰
注意不要設定passphrase
su 【目前使用者】
ssh-keygen -t rsa
3.3 将公鑰發送到其他節點
ssh-copy-id -i ~/.ssh/id_rsa.pub 【使用者名】@【IP】
3.4 測試ssh
ssh 【使用者名】@【IP】
4 修改ssh配置(可選,預設10個一般夠)
vi /etc/ssh/sshd_config
修改
MaxSessions 100
重新開機sshd
systemctl restart sshd
5 配置系統日志
建立日志檔案,應建立在/var/log路徑下,否則syslog無法寫入檔案(除非關閉或配置SELinux)。
mkdir /var/log/pgpool
touch /var/log/pgpool/pgpool_run.log
修改syslog配置
vi /etc/rsyslog.conf
修改
*.info;mail.none;authpriv.none;cron.none;LOCAL1.none /var/log/messages
LOCAL1.* /var/log/pgpool/pgpool_run.log
重新開機
systemctl restart rsyslog
6 配置pgpass
為了允許資料庫的postgres使用者無需為流複制和線上恢複指定密碼,對于每個節點,在作業系統的postgres使用者的主目錄中建立.pgpass檔案,權限改為600。
su postgres
vi ~/.pgpass
編輯
# hostname:port:database:username:password
# In a standby server, a database field of replication matches streaming replication connections made to the master server.
【節點1的IP】:5432:postgres:postgres:123456
【節點2的IP】:5432:postgres:postgres:123456
【節點3的IP】:5432:postgres:postgres:123456
授權
chmod 600 ~/.pgpass
7 安裝Pgpool
root使用者執行,在所有節點安裝和配置Pgpool;為了使用線上恢複功能,需要pgpool_recovery、pgpool_remote_start、pgpool_switch_xlog等函數,是以需要安裝pgpool_recovery。
注意:安裝pgpool_recovery需要先安裝postgresql-devel。
mkdir /usr/local/pgpool
cd /usr/local/pgpool
tar -zxvf pgpool-II-4.0.6.tar.gz
cd /usr/local/pgpool/pgpool-II-4.0.6
./configure --with-pgsql=/usr/local/pgsql
make && make install
cd /usr/local/pgpool/pgpool-II-4.0.6/src/sql/pgpool-recovery
chown -R postgres /usr/local/pgsql
make && make install
cp /usr/local/etc/pgpool.conf.sample-stream /usr/local/etc/pgpool.conf
8 在節點1的Postgresql上安裝pgpool_recovery擴充
使用PG建立資料庫時,實際上是通過複制一個現有的資料庫來工作的。預設情況下,它複制名為template1的标準系統資料庫。
psql template1 -c "CREATE EXTENSION pgpool_recovery"
psql postgres -c "CREATE EXTENSION pgpool_recovery"
9 編寫failover腳本
在所有節點上建立配置檔案,并賦予執行權限
vi /usr/local/pgpool/failover_stream.sh
編輯腳本(注意和pgpool.conf中failover_command參數的聯系),如果primary當機,晉升standby;如果standby當機,僅記錄日志。
#!/bin/bash
# This script is run by failover_command.
set -o xtrace
logger -i -p local1.info failover_command begin
# Special values:
# %d = node id
# %h = host name
# %p = port number
# %D = database cluster path
# %m = new master node id
# %H = hostname of the new master node
# %M = old master node id
# %P = old primary node id
# %r = new master port number
# %R = new master database cluster path
# %% = '%' character
FAILED_NODE_ID="$1"
FAILED_NODE_HOST="$2"
FAILED_NODE_PORT="$3"
FAILED_NODE_PGDATA="$4"
NEW_MASTER_NODE_ID="$5"
NEW_MASTER_NODE_HOST="$6"
OLD_MASTER_NODE_ID="$7"
OLD_PRIMARY_NODE_ID="$8"
NEW_MASTER_NODE_PORT="$9"
NEW_MASTER_NODE_PGDATA="${10}"
PGHOME=/usr/local/pgsql
logger -i -p local1.info failover.sh: start: failed_node_id=${FAILED_NODE_ID} old_primary_node_id=${OLD_PRIMARY_NODE_ID} \
failed_host=${FAILED_NODE_HOST} new_master_host=${NEW_MASTER_NODE_HOST}
## Test passwrodless SSH
ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected]${NEW_MASTER_NODE_HOST} -i ~/.ssh/id_rsa ls /tmp > /dev/null
if [ $? -ne 0 ]; then
logger -i -p local1.error failover.sh: passwrodless SSH to [email protected]${NEW_MASTER_NODE_HOST} failed. Please setup passwrodless SSH.
exit 1
fi
# If standby node is down, skip failover.
if [ ${FAILED_NODE_ID} -ne ${OLD_PRIMARY_NODE_ID} ]; then
logger -i -p local1.info failover.sh: Standby node is down. Skipping failover.
exit 0
fi
# Promote standby node.
logger -i -p local1.info failover.sh: Primary node is down, promote standby node [email protected]${NEW_MASTER_NODE_HOST}.
ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
[email protected]${NEW_MASTER_NODE_HOST} -i ~/.ssh/id_rsa ${PGHOME}/bin/pg_ctl -D ${NEW_MASTER_NODE_PGDATA} -w promote
if [ $? -ne 0 ]; then
logger -i -p local1.error failover.sh: new_master_host=${NEW_MASTER_NODE_HOST} promote failed
exit 1
fi
logger -i -p local1.info failover.sh: end: new_master_node_id=$NEW_MASTER_NODE_ID started as the primary node
exit 0
授權
chmod +x /usr/local/pgpool/failover_stream.sh
10 編寫follow_master腳本
使仍在運作的standby從新的primary上同步資料,三個及以上節點數量時,需要設定此腳本
vi /usr/local/pgpool/follow_master.sh
編輯腳本
#!/bin/bash
# This script is run after failover_command to synchronize the Standby with the new Primary.
set -o xtrace
logger -i -p local1.info follow_master begin
# special values: %d = node id
# %h = host name
# %p = port number
# %D = database cluster path
# %m = new master node id
# %M = old master node id
# %H = new master node host name
# %P = old primary node id
# %R = new master database cluster path
# %r = new master port number
# %% = '%' character
FAILED_NODE_ID="$1"
FAILED_NODE_HOST="$2"
FAILED_NODE_PORT="$3"
FAILED_NODE_PGDATA="$4"
NEW_MASTER_NODE_ID="$5"
NEW_MASTER_NODE_HOST="$6"
OLD_MASTER_NODE_ID="$7"
OLD_PRIMARY_NODE_ID="$8"
NEW_MASTER_NODE_PORT="$9"
NEW_MASTER_NODE_PGDATA="${10}"
PGHOME=/usr/local/pgsql
ARCHIVEDIR=/home/pg/data/archivedir
REPL_USER=postgres
PCP_USER=postgres
PGPOOL_PATH=/usr/local/bin
PCP_PORT=9898
# Recovery the slave from the new primary
logger -i -p local1.info follow_master.sh: start: synchronize the Standby node [email protected]${FAILED_NODE_HOST} with the new Primary node [email protected]${NEW_MASTER_NODE_HOST}
## Test passwrodless SSH
ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected]${NEW_MASTER_NODE_HOST} -i ~/.ssh/id_rsa ls /tmp > /dev/null
if [ $? -ne 0 ]; then
logger -i -p local1.error follow_master.sh: passwrodless SSH to postgr[email protected]${NEW_MASTER_NODE_HOST} failed. Please setup passwrodless SSH.
exit 1
fi
## Get PostgreSQL major version
PGVERSION=`${PGHOME}/bin/initdb -V | awk '{print $3}' | sed 's/\..*//' | sed 's/\([0-9]*\)[a-zA-Z].*/\1/'`
if [ ${PGVERSION} -ge 12 ]; then
RECOVERYCONF=${FAILED_NODE_PGDATA}/myrecovery.conf
else
RECOVERYCONF=${FAILED_NODE_PGDATA}/recovery.conf
fi
# Check the status of standby
ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
[email protected]${FAILED_NODE_HOST} -i ~/.ssh/id_rsa ${PGHOME}/bin/pg_ctl -w -D ${FAILED_NODE_PGDATA} status
## If Standby is running, run pg_basebackup.
if [ $? -eq 0 ]; then
# Execute pg_basebackup
ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected]${FAILED_NODE_HOST} -i ~/.ssh/id_rsa "
set -o errexit
${PGHOME}/bin/pg_ctl -w -m f -D ${FAILED_NODE_PGDATA} stop
rm -rf ${FAILED_NODE_PGDATA}
rm -rf ${ARCHIVEDIR}/*
${PGHOME}/bin/pg_basebackup -h ${NEW_MASTER_NODE_HOST} -U ${REPL_USER} -p ${NEW_MASTER_NODE_PORT} -D ${FAILED_NODE_PGDATA} -X stream
if [ ${PGVERSION} -ge 12 ]; then
sed -i -e \"\\\$ainclude_if_exists = '$(echo ${RECOVERYCONF} | sed -e 's/\//\\\//g')'\" \
-e \"/^include_if_exists = '$(echo ${RECOVERYCONF} | sed -e 's/\//\\\//g')'/d\" ${FAILED_NODE_PGDATA}/postgresql.conf
fi
cat > ${RECOVERYCONF} << EOT
primary_conninfo = 'host=${NEW_MASTER_NODE_HOST} port=${NEW_MASTER_NODE_PORT} user=${REPL_USER} passfile=''/home/postgres/.pgpass'''
recovery_target_timeline = 'latest'
restore_command = 'scp ${NEW_MASTER_NODE_HOST}:${ARCHIVEDIR}/%f %p'
EOT
if [ ${PGVERSION} -ge 12 ]; then
touch ${FAILED_NODE_PGDATA}/standby.signal
else
echo \"standby_mode = 'on'\" >> ${RECOVERYCONF}
fi
"
if [ $? -ne 0 ]; then
logger -i -p local1.error follow_master.sh: end: pg_basebackup failed
exit 1
fi
# start Standby node on ${FAILED_NODE_HOST}
ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
[email protected]${FAILED_NODE_HOST} -i ~/.ssh/id_rsa $PGHOME/bin/pg_ctl -l /dev/null -w -D ${FAILED_NODE_PGDATA} start
# If start Standby successfully, attach this node
if [ $? -eq 0 ]; then
# Run pcp_attact_node to attach Standby node to Pgpool-II.
${PGPOOL_PATH}/pcp_attach_node -w -h localhost -U $PCP_USER -p ${PCP_PORT} -n ${FAILED_NODE_ID}
if [ $? -ne 0 ]; then
logger -i -p local1.error follow_master.sh: end: pcp_attach_node failed
exit 1
fi
# If start Standby failed, drop replication slot "${FAILED_NODE_HOST}"
else
logger -i -p local1.error follow_master.sh: end: follow master command failed
exit 1
fi
else
logger -i -p local1.info follow_master.sh: failed_nod_id=${FAILED_NODE_ID} is not running. skipping follow master command
exit 0
fi
logger -i -p local1.info follow_master.sh: end: follow master command complete
exit 0
授權
chmod +x /usr/local/pgpool/follow_master.sh
11 編寫recovery_1st_stage腳本
pcp_recovery_node會用到recovery_1st_stage和pgpool_remote_start。
recovery_1st_stage會使用pg_basebackup從現存的主節點同步資料,初始化資料庫,更新recovery配置檔案。
vi /home/pg/data/recovery_1st_stage.sh
編輯
#!/bin/bash
# This script is executed by "recovery_1st_stage" to recovery a Standby node.
set -o xtrace
logger -i -p local1.info recovery_1st_stage begin
PRIMARY_NODE_PGDATA="$1"
DEST_NODE_HOST="$2"
DEST_NODE_PGDATA="$3"
PRIMARY_NODE_PORT="$4"
DEST_NODE_PORT=5432
# 這裡是hostname變量,是以需要配置DNS
PRIMARY_NODE_HOST=$(hostname)
PGHOME=/usr/local/pgsql
ARCHIVEDIR=/home/pg/data/archivedir
REPL_USER=postgres
logger -i -p local1.info recovery_1st_stage: start: pg_basebackup for Standby node [email protected]{$DEST_NODE_HOST}
## Test passwrodless SSH
ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected]${DEST_NODE_HOST} -i ~/.ssh/id_rsa ls /tmp > /dev/null
if [ $? -ne 0 ]; then
logger -i -p local1.error recovery_1st_stage: passwrodless SSH to [email protected]${DEST_NODE_HOST} failed. Please setup passwrodless SSH.
exit 1
fi
## Get PostgreSQL major version
PGVERSION=`${PGHOME}/bin/initdb -V | awk '{print $3}' | sed 's/\..*//' | sed 's/\([0-9]*\)[a-zA-Z].*/\1/'`
if [ $PGVERSION -ge 12 ]; then
RECOVERYCONF=${DEST_NODE_PGDATA}/myrecovery.conf
else
RECOVERYCONF=${DEST_NODE_PGDATA}/recovery.conf
fi
## Execute pg_basebackup to recovery Standby node
ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected]$DEST_NODE_HOST -i ~/.ssh/id_rsa "
set -o errexit
rm -rf $DEST_NODE_PGDATA
rm -rf $ARCHIVEDIR/*
${PGHOME}/bin/pg_basebackup -h ${PRIMARY_NODE_HOST} -U ${REPL_USER} -p ${PRIMARY_NODE_PORT} -D ${DEST_NODE_PGDATA} -X stream
if [ ${PGVERSION} -ge 12 ]; then
sed -i -e \"\\\$ainclude_if_exists = '$(echo ${RECOVERYCONF} | sed -e 's/\//\\\//g')'\" \
-e \"/^include_if_exists = '$(echo ${RECOVERYCONF} | sed -e 's/\//\\\//g')'/d\" ${DEST_NODE_PGDATA}/postgresql.conf
fi
cat > ${RECOVERYCONF} << EOT
primary_conninfo = 'host=${PRIMARY_NODE_HOST} port=${PRIMARY_NODE_PORT} user=${REPL_USER} passfile=''/home/postgres/.pgpass'''
recovery_target_timeline = 'latest'
restore_command = 'scp ${PRIMARY_NODE_HOST}:${ARCHIVEDIR}/%f %p'
EOT
if [ ${PGVERSION} -ge 12 ]; then
touch ${DEST_NODE_PGDATA}/standby.signal
else
echo \"standby_mode = 'on'\" >> ${RECOVERYCONF}
fi
sed -i \"s/#*port = .*/port = ${DEST_NODE_PORT}/\" ${DEST_NODE_PGDATA}/postgresql.conf
"
if [ $? -ne 0 ]; then
logger -i -p local1.error recovery_1st_stage: end: pg_basebackup failed. online recovery failed
exit 1
fi
logger -i -p local1.info recovery_1st_stage: end: recovery_1st_stage complete
exit 0
授權
chmod +x /home/pg/data/recovery_1st_stage.sh
12 編寫pgpool_remote_start腳本(注意沒有sh擴充名)
pgpool_remote_start負責啟動資料庫
vi /home/pg/data/pgpool_remote_start
編輯
#!/bin/bash
# This script is run after recovery_1st_stage to start Standby node.
set -o xtrace
logger -i -p local1.info pgpool_remote_start begin
PGHOME=/usr/local/pgsql
DEST_NODE_HOST="$1"
DEST_NODE_PGDATA="$2"
logger -i -p local1.info pgpool_remote_start: start: remote start Standby node [email protected]$DEST_NODE_HOST
## Test passwrodless SSH
ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected]${DEST_NODE_HOST} -i ~/.ssh/id_rsa ls /tmp > /dev/null
if [ $? -ne 0 ]; then
logger -i -p local1.error pgpool_remote_start: passwrodless SSH to [email protected]${DEST_NODE_HOST} failed. Please setup passwrodless SSH.
exit 1
fi
## Start Standby node
ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected]$DEST_NODE_HOST -i ~/.ssh/id_rsa "
$PGHOME/bin/pg_ctl -l /dev/null -w -D $DEST_NODE_PGDATA start
"
if [ $? -ne 0 ]; then
logger -i -p local1.error pgpool_remote_start: [email protected]$DEST_NODE_HOST start failed.
exit 1
fi
logger -i -p local1.info pgpool_remote_start: end: [email protected]$DEST_NODE_HOST started successfully.
exit 0
授權
chmod +x /home/pg/data/pgpool_remote_start.sh
13 配置pgpool.conf
複制Pgpool配置模闆檔案
cp /usr/local/etc/pgpool.conf.sample-stream /usr/local/etc/pgpool.conf
vi /usr/local/etc/pgpool.conf
修改
#CONNECTIONS
listen_addresses = '*'
port = 9999
pcp_listen_addresses = '*'
pcp_port = 9898
#- Backend Connection Settings -
backend_hostname0 ='【叢集内第1個節點的IP,多個節點配置一緻】'
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/home/pg/data'
backend_flag0 = ‘ALLOW_TO_FAILOVER’
backend_hostname1 ='【叢集内第2個節點的IP,多個節點配置一緻】'
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/home/pg/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'
backend_hostname2 ='【叢集内第3個節點的IP,多個節點配置一緻】'
backend_port2 = 5432
backend_weight2 = 1
backend_data_directory2 = '/home/pg/data'
backend_flag2 = 'ALLOW_TO_FAILOVER'
#- Authentication -
enable_pool_hba = on
pool_passwd ='pool_passwd'
#------------------------------------------------------------------------------
# POOLS
#------------------------------------------------------------------------------
# - Concurrent session and pool size -
num_init_children = 400
max_pool = 4
#------------------------------------------------------------------------------
# LOGS
#------------------------------------------------------------------------------
log_destination = 'syslog'
syslog_facility = 'LOCAL1'
#------------------------------------------------------------------------------
# FILE LOCATIONS
#------------------------------------------------------------------------------
pid_file_name = '/usr/local/pgpool/pgpool.pid'
#------------------------------------------------------------------------------
# REPLICATION MODE
#------------------------------------------------------------------------------
replication_mode = off
#------------------------------------------------------------------------------
# LOAD BALANCING MODE
#------------------------------------------------------------------------------
load_balance_mode = on
#------------------------------------------------------------------------------
# MASTER/SLAVE MODE
#------------------------------------------------------------------------------
master_slave_mode = on
master_slave_sub_mode = 'stream'
# - Streaming -
sr_check_period = 5
sr_check_user = 'postgres'
sr_check_password ='123456'
sr_check_database = 'postgres'
follow_master_command = '/usr/local/pgpool/follow_master.sh %d %h %p %D %m %H %M %P %r %R'
#------------------------------------------------------------------------------
#HEALTH CHECK
#------------------------------------------------------------------------------
health_check_period = 10
health_check_timeout = 20
health_check_user = 'postgres'
health_check_password ='123456'
health_check_database = 'postgres'
#------------------------------------------------------------------------------
#FAILOVER AND FAILBACK
#------------------------------------------------------------------------------
# 注意failover_stream.sh後的參數,要與failover_stream.sh中的腳本比對
failover_command = '/usr/local/pgpool/failover_stream.sh %d %h %p %D %m %H %M %P %r %R'
#------------------------------------------------------------------------------
#WATCHDOG
#------------------------------------------------------------------------------
use_watchdog = on
wd_hostname = '【本機IP】'
wd_port = 9000
delegate_IP = '【虛拟IP】'
if_cmd_path = '/sbin'
if_up_cmd = 'ip addr add $_IP_$/24 dev 【網卡名稱(通過ip addr檢視)】 label 【網卡名稱(通過ip addr檢視)】:0'
if_down_cmd = 'ip addr del $_IP_$/24 dev 【網卡名稱(通過ip addr檢視)】'
arping_path = '/usr/sbin'
arping_cmd = 'arping -U $_IP_$ -w 1'
wd_heartbeat_port = 9694
wd_heartbeat_keepalive = 2
wd_heartbeat_deadtime = 30
heartbeat_destination0 = '【其他節點1的IP】'
heartbeat_destination_port0 = 9694
heartbeat_device0 = '【網卡名稱(通過ip addr檢視)】'
heartbeat_destination1 = '【其他節點2的IP】'
heartbeat_destination_port1 = 9694
heartbeat_device1 = '【網卡名稱(通過ip addr檢視)】'
#------------------------------------------------------------------------------
# ONLINE RECOVERY
#------------------------------------------------------------------------------
recovery_user = 'postgres'
recovery_password = '123456'
recovery_1st_stage_command = 'recovery_1st_stage.sh'
#- Other pgpool Connection Settings -
other_pgpool_hostname0 ='【其他節點1的IP】'
other_pgpool_port0 = 9999
other_wd_port0 = 9000
other_pgpool_hostname1 ='【其他節點2的IP】'
other_pgpool_port1 = 9999
other_wd_port1 = 9000
14 生成pool_passwd
/usr/local/bin/pg_md5 -p --md5auth --username=postgres pool_passwd
chown postgres:postgres /usr/local/etc/pool_passwd
操作完成後,在/usr/local/etc目錄下會生成一個pool_passwd檔案,該檔案在pgpool.conf中通過“pool_passwd”選項配置。
15 配置pool_hba.conf
用戶端認證配置檔案,在pgpool.conf中配置“enable_pool_hba = on”時,将使用該檔案認證用戶端連接配接。
root使用者執行
cp /usr/local/etc/pool_hba.conf.sample /usr/local/etc/pool_hba.conf
chown postgres:postgres /usr/local/etc/pool_hba.conf
vi /usr/local/etc/pool_hba.conf
修改
local all all md5
host all all 0.0.0.0/0 md5
host all all 0/0 md5
16 配置pcp.conf
Pgpool-II為管理者提供了執行管理操作的接口,例如擷取Pgpool-II狀态或遠端終止Pgpool-II程序。pcp.conf是此接口用于身份驗證的使用者名/密碼檔案。所有操作模式都需要設定pcp.conf檔案。資料庫中使用PCP進行健康檢測和複制延遲檢測的使用者,其使用者名和密碼必須在pcp.conf中聲明。
16.1 生成密碼摘要
/usr/local/bin/pg_md5 【密碼】
16.2 生成和配置檔案
cp /usr/local/etc/pcp.conf.sample /usr/local/etc/pcp.conf
vi /usr/local/etc/pcp.conf
編輯
# Example:
postgres:【上一步生成的密碼摘要】
17 設定PCP密碼配置檔案
由于follow_master_command腳本必須在不輸入密碼的情況下執行PCP指令,是以我們在Pgpool-II啟動使用者的主目錄中建立.pcppass。
echo 'localhost:9898:【資料庫使用者名稱】:【資料庫使用者密碼】' > ~/.pcppass
chmod 600 ~/.pcppass
18 允許postgres使用者以root身份執行相關指令
root使用者執行
chmod u+s /sbin/ip
chmod u+s /sbin/arping
19 配置開機自啟
vi /etc/systemd/system/pgpool.service
編輯
[Unit]
Description=Pgpool-II
After=syslog.target network.target
[Service]
Type=forking
User=root
ExecStart=/usr/local/bin/pgpool -C -D
ExecStop=/usr/local/bin/pgpool -m fast stop
ExecReload=/usr/local/bin/pgpool reload
LimitNOFILE=65536
KillMode=process
KillSignal=SIGINT
Restart=on-abnormal
RestartSec=30s
TimeoutSec=0
[Install]
WantedBy=multi-user.target
開機自啟
systemctl enable pgpool
20 在所有節點啟動pgpool
systemctl start pgpool
21 通過pcp_recovery_node初始化備節點資料庫
pcp_recovery_node會先在primary節點執行SELECT pgpool_recovery(‘recovery_1st_stage’, ‘【需要啟動的standby的IP】’, ‘【資料目錄】’, ‘5432’, 【節點編号】),可以通過查詢PG日志檢視異常資訊;然後執行recovery_1st_stage.sh和pgpool_remote_start.sh
pcp_recovery_node -h 【主節點的IP】 -p 9898 -U 【PCP使用者名(資料庫)】 -n 【node-id】
22 檢視節點狀态
22.1 Pgpool節點狀态
pcp_watchdog_info -h 【虛拟IP】 -p 9898 -U 【Pgpool使用者】
22.2 資料庫節點狀态
通過虛拟IP的9999端口開啟PostgreSQL資料庫指令行,執行
注意:如果使用navicat的指令行功能,可能需要關閉并重新開機指令行界面(建立新的session)才能看到正确的節點狀态
23 高可用測試
23.1 Pgpool 高可用測試
- master停止pgpool服務,某個standby接管master服務
- 重新開機之前停止的master的pgpool服務,節點狀态變為standby
- standby停止pgpool服務,節點狀态變為shutdown
- 重新開機standby,節點狀态恢複為standby
23.2 資料庫高可用測試
-
primary停止資料庫服務,某個standby晉升為primary,其他standby執行follow
master,從新的primary同步資料
- 執行pcp_recovery_node,将之前停止服務的primary重新開機
- standby停止資料庫服務,其他節點無變化
- 執行pcp_recovery_node,将之前停止服務的standby重新開機
24 負載均衡測試
使用pgbench進行負載均衡測試
24.1 資料初始化
pgbench -i -h 【主節點IP】 -p 5432 postgres
24.2 測試
```shell
pgbench -c 【用戶端數量】 -T 【持續時間(秒)】 -h 【叢集虛拟IP】 postgres -p 9999 -U postgres -S(表示隻讀測試)
24.3 使用show pool_nodes檢視查詢請求在各節點的負載
25 非正常關閉pgpool後的故障恢複
- 非正常關閉pgpool,要清理緩存檔案:
rm /tmp/.s.PGSQL.9999
rm /tmp/.s.PGPOOLWD_CMD.9000
rm /tmp/.s.PGSQL.9898
-
如果啟動第一個節點狀态為standby,重新開機pgpool并使用
pcp_attach_node加入該節點