PostgreSQL patroni高可用叢集

sync_tb發表於2021-03-23

虛擬機器規劃

--無需配置/etc/hosts
10.37.129.3 node1
10.37.129.4 node2
10.37.129.5 node3
10.37.129.6 vip

-- 所有節點安裝配置

一、系統環境準備

關閉防火牆

systemctl stop firewalld
systemctl disable firewalld

關閉selinux

sed -i 's/SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config
# 臨時關閉selinux
setenforce 0

安裝配置NTP

yum install -y chrony # 時間同步對於叢集環境很重要
sed ’/^server/d' /etc/chrony.conf
echo 'server s1a.time.edu.cn iburst' >> /etc/chrony.conf

啟動NTP服務

systemctl start chronyd
systenctl enable chronyd

二、各類軟體安裝

安裝PostgreSQL軟體

# 僅需要安裝軟體,安裝過程會自動建立postgres使用者,但是不包含使用者密碼
yum install -y postgresql12 postgresql12-server postsedgresql12-libs postgresql12-contrib
# 修改postgres使用者密碼
echo '123456'|passwd postgres --stdin

安裝python3以及依賴包

yum install -y python3 python-psycopg2 python3-devel

安裝Etcd軟體

yum install -y etcd

安裝patroni軟體

# patroni軟體使用python3編寫,因此需要使用pip安裝
pip3 install psycopg2-binary
pip3 install patroni[etcd]

三、配置sudo許可權

$ visudo 
## Allow root to run any commands anywhere
postgres        ALL=(root)        NOPASSWD: ALL

四、Etcd叢集配置

Etcd配置安裝參考另外一篇部落格《Etcd叢集靜態配置》,安裝配置較為簡單
# 啟動Etcd
systemctl start etcd # 命令執行後,直接去其他節點啟動,節點間通訊成功後才可以正常啟動,不然會報超時錯誤 
systemctl enable etcd # 啟用開啟啟動
# 檢視Etcd狀態
$ etcdctl member list
49bab10dd5347fa2, started, etcd2, 
97cdb5480a6be19f, started, etcd3, 
a2916ae27f29d955, started, etcd1,

五、建立patroni服務

# 為了更便於管理,配置systemd服務進行管理,在patroni原始碼包中有patroni.service示例檔案可以參考
$ vi /usr/lib/systemd/system/patroni.service
[Unit]
Description=Runners to orchestrate a high-availability PostgreSQL
After=syslog.target network.target
 
[Service]
Type=simple
User=postgres
Group=postgres
EnvironmentFile=-/etc/patroni/patroni_env.conf
ExecStartPre=-/usr/bin/sudo /sbin/modprobe softdog # 使用watchdog進行服務監控
ExecStartPre=-/usr/bin/sudo /bin/chown postgres /dev/watchdog # 使用postgres使用者管理,需要sudo
ExecStart=/usr/local/bin/patroni /etc/patroni/patroni.yml # 注意糾正patroni命令的路徑
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=process
TimeoutSec=30
Restart=no
 
[Install]
WantedBy=multi-user.target
# 重新載入systemd服務
$ systemctl daemon-reload

六、配置patroni

# node1
# 配置檔案路徑在前面systemd服務中已經定義
# 檔案格式是yaml文字,不支援使用tab製表位,會提示語法錯誤
$ vi /etc/patroni/patroni.yml
scope: pgsql
namespace: /service/ # Etcd中鍵值位置
name: pg1 # patroni名稱,每個節點不一樣
 
restapi:
  listen: 0.0.0.0:8008 # 保持預設,監聽所有的8008埠
  connect_address: 10.37.129.3:8008 # 本地連線通訊
 
etcd3: # 這裡建議使用etcdv3,預設是etcdv2,預設寫入到etcd中的鍵值都是不可見的(僅patroni如此)
  hosts: 10.37.129.3:2379,10.37.129.4:2379,10.37.129.5:2379 # Etcd地址,如果這裡使用單節點的etcd,需要將hosts關鍵字替換為host
 
bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576 # 如果延遲超過1048576,不允許failover
    master_start_timeout: 300
    synchronous_mode: false # 非同步複製
    postgresql: # 以下是pgsql服務的特性即引數配置,不詳述
      use_pg_rewind: true
      use_slots: true
      parameters:
        listen_addresses: "0.0.0.0"
        port: 5432
        wal_level: replica
        hot_standby: "on"
        wal_keep_segments: 100
        max_wal_senders: 10
        max_replication_slots: 10
        wal_log_hints: "on"
        archive_mode: "on"
        archive_timeout: 1800s
        archive_command: mkdir -p ../wal_archive && test ! -f ../wal_archive/%f && cp %p ../wal_archive/%f
      recovery_conf:
        restore_command: cp ../wal_archive/%f %p
 
  initdb:
  - encoding: UTF8
  - locale: C
  - lc-ctype: zh_CN.UTF-8
  - data-checksums
 
  pg_hba: # 定義流複製使用者和遠端連線身份鑑別設定
  - host replication postgres 10.37.129.0/24 md5
  - host all all 0.0.0.0/0 md5
 
postgresql: 
  listen: 0.0.0.0:5432
  connect_address: 10.37.129.3:5432 # 連線pgsql服務的配置,這裡不能使用127.0.0.1,pg_basebackup需要遠端連線主庫進行線上複製
  data_dir: /var/lib/pgsql/12/data # $PGDATA
  bin_dir: /usr/pgsql-12/bin # $PGHOME/bin
 
  authentication:
    replication:
      username: postgres
      password: "123456"
    superuser:
      username: postgres
      password: "123456"
    rewind:
      username: postgres
      password: "123456"
 
  basebackup:
    max-rate: 100M
    checkpoint: fast
 
  callbacks: # 本次配置沒有使用haproxy+keepalived實現VIP切換和負載均衡,因為callbacks方式更快速,對系統資源消耗更小,操作更簡單,指令碼後面提供
    on_start: /bin/bash /etc/patroni/patroni_callback.sh # patroni服務啟動時候的觸發的操作
    on_stop: /bin/bash /etc/patroni/patroni_callback.sh # patroni服務停止時候觸發的操作
    on_role_change: /bin/bash /etc/patroni/patroni_callback.sh # patroni服務角色切換時觸發的操作
 
watchdog: # 使用linux自帶的軟體watchdog監控patroni的服務持續性
  mode: automatic # Allowed values: off, automatic, required
  device: /dev/watchdog # watchdog裝置,/dev/watchdog和/dev/watchdog0等同,可能存在相容性區別
  safety_margin: 5
 
tags:
    nofailover: false # 是否執行自動切換
    noloadbalance: false # 是否開啟負載均衡
    clonefrom: false
    nosync: false
# node2
# 修改
name: pg2
restapi:
  listen: 0.0.0.0:8008
  connect_address: 10.37.129.4:8008
postgresql: 
  listen: 0.0.0.0:5432
  connect_address: 10.37.129.4:5432
# node3
# 修改
name: pg3
restapi:
  listen: 0.0.0.0:8008
  connect_address: 10.37.129.5:8008
  
postgresql: 
  listen: 0.0.0.0:5432
  connect_address: 10.37.129.5:5432

七、安裝watchdog

# 安裝軟體,linux內建功能
yum install -y watchdog
# 初始化watchdog字元裝置
modprobe softdog
# 修改/dev/watchdog裝置許可權
chmod 666 /dev/watchdog
# 啟動watchdog服務
systemctl start watchdog
systemctl enable watchdog

八、建立patroni_callback指令碼

# 指令碼的開頭傳入了三個變數,但是在patroni.yml檔案中我們並沒有傳入任何的變數,實際測試過程中發現由patroni服務預設傳入三個變數
$1 - action, patroni觸發的動作,stop/start/on_role_change/restart/reload
$2 - role, 當前節點的角色,master/{slave|replica}
$3 - scope, 作用範圍,pgsql服務
# 指令碼來自於其他部落格,由於邏輯很簡單,直接引用了
# 當節點角色為主,使用ip addr命令繫結VIP地址
# 當節點角色為備,使用ip addr命令解綁VIP地址
$ vi /etc/patroni/patroni_callback.sh
#!/bin/bash
 
readonly action=$1
readonly role=$2
readonly scope=$3
 
function usage() {
    echo "Usage: $0 <on_start|on_stop|on_role_change> <role> <scope>"
    exit 1
}
 
echo "this is patroni callback $action $role $scope"
 
case $cb_name in
    on_stop)
        sudo ip addr del 10.37.129.6/24 dev eth1 label eth1:1
        ;;
    on_start)
        ;;
    on_role_change)
        if [[ $role == 'master' ]]; then
            # 繫結VIP
            sudo ip addr add 10.37.129.6/24 brd 10.37.129.255 dev eth1 label eth1:1
            # 監測VIP衝突,並遮蔽衝突的IP
            sudo arping -q -A -c 1 -I eth1 10.37.129.6
        else
            sudo ip addr del 10.37.129.6/24 dev eth1 label eth1:1
        fi
        ;;
    *)
        usage
        ;;
esac

九、啟動patroni服務

# 啟動服務
systemctl start patroni # 服務啟動會自動進行資料庫的初始化和備庫的建立
systemctl enable patroni
# 檢視狀態
$ patronictl -c /etc/patroni/patroni.yml list
+ Cluster: pgsql (6942702405679816489) ----+----+-----------+
| Member | Host        | Role    | State   | TL | Lag in MB |
+--------+-------------+---------+---------+----+-----------+
| pg1    | 10.37.129.3 | Replica | running |  2 |         0 |
| pg2    | 10.37.129.4 | Leader  | running |  2 |           |
| pg3    | 10.37.129.5 | Replica | running |  2 |         0 |
+--------+-------------+---------+---------+----+-----------+
# 檢視VIP
[root@node2 ~]# ip -o -4 a
1: lo    inet 127.0.0.1/8 scope host lo\       valid_lft forever preferred_lft forever
2: eth0    inet 10.211.55.11/24 brd 10.211.55.255 scope global noprefixroute dynamic eth0\       valid_lft 1766sec preferred_lft 1766sec
3: eth1    inet 10.37.129.4/24 brd 10.37.129.255 scope global noprefixroute eth1\       valid_lft forever preferred_lft forever
3: eth1    inet 10.37.129.6/24 brd 10.37.129.255 scope global secondary eth1:1\       valid_lft forever preferred_lft forever
4: eth2    inet 192.168.56.4/24 brd 192.168.56.255 scope global noprefixroute eth2\       valid_lft forever preferred_lft forever

十、手動觸發故障切換

# PostgreSQL預設使用的非同步複製,當postgres服務異常停止後並不會觸發主備自動切換,而是patroni嘗試拉起down掉的服務,如果未正常拉起服務,則執行故障切換
# 關閉patroni服務
$ systemctl stop patroni
# 檢視patroni服務
[root@node3 ~]# patronictl -c /etc/patroni/patroni.yml list
+ Cluster: pgsql (6942702405679816489) ----+----+-----------+
| Member | Host        | Role    | State   | TL | Lag in MB |
+--------+-------------+---------+---------+----+-----------+
| pg1    | 10.37.129.3 | Replica | running |  4 |         0 |
| pg2    | 10.37.129.4 | Replica | stopped |    |   unknown |
| pg3    | 10.37.129.5 | Leader  | running |  4 |           |
+--------+-------------+---------+---------+----+-----------+
# 檢視VIP
[root@node3 ~]# ip -o -4 a
1: lo    inet 127.0.0.1/8 scope host lo\       valid_lft forever preferred_lft forever
2: eth0    inet 10.211.55.12/24 brd 10.211.55.255 scope global noprefixroute dynamic eth0\       valid_lft 1224sec preferred_lft 1224sec
3: eth1    inet 10.37.129.5/24 brd 10.37.129.255 scope global noprefixroute eth1\       valid_lft forever preferred_lft forever
3: eth1    inet 10.37.129.6/24 brd 10.37.129.255 scope global secondary eth1:1\       valid_lft forever preferred_lft forever
4: eth2    inet 192.168.56.5/24 brd 192.168.56.255 scope global noprefixroute eth2\       valid_lft forever preferred_lft forever
# 管理叢集
$ patronictl --help


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30496307/viewspace-2764349/,如需轉載,請註明出處,否則將追究法律責任。

相關文章