Patroni + PostgreSQL 集群高可用部署

項(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

https://github.com/etcd-io/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

20250213154223.png

負(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)

20250213111759.png

切換節(jié)點(diǎn),需指定集群名稱:pg_patroni

patronictl -c /data/pgsql/patroni.yml switchover pg_patroni

20250213155608.png

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

20250213155717.png

關(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

20250213111655.png

systemctl start patroni

20250213155323.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容