本指南提供了有關如何在 Red Hat Enterprise Linux 或 CentOS 上使用 Patroni 設定高可用性 PostgreSQL 叢集的說明。
注意事項¶
-
這是一個示例部署,其中 etcd 與 Patroni 和 PostgreSQL 在同一臺主機上執行,並且有一個專用的 HAProxy 主機。或者,etcd 可以在不同的節點集上執行。
如果 etcd 與 Patroni 和 PostgreSQL 部署在同一臺主機上,出於效能原因,建議為 etcd 和 PostgreSQL 使用單獨的磁碟系統。
對於此設定,我們使用執行 Red Hat Enterprise Linux 8 的節點作為基礎作業系統:
節點名稱 | 應用 | IP地址 |
---|---|---|
節點1 | Patroni、PostgreSQL、etcd | 10.104.0.1 |
節點2 | Patroni、PostgreSQL、etcd | 10.104.0.2 |
節點3 | Patroni、PostgreSQL、etcd | 10.104.0.3 |
HAProxy 演示 | HAProxy | 10.104.0.6 |
由於存在安全風險,我們建議不要將執行 Patroni / etcd / PostgreSQL 的主機/節點暴露到公共網路。使用防火牆、虛擬網路、子網等保護資料庫主機免受任何型別的攻擊。
初始設定¶
/etc/hosts
在檔案中設定主機名¶
名稱解析不是必需的,但它使整個設定更易讀且更不容易出錯。在這裡,我們不是配置 DNS,而是透過更新檔案來使用本地名稱解析/etc/hosts
。透過將其主機名解析為其 IP 地址,我們使節點知道彼此的名稱並允許它們無縫通訊。
-
在每個節點上執行以下命令。將節點名稱分別更改為
node1
、node2
和node3
:
sudo hostnamectl set-hostname node-1
- 修改每個 PostgreSQL 節點的檔案,使其包含其餘節點的主機名和 IP 地址。在所有節點上的檔案
/etc/hosts
末尾新增以下內容:/etc/hosts
節點
# Cluster IP and names 10.104.0.1 node1 10.104.0.2 node2 10.104.0.3 node3
HAproxy 演示
HAProxy 例項應在其檔案中具有所有三個節點的名稱解析/etc/hosts
。在檔案末尾新增以下幾行:
# Cluster IP and names 10.104.0.6 HAProxy-demo 10.104.0.1 node1 10.104.0.2 node2 10.104.0.3 node3
安裝軟體¶
在 上安裝 Percona Distribution for PostgreSQL node1
,node2
並node3
從 Percona 儲存庫安裝:
安裝一些 Python 和輔助包來幫助 Patroni 和 etcd
sudo yum install python3-pip python3-devel binutils
安裝 etcd、Patroni、pgBackRest 包。
sudo yum install percona-patroni \ etcd python3-python-etcd\ percona-pgbackrest
停止並禁用所有已安裝的服務:
sudo systemctl stop {etcd,patroni,postgresql}
systemctl disable {etcd,patroni,postgresql}
配置 etcd 分散式儲存
分散式配置儲存提供了一種可靠的方法來儲存需要由大規模分散式系統訪問的資料。最流行的分散式配置儲存實現是 etcd。etcd 部署為叢集以實現容錯,並且需要奇數個成員 (n/2+1) 才能就叢集狀態的更新達成一致。etcd 叢集有助於在故障轉移期間在節點之間建立共識,並管理三個 PostgreSQL 例項的配置。
叢集etcd
首先在一個節點上啟動,然後使用命令將後續節點新增到第一個節點上add
。
配置node1
- 建立配置檔案。您可以編輯示例配置檔案
/etc/etcd/etcd.conf.yaml
或建立自己的配置檔案。將節點名稱和 IP 地址替換為您節點的實際名稱和 IP 地址。
/etc/etcd/etcd.conf.yaml
name: 'node1' #成員的可讀性的名字. initial-cluster-token: PostgreSQL_HA_Cluster_1 #在啟動期間用於 etcd 叢集的初始化叢集記號(cluster token)。 initial-cluster-state: new #初始化叢集狀態("new" or "existing")。在初始化靜態(initial static)或者 DNS 啟動 (DNS bootstrapping) 期間為所有成員設定為new
。如果這個選項被設定為existing
, etcd 將試圖加入已有的叢集。如果設定為錯誤的值,etcd 將嘗試啟動但安全失敗。 initial-cluster: node1=http://10.104.0.1:2380 #為啟動初始化叢集配置。 data-dir: /var/lib/etcd #資料目錄的路徑 initial-advertise-peer-urls: http://10.104.0.1:2380 #列出這個成員的夥伴 URL 以便通告給叢集的其他成員。預設:"http://localhost:2380" listen-peer-urls: http://10.104.0.1:2380 #用於監聽夥伴通訊的URL列表。 advertise-client-urls: http://10.104.0.1:2379 #列出這個成員的客戶端URL,預設: "http://localhost:2379" listen-client-urls: http://10.104.0.1:2379 #用於監聽客戶端通訊的URL列表。
啟動etcd
服務以應用更改node1
:
sudo systemctl enable --now etcd
sudo systemctl status etcd
檢查 etcd 叢集成員node1
。
sudo etcdctl member lis
示例輸出:
21d50d7f768f153a: name=default peerURLs=http://10.104.0.5:2380 clientURLs=http://10. 104.0.5:2379 isLeader=true
新增node2
到叢集。在 node1上執行以下命令:
$ sudo etcdctl member add node2 http://10.104.0.2:2380
Added member named node2 with ID 10042578c504d052 to cluster etcd_NAME="node2" etcd_INITIAL_CLUSTER="node2=http://10.104.0.2:2380,node1=http://10.104.0.1:2380" etcd_INITIAL_CLUSTER_STATE="existing"
配置node2
建立配置檔案。您可以編輯示例配置檔案/etc/etcd/etcd.conf.yaml
或建立自己的配置檔案。將節點名稱和 IP 地址替換為您節點的實際名稱和 IP 地址。
/etc/etcd/etcd.conf.yaml
name: 'node2' initial-cluster-token: PostgreSQL_HA_Cluster_1 initial-cluster-state: existing initial-cluster: node1=http://10.104.0.1:2380,node2=http://10.104.0.2:2380 data-dir: /var/lib/etcd initial-advertise-peer-urls: http://10.104.0.2:2380 listen-peer-urls: http://10.104.0.2:2380 advertise-client-urls: http://10.104.0.2:2379 listen-client-urls: http://10.104.0.2:2379
啟動etcd
服務以應用更改node2
:
sudo systemctl enable --now etcd
sudo systemctl status etcd
配置node3
新增node3
到叢集。在 node1
上執行以下命令:
sudo etcdctl member add node3 http://10.104.0.3:2380
在 node3上,建立配置檔案。您可以編輯示例配置檔案/etc/etcd/etcd.conf.yaml
或建立自己的配置檔案。將節點名稱和 IP 地址替換為您的節點的實際名稱和 IP 地址:
/etc/etcd/etcd.conf.yaml
name: 'node1' initial-cluster-token: PostgreSQL_HA_Cluster_1 initial-cluster-state: existing initial-cluster: node1=http://10.104.0.1:2380,node2=http://10.104.0.2:2380,node3=http://10.104.0.3:2380 data-dir: /var/lib/etcd initial-advertise-peer-urls: http://10.104.0.3:2380 listen-peer-urls: http://10.104.0.3:2380 advertise-client-urls: http://10.104.0.3:2379 listen-client-urls: http://10.104.0.3:2379
啟動etcd
服務以應用更改。
sudo systemctl enable --now etcd
sudo systemctl status etcd
檢查 etcd 叢集成員。
sudo etcdctl member list
2d346bd3ae7f07c4: name=node2 peerURLs=http://10.104.0.2:2380 clientURLs=http://10.104.0.2:2379 isLeader=false 8bacb519ebdee8db: name=node3 peerURLs=http://10.104.0.3:2380 clientURLs=http://10.104.0.3:2379 isLeader=false c5f52ea2ade25e1b: name=node1 peerURLs=http://10.104.0.1:2380 clientURLs=http://10.104.0.1:2379 isLeader=true
配置 Patroni
在所有節點上執行以下命令。您可以並行執行此操作:
-
匯出並建立環境變數以簡化配置檔案的建立:
- 節點名稱:
export NODE_NAME=`hostname -f` #
- 節點 IP:
export NODE_IP=`hostname -i | awk '{print $1}'`
- 建立變數來儲存 PATH:
DATA_DIR="/var/lib/pgsql/data/" PG_BIN_DIR="/usr/pgsql-15/bin"
注意:檢查作業系統上資料和 bin 資料夾的路徑,並相應地更改變數。
- 贊助人資訊:
NAMESPACE="percona_lab" SCOPE="cluster_1
建立 Patroni 所需的目錄
- 建立用於儲存配置檔案的目錄並使其歸使用者所有
postgres
。
sudo mkdir -p /etc/patroni/
sudo chown -R postgres:postgres /etc/patroni/
- 建立資料目錄來儲存 PostgreSQL 資料。將其所有權更改為使用者
postgres
並限制對它的訪問
sudo mkdir /data/pgsql -p sudo chown -R postgres:postgres /data/pgsql sudo chmod 700 /data/pgsql
建立/etc/patroni/patroni.yml
配置檔案。新增以下配置:
echo " namespace: ${NAMESPACE} scope: ${SCOPE} name: ${NODE_NAME} restapi: listen: 0.0.0.0:8008 connect_address: ${NODE_IP}:8008 etcd3: host: ${NODE_IP}:2379 bootstrap: # this section will be written into Etcd:/<namespace>/<scope>/config after initializing new cluster dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 slots: percona_cluster_1: type: physical postgresql: use_pg_rewind: true use_slots: true parameters: wal_level: replica hot_standby: "on" wal_keep_segments: 10 max_wal_senders: 5 max_replication_slots: 10 wal_log_hints: "on" logging_collector: 'on' # some desired options for 'initdb' initdb: # Note: It needs to be a list (some options need values, others are switches) - encoding: UTF8 - data-checksums pg_hba: # Add following lines to pg_hba.conf after running 'initdb' #初始化叢集后配置設定 - host replication replicator 127.0.0.1/32 trust - host replication replicator 0.0.0.0/0 md5 - host all all 0.0.0.0/0 md5 - host all all ::0/0 md5 # Some additional users which needs to be created after initializing new cluster,#資料庫需要建立的使用者 users: admin: password: qaz123 options: - createrole - createdb percona: password: qaz123 options: - createrole - createdb postgresql: cluster_name: cluster_1 listen: 0.0.0.0:5432 connect_address: ${NODE_IP}:5432 data_dir: ${DATA_DIR} bin_dir: ${PG_BIN_DIR} pgpass: /tmp/pgpass authentication: replication: username: replicator password: replPasswd superuser: username: postgres password: qaz123 parameters: unix_socket_directories: "/var/run/postgresql/" create_replica_methods: - basebackup basebackup: checkpoint: 'fast' tags: nofailover: false noloadbalance: false clonefrom: false nosync: false " | sudo tee -a /etc/patroni/patroni.yml
檢查 systemd 單元檔案patroni.service
是否已在 /etc/systemd/system中建立。如果已建立,請跳過此步驟。
若未建立,請手動建立,並在其中指定以下內容:
/etc/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 # Start the patroni process ExecStart=/bin/patroni /etc/patroni/patroni.yml # Send HUP to reload from patroni.yml ExecReload=/bin/kill -s HUP $MAINPID # only kill the patroni process, not its children, so it will gracefully stop postgres KillMode=process # Give a reasonable amount of time for the server to start up/shut down TimeoutSec=30 # Do not restart the service if it crashes, we want to manually inspect database on failure Restart=no [Install] WantedBy=multi-user.target
瞭解systemd
新服務:
sudo systemctl daemon-reload
現在是時候啟動 Patroni 了。您需要在所有節點上(但不是並行)執行以下命令。從node1
第一個節點開始,等待服務上線,然後逐個處理其他節點,始終等待它們與主節點同步:
sudo systemctl enable --now patroni
sudo systemctl restart patroni
當 Patroni 啟動時,它會按照配置檔案引導部分中的指令初始化 PostgreSQL(因為該服務當前未執行且資料目錄為空)。
-
檢查服務是否有錯誤:
sudo journalctl -fu patroni
一個常見錯誤是 Patroni 抱怨 pg_hba.conf 檔案中缺少正確的條目。如果您看到此類錯誤,則必須手動新增或修復該檔案中的條目,然後重新啟動服務。
更改 patroni.yml 檔案並重新啟動服務不會產生任何影響,因為 bootstrap 部分指定了在節點中首次啟動 PostgreSQL 時要應用的配置。即使修改了 Patroni 配置檔案並重新啟動服務,它也不會重複該過程。
如果 Patroni 已正確啟動,您應該能夠使用以下命令本地連線到 PostgreSQL 節點:
sudo psql -U postgres psql (15.4) Type "help" for help. postgres=#
當所有節點都啟動並執行時,您可以使用以下命令檢查叢集狀態:
sudo patronictl -c /etc/patroni/patroni.yml list
輸出node1
類似以下內容:
+ Cluster: cluster_1 --+---------+---------+----+-----------+ | Member | Host | Role | State | TL | Lag in MB | +--------+-------------+---------+---------+----+-----------+ | node-1 | 10.0.100.1 | Leader | running | 1 | | +--------+-------------+---------+---------+----+-----------+
在其餘節點上:
+ Cluster: cluster_1 --+---------+---------+----+-----------+ | Member | Host | Role | State | TL | Lag in MB | +--------+-------------+---------+---------+----+-----------+ | node-1 | 10.0.100.1 | Leader | running | 1 | | | node-2 | 10.0.100.2 | Replica | running | 1 | 0 | +--------+-------------+---------+---------+----+-----------+
配置 HAProxy
HAproxy 是負載均衡器,也是客戶端應用程式進入 PostgreSQL 叢集的單一入口點。客戶端應用程式訪問 HAPpoxy URL 並將其讀/寫請求傳送到那裡。在後臺,HAProxy 以迴圈方式將寫入請求路由到主節點,將讀取請求路由到輔助節點,這樣就不會不必要地載入輔助例項。要實現這一點,請在 HAProxy 配置檔案中提供不同的埠。在此部署中,寫入被路由到埠 5000,讀取被路由到埠 5001
這樣,客戶端應用程式就不知道底層叢集中的哪個節點是當前主節點。HAProxy 將連線傳送到健康節點(只要至少有一個健康節點可用),並確保客戶端應用程式請求永遠不會被拒絕。
-
在節點上安裝 HAProxy
HAProxy-demo
:
sudo yum install percona-haproxy
HAProxy 配置檔案路徑為:/etc/haproxy/haproxy.cfg
。在此檔案中指定以下配置。
global maxconn 100 defaults log global mode tcp retries 2 timeout client 30m timeout connect 4s timeout server 30m timeout check 5s listen stats #“listen”部分定義了一個完整的代理,其前端和後端部分合並在一個部分中。它通常適用於僅 TCP 流量。 mode http bind *:7000 stats enable stats uri / listen primary bind *:5000 option httpchk /primary #後端,啟用 HTTP 協議檢查伺服器健康狀況,option httpchk <method> <uri> <version>,method是http中的方法,可省略;uri是http中的路徑; http-check expect status 200 #後端,定義以下 http-check 規則的註釋,如果失敗則在日誌中報告。使 HTTP 健康檢查考慮響應內容或特定狀態程式碼,配合上面使用 default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions #後端,更改後端伺服器的預設選項,“ inter ”引數將兩次連續健康檢查之間的間隔設定為 <delay> 毫秒;“ fall ” 參數列示伺服器在連續 <count> 次健康檢查失敗後將被視為已死亡。如果未指定,此值預設為 3;“ rise ”參數列示在連續 <count> 次成功健康檢查後,伺服器將被視為正常執行;on-marked-down修改伺服器被標記為關閉時發生的情況。目前有一個操作可用:-shutdown-sessions:關閉對等會話。啟用此設定後,伺服器關閉時所有與伺服器的連線都會立即終止。 server node1 node1:5432 maxconn 100 check port 8008 server node2 node2:5432 maxconn 100 check port 8008 server node3 node3:5432 maxconn 100 check port 8008 listen standbys balance roundrobin bind *:5001 option httpchk /replica http-check expect status 200 #後端 default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions server node1 node1:5432 maxconn 100 check port 8008 #check此選項啟用伺服器上的執行狀況檢查: - 未設定時,不執行執行狀況檢查,並且始終認為伺服器可用。可以使用“ addr ”更改目標地址,使用“ port ”更改埠。 server node2 node2:5432 maxconn 100 check port 8008 server node3 node3:5432 maxconn 100 check port 8008
-
HAProxy 將使用 Patroni 託管的 REST API 來檢查每個 PostgreSQL 節點的健康狀態並適當地路由請求。
-
啟用 SELinux 布林值以允許 HAProxy 繫結到非標準埠:
sudo setsebool -P haproxy_connect_any on
重新啟動 HAProxy:
sudo systemctl restart haproxy
檢查 HAProxy 日誌以檢視是否有任何錯誤:
sudo journalctl -u haproxy.service -n 100 -f
來源: https://docs.percona.com/postgresql/15/solutions/high-availability.html
https://www.haproxy.com/documentation/haproxy-configuration-tutorials/alerts-and-monitoring/prometheus/
https://www.haproxy.com/documentation/haproxy-configuration-manual/2-6r1/#4-server