項(xiàng)目地址:https://github.com/patroni/patroni
官方文檔:https://patroni.readthedocs.io/en/latest/
中文手冊:https://postgres-cn.github.io/patroni-doccn/
參考:https://docs.percona.com/postgresql/14/solutions/ha-setup-yum.html#method-1-modify-the-configuration-file
服務(wù)規(guī)劃
| hostname | ip | 服務(wù) |
|---|---|---|
| node1 | 172.17.83.2 | etcd,postgresql,Patroni,haproxy |
| node2 | 172.17.83.8 | etcd,postgresql,Patroni,haproxy |
| node3 | 172.17.83.12 | etcd,postgresql,Patroni,haproxy |
準(zhǔn)備工作
調(diào)整 hostname
# 修改 hostname
hostnamectl set-hostname node1
# 修改 hosts文件 /etc/hosts
172.17.83.2 node1
172.17.83.8 node2
172.17.83.12 node3
Watchdog
# 加載 `softdog` 內(nèi)核模塊
modprobe softdog
chown postgres /dev/watchdog
# 確保 Watchdog 設(shè)備文件存在
[root@node2 pgsql]# ll /dev/watchdog
crw------- 1 postgres root 10, 130 2月 12 09:54 /dev/watchdog
部署 PG14
安裝PG
# 更新系統(tǒng)包
yum install -y epel-release
yum update -y
# 安裝pg
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum install -y postgresql14-server
安裝 Postgis
# 清理重復(fù)的包
yum install yum-utils -y
package-cleanup --dupes
# Postgis
yum install -y zlib-devel openssl postgis33_14 postgis33_14-utils
初始化
數(shù)據(jù)目錄
mkdir -p /data/pgsql/
touch /data/pgsql/patroni.yml
chown -Rf postgres:postgres /data/pgsql
環(huán)境變量
# 切換用戶
[root@VM-0-3-centos ~]# su - postgres
上一次登錄:二 10月 22 10:20:05 CST 2024pts/1 上
# 修改配置
-bash-4.2$ vim .bash_profile
export PGHOME=/usr/pgsql-14
export PGDATA=/data/pgsql/data
PATH=$PGHOME/bin:$PATH
# 使生效
source ~/.bash_profile
部署 ETCD
etcd 集群的節(jié)點(diǎn)時(shí)間一定要同步!
時(shí)間同步
yum install chrony -y
systemctl start chronyd.service
systemctl enable chronyd.service
systemctl status chronyd.service
配置文件
[root@VM-0-17-centos etcd]# egrep -v '^#|^$' /etc/chrony.conf
server ntpupdate.tencentyun.com iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony
YUM 安裝
在線安裝
yum -y install etcd
配置文件
/etc/etcd/etcd.conf
定義變量
export NODE_NAME=`hostname -f`
export NODE_IP=`hostname -i | awk '{print $1}'`
生成配置
echo "
ETCD_NAME="${NODE_NAME}"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://${NODE_IP}:2379,http://127.0.0.1:2379"
ETCD_LISTEN_PEER_URLS="http://${NODE_IP}:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://${NODE_IP}:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://${NODE_IP}:2379"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER="node1=http://172.17.83.2:2380,node2=http://172.17.83.8:2380,node3=http://172.17.83.12:2380"
" | sudo tee /etc/etcd/etcd.conf
啟動(dòng)測試
WARNING:
Environment variable ETCDCTL_API is not set; defaults to etcdctl v2.
Set environment variable ETCDCTL_API=3 to use v3 API or ETCDCTL_API=2 to use v2 API
設(shè)置環(huán)境變量
vim /etc/profile
export ETCDCTL_API=3
export ENDPOINTS=172.17.83.2:2379,172.17.83.8:2379,172.17.83.12:2379
# 生效
source /etc/profile
啟動(dòng)服務(wù)
# 關(guān)閉防火墻
systemctl stop firewalld && systemctl disable firewalld
# 啟動(dòng)etcd
systemctl start etcd.service
systemctl enable etcd.service
檢查狀態(tài)
# 查看節(jié)點(diǎn)狀態(tài)
[root@node3 ~]# etcdctl member list --write-out=table
+------------------+---------+-------+--------------------------+--------------------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS |
+------------------+---------+-------+--------------------------+--------------------------+
| 94e289847b4c3e24 | started | node2 | http://172.17.83.8:2380 | http://172.17.83.8:2379 |
| 9e132ce4635c9d9d | started | node1 | http://172.17.83.2:2380 | http://172.17.83.2:2379 |
| e32396bcdee20faf | started | node3 | http://172.17.83.12:2380 | http://172.17.83.12:2379 |
+------------------+---------+-------+--------------------------+--------------------------+
--------+-------------------------+
[root@node3 ~]# etcdctl endpoint status --endpoints=$ENDPOINTS --write-out=table
+-------------------+------------------+---------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-------------------+------------------+---------+---------+-----------+-----------+------------+
| 172.17.83.2:2379 | 9e132ce4635c9d9d | 3.3.11 | 20 kB | false | 366 | 10 |
| 172.17.83.8:2379 | 94e289847b4c3e24 | 3.3.11 | 20 kB | false | 366 | 10 |
| 172.17.83.12:2379 | e32396bcdee20faf | 3.3.11 | 20 kB | true | 366 | 10 |
+-------------------+------------------+---------+---------+-----------+-----------+------------+
數(shù)據(jù)操作
# 查詢存儲(chǔ)的所有key,并且前綴為'/'
[root@VM-0-3-centos system]# etcdctl get / --prefix
/service/pg_patroni/config
{"loop_wait":10,"retry_timeout":10,"ttl":30,"postgresql":{"parameters":{"listen_addresses":"0.0.0.0","hot_standby":"on","max_connections":2000,"shared_buffers":"4GB","max_locks_per_transaction":64,"max_prepared_transactions":0,"max_replication_slots":10,"max_wal_senders":10,"max_worker_processes":8,"track_commit_timestamp":"off","wal_keep_size":"128MB","wal_level":"replica","wal_log_hints":"on"},"use_pg_rewind":true,"use_slots":true}}
/service/pg_patroni/initialize
7428520042617295490
/service/pg_patroni/status
{"optime":24414320,"slots":{"patroni1":24414320},"retain_slots":["patroni1"]}
# 清除所有數(shù)據(jù)
[root@VM-0-3-centos system]# etcdctl del / --prefix
3
部署 Patroni
Patroni 依賴 Python3,必須 3.7 及以上版本
PIP 安裝
pip install patroni[psycopg3,etcd3]
YUM 安裝
yum install patroni patroni-etcd
驗(yàn)證調(diào)試
[root@node3 opt]# python3.8 -V
Python 3.8.20
[root@node3 opt]# patronictl --help
Usage: patronictl [OPTIONS] COMMAND [ARGS]...
Command-line interface for interacting with Patroni.
Options:
-c, --config-file TEXT Configuration file
-d, --dcs-url, --dcs TEXT The DCS connect url
-k, --insecure Allow connections to SSL sites without certs
--help Show this message and exit.
配置文件
https://patroni.readthedocs.io/en/latest/yaml_configuration.html
定義變量
export NODE_NAME=`hostname -f`
export NODE_IP=`hostname -i | awk '{print $1}'`
生成配置
注意修改 postgres 用戶的密碼,pg_hba 網(wǎng)絡(luò)的配置,etcd 的ip
echo "
scope: 'pg_patroni'
namespace: /db/
name: '${NODE_NAME}'
log:
format: '%(asctime)s %(levelname)s: %(message)s'
level: INFO
max_queue_size: 1000
traceback_level: ERROR
type: plain
restapi:
connect_address: '${NODE_IP}:8008'
listen: '0.0.0.0:8008'
etcd3:
hosts:
- 172.17.83.2:2379
- 172.17.83.8:2379
- 172.17.83.12:2379
retry_timeout: 30
ttl: 60
bootstrap:
dcs:
loop_wait: 10
retry_timeout: 10
ttl: 30
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
hot_standby: 'on'
max_connections: 2000
shared_buffers: 4GB
max_locks_per_transaction: 64
max_prepared_transactions: 0
max_replication_slots: 10
max_wal_senders: 10
max_worker_processes: 8
track_commit_timestamp: 'off'
wal_keep_size: 5GB
wal_level: replica
wal_log_hints: 'on'
max_wal_size: '10GB'
archive_mode: "on"
archive_timeout: 600s
archive_command: "cp -f %p /data/pgsql/data/archived/%f"
initdb:
- encoding: UTF8
- locale: C
- data-checksums
pg_hba:
- host all all 0.0.0.0/0 md5
- host replication replicator 172.17.83.0/24 md5
- host replication replicator 127.0.0.1/32 trust
postgresql:
listen: '0.0.0.0:5432'
connect_address: '${NODE_IP}:5432'
bin_dir: '/usr/pgsql-14/bin/'
data_dir: '/data/pgsql/data/'
parameters:
password_encryption: scram-sha-256
unix_socket_directories: "/var/run/postgresql/"
authentication:
replication:
password: 'replicator'
username: replicator
superuser:
password: 'xxxx'
username: postgres
create_replica_methods:
- basebackup
basebackup:
checkpoint: 'fast'
watchdog:
mode: automatic
device: /dev/watchdog
tags:
clonefrom: false
failover_priority: 1
noloadbalance: false
nostream: false
nosync: false
" | sudo tee /data/pgsql/patroni.yml
啟動(dòng)集群
手動(dòng)啟動(dòng)
# 切換 postgres
su postgres
cd /data/pgsql/
nohup patroni patroni.yml > patroni.log 2>&1 &
systemd
創(chuàng)建啟動(dòng)文件
注意修改 patroni 可執(zhí)行文件路徑
/etc/systemd/system/percona-patroni.service
echo "
[Unit]
Description=Patroni PostgreSQL HA
After=network.target
[Service]
Type=simple
User=postgres
Group=postgres
ExecStart=/opt/python3.8/lib/python3.8/site-packages/bin/patroni /data/pgsql/patroni.yml
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
TimeoutSec=300
LimitNOFILE=4096
[Install]
WantedBy=multi-user.target
" | sudo tee /etc/systemd/system/patroni.service
啟動(dòng)服務(wù)
先啟動(dòng)一個(gè) node1 節(jié)點(diǎn),服務(wù)啟動(dòng)后,再依次啟動(dòng)其他 node節(jié)點(diǎn)
systemctl daemon-reload
systemctl start patroni
檢查狀態(tài)
[root@node1 pgsql]# patronictl -c /data/pgsql/patroni.yml list
+ Cluster: pg_patroni (7470725539388708392) --+----+-----------+----------------------+
| Member | Host | Role | State | TL | Lag in MB | Tags |
+--------+--------------+---------+-----------+----+-----------+----------------------+
| node1 | 172.17.83.2 | Replica | streaming | 1 | 0 | failover_priority: 1 |
| node2 | 172.17.83.8 | Leader | running | 1 | | failover_priority: 1 |
| node3 | 172.17.83.12 | Replica | streaming | 1 | 0 | failover_priority: 1 |
+--------+--------------+---------+-----------+----+-----------+----------------------+
HAProxy
YUM 安裝
yum install haproxy -y
配置文件
/etc/haproxy/haproxy.cfg
global
maxconn 2000
defaults
log global
mode tcp
retries 2
timeout client 40m
timeout connect 4s
timeout server 40m
timeout check 5s
listen stats
bind *:8089
mode http
stats enable
stats uri /stats
stats refresh 10s
listen primary
bind *:5000
option httpchk /primary
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server node1 node1:5432 maxconn 2000 check port 8008
server node2 node2:5432 maxconn 2000 check port 8008
server node3 node3:5432 maxconn 2000 check port 8008
啟動(dòng)驗(yàn)證
# 啟動(dòng)服務(wù)
systemctl enable --now haproxy
監(jiān)控管理端:http://172.17.83.8:8089/stats

負(fù)載均衡
haproxy 的 5000 端口 會(huì)轉(zhuǎn)發(fā)到 PG 集群的 Leader 節(jié)點(diǎn)的 5432
再使用負(fù)載均衡服務(wù),轉(zhuǎn)發(fā) node1,node2,node3 的 5000 端口
應(yīng)用服務(wù)配置負(fù)載均衡的地址,即可實(shí)現(xiàn)PG高可用。
高可用驗(yàn)證
主動(dòng)切換
檢查集群狀態(tài),node3 為 Leader 節(jié)點(diǎn)

切換節(jié)點(diǎn),需指定集群名稱:pg_patroni
patronictl -c /data/pgsql/patroni.yml switchover pg_patroni

檢查節(jié)點(diǎn)狀態(tài),成功切換為 node1 為 Leader 節(jié)點(diǎn)

關(guān)停服務(wù)
關(guān)停 PG
使用 kill 命令,停止 postgresql 進(jìn)程,patroni 會(huì)主動(dòng)拉起 postgresql 服務(wù)。
關(guān)停 patroni
停止 patroni 服務(wù),會(huì)同時(shí)停止 postgresql 進(jìn)程,PG 集群會(huì)重新選主,并剔除掛掉的節(jié)點(diǎn)。
重新啟動(dòng) patroni 服務(wù),PG 集群恢復(fù)1主2從,自動(dòng)同步數(shù)據(jù)。
systemctl stop patroni

systemctl start patroni
