openGauss+KeepAlived
實驗環境
作業系統: CentOS 7.6
資料庫版本: openGauss 1.1.0Primary
主機/IP: opengaussdb1/...1 (openGauss 主備已部署完畢)
Standby 主機/IP: opengaussdb2/...2 (openGauss 主備已部署完畢)
說明:
不建議在雲環境(如:華為雲)下搭建 Keepalived 進行測試,本人在雲環境下測試發現,Keepalived 的 VIP 無法在雲環境下與其他主機通訊,雲環境下如何使用該 VIP 建議諮詢雲服務廠商。在踩坑之後,選擇使用本地的 VMWare workstation 進行簡單測試。
安裝 KeepAlived 軟體
在所有節點執行安裝
yum install keepalived -y
配置 keepalived
說明:
採用 nopreempt 不搶佔 VIP,主備節點的 state 均設定為 BACKUP。
主節點配置檔案。
vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived
全域性定義
global_defs {
router_id Keepalived_openGauss #執行 keepalived 伺服器的一個標識
script_user root #執行指令碼的使用者
}
VRRP例項定義
通常如果master服務Down掉後backup會變成master,但是當master服務又好了的時候 master此時會搶佔VIP,這樣就會發生兩次資料庫切換。
建議使用nopreempt引數設定為非搶佔模式,此時主庫從故障中恢復後,不會從新的主庫搶回VIP,但這需要將master和backup的state都設定成backup。
vrrp_instance VI_1 {
state BACKUP #指定Keepalived的角色(BACKUP需大寫)
interface eth0 #指定 HA 監測的網路介面
virtual_router_id 59 #虛擬路由的數字標識,同一個 vrrp_instance 下,MASTER 和 BACKUP 一致
nopreempt #非搶佔模式,主庫從故障中恢復後,不會從新的主庫搶回VIP
priority 100 #優先順序,備節點需要適當降低優先順序
advert_int 1 #MASTER 和 BACKUP 負載均衡器同步檢查的時間間隔(秒)
authentication { #設定驗證碼和驗證型別
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { #設定虛擬 IP 地址,可以設定多個,每個一行
...0
}
}
虛擬伺服器定義
virtual_server ...0 26000 { #設定虛擬伺服器的 IP 和埠,用空格隔開
delay_loop 6 #設定執行情況檢查時間,單位是秒
lb_algo rr #負載排程演算法(輪詢)
lb_kind DR #負載均衡機制(NAT、TUN、DR)
persistence_timeout 50 #會話保持時間(秒)
protocol TCP #轉發協議型別
real_server ...1 26000 { #配置服務節點
weight 100 #配置服務節點的權重
notify_down /gauss/failoverdb.sh #故障響應指令碼
TCP_CHECK { #使用TCP_CHECK方式進行健康檢查
connect_timeout 10 #10秒無響應即超時
delay_before_retry 3 #重試間隔時間
}
}
}
主節點故障切換指令碼(僅適用 openGauss 程序崩潰故障處理,不適用 Primary 作業系統當機故障處理)。
vi /gauss/failoverdb.sh
!/bin/bash
echo "Start to failover openGauss database."
pkill keepalived
ssh ...2 "su - omm -c 'gs_ctl failover -D /gauss/data/db1'"
ssh ...2 "su - omm -c 'gs_om -t refreshconf'"
echo 'Failover operation is completed.'
chmod 764 /gauss/failoverdb.sh
備節點配置檔案。
vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived
全域性定義
global_defs {
router_id Keepalived_openGauss #執行 keepalived 伺服器的一個標識
script_user root #執行指令碼的使用者
}
VRRP例項定義
通常如果master服務Down掉後backup會變成master,但是當master服務又好了的時候 master此時會搶佔VIP,這樣就會發生兩次資料庫切換。
建議使用nopreempt引數設定為非搶佔模式,此時主庫從故障中恢復後,不會從新的主庫搶回VIP,但這需要將master和backup的state都設定成backup。
vrrp_instance VI_1 {
state BACKUP #指定Keepalived的角色(BACKUP需大寫)
interface eth0 #指定 HA 監測的網路介面
virtual_router_id 59 #虛擬路由的數字標識,同一個 vrrp_instance 下,MASTER 和 BACKUP 一致
nopreempt #非搶佔模式,主庫從故障中恢復後,不會從新的主庫搶回VIP
priority 60 #優先順序,備節點需要適當降低優先順序
advert_int 1 #MASTER 和 BACKUP 負載均衡器同步檢查的時間間隔(秒)
authentication { #設定驗證碼和驗證型別
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { #設定虛擬 IP 地址,可以設定多個,每個一行
...0
}
}
虛擬伺服器定義
virtual_server ...0 26000 { #設定虛擬伺服器的 IP 和埠,用空格隔開
delay_loop 6 #設定執行情況檢查時間,單位是秒
lb_algo rr #負載排程演算法(輪詢)
lb_kind DR #負載均衡機制(NAT、TUN、DR)
persistence_timeout 50 #會話保持時間(秒)
protocol TCP #轉發協議型別
real_server ...2 26000 { #配置服務節點
weight 60 #配置服務節點的權重
notify_down /gauss/failoverdb.sh #虛擬服務故障響應指令碼
MISC_CHECK { ## 使用 MISC_CHECK 方式自定義指令碼做健康檢查
misc_path "/gauss/check.sh" ## 檢測指令碼
misc_timeout 10 ## 執行指令碼的超時時間
misc_dynamic ## 根據退出狀態碼動態調整伺服器的權重
}
}
}
備節點選擇MISC_CHECK方式的原因:
測試發現,當主節點直接斷電當機後,Keepalived的VIP會漂移至備節點,此時如果使用TCP_CHECK方式做健康檢查,會因為備機可讀的原因使得VIP:26000連線正常,造成keepalived健康檢查的誤判。
最終導致主節點斷電當機後,備節點雖獲取了VIP,但並沒有執行openGauss的failover操作,備節點依舊只讀,無法對外提供業務。
為了糾正這一點,建議使用MISC_CHECK方式自定義指令碼,登入主節點做資料庫健康檢查(簡單示例指令碼:/gauss/check.sh)
備節點健康檢查指令碼[ ssh 登入主節點進行資料庫連線檢查 ]。
vi /gauss/check.sh
ssh ...1 "su - omm -c "gsql -d postgres -p 26000 -t -A -c 'select 1;'""
備節點故障切換指令碼。
vi /gauss/failoverdb.sh
!/bin/bash
echo "Start to failover openGauss database."
pkill keepalived
su - omm -c "gs_ctl failover -D /gauss/data/db1"
su - omm -c "gs_om -t refreshconf"
echo 'Failover operation is completed.'
chmod 764 /gauss/failoverdb.sh
openGauss 配置
修改 openGauss 偵聽地址。
$ gs_guc set -I all -N all -c "listen_addresses = '...'"
$ gs_guc set -I all -N all -c "local_bind_address = '...'"
修改所有節點 replconninfo 引數(避免埠衝突)。
$ vi /gauss/data/db1/postgresql.conf
修改:localport --> 26011
修改:remoteport --> 26011
重啟 openGauss 資料庫,並檢查伺服器狀態。
重啟openGauss
[omm@prod db1]$ gs_om -t stop && gs_om -t start
檢查openGauss狀態
[root@opengaussdb1 ~]# su - omm -c "gs_om -t status --detail"
[ Cluster State ]
cluster_state : Normal
redistributing : No
current_az : AZ_ALL
[ Datanode State ]
node node_ip instance state |
---|
1 opengaussdb1 ...1 6001 /gauss/data/db1 P Primary Normal |
2 opengaussdb2 ...2 6002 /gauss/data/db1 S Standby Normal |
檢查KeepAlived程序狀態
[omm@opengaussdb1 ~]$ ps -ef|grep keep|grep -v grep
root 15664 1 0 16:15 ? 00:00:00 /usr/sbin/keepalived -D
root 15665 15664 0 16:15 ? 00:00:00 /usr/sbin/keepalived -D
root 15666 15664 0 16:15 ? 00:00:00 /usr/sbin/keepalived -D
檢查VIP狀態
[root@opengaussdb1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet .../8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:da:60:c0 brd ff:ff:ff:ff:ff:ff
inet ...1/24 brd ... scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet ...0/32 scope global ens33 ## VIP:...0
valid_lft forever preferred_lft forever
inet6 2408:8270:237:ded0:c89c:adab:e7b:8bd6/64 scope global noprefixroute dynamic
valid_lft 258806sec preferred_lft 172406sec
inet6 fe80::c4f2:8ad1:200d:ce9b/64 scope link noprefixroute
valid_lft forever preferred_lft forever
故障模擬測試
主節點[...1]操作。
kill資料庫程序
[root@opengaussdb1 ~]# ps -ef|grep gauss
omm 18115 1 4 16:30 ? 00:00:35 /gauss/app/bin/gaussdb -D /gauss/data/db1 -M primary
root 19254 9299 0 16:42 pts/0 00:00:00 grep --color=auto gauss
[root@opengaussdb1 ~]# kill -9 18115
檢查message日誌[檢測到故障,執行notify_down指令碼,並關閉keepalived服務]
tail -fn 200 /var/log/messages
Feb 19 16:42:57 opengaussdb1 Keepalived_healthcheckers[18816]: TCP connection to [...1]:26000 failed.
Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: TCP connection to [...1]:26000 failed.
Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: Check on service [...1]:26000 failed after 1 retry.
Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: Removing service [...1]:26000 from VS [...0]:26000
Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: IPVS (cmd 1160, errno 2): No such destination
Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: Executing [/gauss/failoverdb.sh] for service [...1]:26000 in VS [...0]:26000
Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: Lost quorum 1-0=1 > 0 for VS [...0]:26000
Feb 19 16:43:00 opengaussdb1 Keepalived[18815]: Stopping
Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: pid 19258 exited due to signal 15
Feb 19 16:43:00 opengaussdb1 Keepalived_vrrp[18817]: VRRP_Instance(VI_1) sent 0 priority
Feb 19 16:43:00 opengaussdb1 Keepalived_vrrp[18817]: VRRP_Instance(VI_1) removing protocol VIPs.
Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: IPVS (cmd 1156, errno 2): No such file or directory
Feb 19 16:43:00 opengaussdb1 Keepalived_healthcheckers[18816]: Stopped
Feb 19 16:43:01 opengaussdb1 Keepalived_vrrp[18817]: Stopped
Feb 19 16:43:01 opengaussdb1 Keepalived[18815]: Stopped Keepalived v1.3.5 (03/19,2017), git commit v1.3.5-6-g6fa32f2
備節點[...2]檢查。
檢查VIP是否已漂移
[root@opengaussdb2 ~]# ip a|grep 192.168
inet ...2/24 brd ... scope global noprefixroute ens33
inet ...0/32 scope global ens33
檢查資料庫狀態[已failover成為Primary]
[omm@opengaussdb2 ~]$ gs_om -t status --detail
[ Cluster State ]
cluster_state : Degraded
redistributing : No
current_az : AZ_ALL
[ Datanode State ]
node node_ip instance state |
---|
1 opengaussdb1 ...1 6001 /gauss/data/db1 P Down Manually stopped |
2 opengaussdb2 ...2 6002 /gauss/data/db1 S Primary Normal |