注意:
- 此教學課程需要存取 Oracle Cloud。若要註冊免費帳戶,請參閱 Oracle Cloud Infrastructure Free Tier 入門。
- 它會使用 Oracle Cloud Infrastructure 證明資料、租用戶以及區間的範例值。完成實驗室之後,請將這些值取代為您雲端環境特有的值。
在 Oracle Cloud Infrastructure 上部署高可用性 Postgres 叢集
簡介
本教學課程概述使用 Patroni 和其他元件在 HA 組態中 Postgres 的設計與實作。PostgreSQL 缺少內建的自動容錯移轉和自動機制,可將失敗的主控機制加回叢集。Patroni 是 PostgreSQL 歲的新高可用性 (HA) 解決方案,具備雲端原生功能和進階選項,可進行容錯移轉 / 切換和自動啟動安裝及複本設定。
Patroni 是一個使用 Python 建立您自己的客製化 HA 解決方案的樣板,也是分散式組態存放區 (例如 etcd) 的最大輔助功能。
原生 Postgres 複製和使用 Patroni 的解決方案有下列限制:
原生 Postgres 複製中的限制 | 以 Patroni 為主的解決方案 |
---|---|
預設複製機制不支援自動容錯移轉。 | Patroni 提供自動容錯移轉。 |
使用外部工具進行容錯移轉可能需要額外努力,才能讓它們繼續運作。 | 帕特羅尼負責容錯移轉。 |
監督 Postgres 也可以是挑戰性。 | Patroni 擁有內建機制,可監控 Postgres 服務。 |
自動將失敗的節點加回叢集,需要進階命令檔技能。 | Patroni 已內建自動化功能,可將失敗的節點回復至叢集。 |
無法處理分割區塊鏈案例。 | 在 ETCD 的幫助下,Patroni 將能夠選擇新的領導者。 |
其他 PostgreSQL HA 解決方案包括:
- 維修員
- PostgreSQL 自動容錯移轉 (PAF)
- 俯瞰圖
- pgPool-II
不過,使用 Patroni 搭配 Postgres 實行,可大幅簡化整個叢集管理生命週期。
-
ETCD 是作為分散式組態存放區 (DCS)。它會儲存 PostgreSQL 叢集的狀態。當有任何 PostgreSQL 節點的狀態發生變更時,Patroni 會更新 ETCD 金鑰值存放區中的狀態變更。ETCD 會使用此資訊來選擇主節點,並保持叢集啟動與執行。
-
pgBackrest 是簡單可靠的自動備份解決方案。Pgbackrest 的優點:
- 這是一個實體備份工具,您可以採用差動、增量和完整備份
- 可以將平行工作設定為執行備份
- 可從待命資料庫進行備份
- 非同步 WAL (預先寫入存檔日誌) 推送和提取
- 可以配置多個儲存庫
- OCI/GCP/S3/Azure 的雲端備份選項
-
OCI 網路負載平衡器是用來與「領導者」節點通訊,而非 HAProxy。Oracle Cloud Infrastructure (OCI) 網路負載平衡器正透過此設定輕鬆整合託管服務。
目標
本教學課程列出可行的高效能解決方案,可讓客戶將 Postgres 資料庫 (從 AWS 或其他雲端供應商) 移轉至 OCI。HA 和即時資料移轉的主要需求。
架構
下列架構包含 3 個 ETCD 伺服器、3 個 (Postgres + Patroni + Pgbackrest) 伺服器、物件儲存的儲存桶以及網路負載平衡器。
建議
- 針對 HA:使用 3 個 ETCD 伺服器,即 PostgreSQL 的 3 個節點,並將其置於不同的可用性網域。
- 為了得到更佳的傳輸量,請為資料、暫時、Wal 和日誌檔建立個別的區塊磁碟區。
- 在建立叢集時,定義
patroni.yaml
bootstrap 區段中的所有自訂參數。
設定並安裝 PostgreSQL HA 元件
設定分為兩個部分:
- 基礎架構佈建
- 軟體安裝與組態
工作 1:佈建基礎架構
-
建立運算 VM:
- 3 ETCD 伺服器
- Postgres + Patroni 的 3 個伺服器 (1 個領導者和 2 個複本)
-
建立用於儲存備份的物件儲存的儲存桶。
-
在上述物件存放區儲存桶上建立具備 READ/WRITE 存取權的 OCI 租用戶使用者。
作業 2:安裝並設定軟體
-
配置 ETCD。
-
在 3 台伺服器上安裝 ETCD。
cd /tmp wget https://github.com/etcd-io/etcd/releases/download/v3.5.2/etcd-v3.5.2-linux-amd64.tar.gz tar xzvf /tmp/etcd-v3.5.2-linux-amd64.tar.gz cd etcd-v3.5.2-linux-amd64 cp etcdutl etcdctl etcd /usr/local/bin/ mkdir -p /etc/etcd mkdir -p /var/lib/etcd groupadd -f -g 1501 etcd useradd -c "etcd user" -d /var/lib/etcd -s /bin/false -g etcd -u 1501 etcd chown -R etcd:etcd /var/lib/etcd
-
在所有 3 個伺服器上設定並啟動 ETCD。
以下是 ETCD 伺服器詳細資料:
| Hostname | IP Address | Availability Domain | | --- | --- | --- | | pg-etcd-01 | 192.0.2.4 | AD1 | | pg-etcd-02 | 192.0.2.5 | AD2 | | pg-etcd-03 | 192.0.2.6 | AD3 |
注意:根據需求修改 IP。
pg-etcd-01
vi /etc/etcd/etcd.conf ###Node1 ##192.0.2.4 ETCD_NAME="pg-etcd-01" ETCD_INITIAL_CLUSTER="pg-etcd-01=http://192.0.2.4:2380" ETCD_LISTEN_CLIENT_URLS="http://192.0.2.4:2379,http://127.0.0.1:2379" ETCD_ADVERTISE_CLIENT_URLS="http://192.0.2.4:2379" ETCD_LISTEN_PEER_URLS="http://192.0.2.4:2380,http://127.0.0.1:7001" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.0.2.4:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="new" ETCD_DATA_DIR="/var/lib/etcd" ETCD_ELECTION_TIMEOUT="5000" ETCD_HEARTBEAT_INTERVAL="1000" ETCD_ENABLE_V2="true"
pg-etcd-02
vi /etc/etcd/etcd.conf ##Node2 ##192.0.2.5 ETCD_NAME=" pg-etcd-02" ETCD_INITIAL_CLUSTER="pg-etcd-01=http://192.0.2.4:2380,pg-etcd-02=http://192.0.2.5:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="existing" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.0.2.5:2380" ETCD_LISTEN_PEER_URLS="http://192.0.2.5:2380,http://127.0.0.1:7001" ETCD_LISTEN_CLIENT_URLS="http://192.0.2.5:2379,http://127.0.0.1:2379" ETCD_ADVERTISE_CLIENT_URLS="http://192.0.2.5:2379" ETCD_DATA_DIR="/var/lib/etcd" ETCD_ELECTION_TIMEOUT="5000" ETCD_HEARTBEAT_INTERVAL="1000" ETCD_ENABLE_V2="true"
pg-etcd-03
vi /etc/etcd/etcd.conf ##Node3 ##192.0.2.6 ETCD_NAME="pg-etcd-03" ETCD_INITIAL_CLUSTER="pg-etcd-01=http://192.0.2.4:2380,pg-etcd-02=http://192.0.2.5:2380,pg-etcd-03=http://192.0.2.6:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="existing" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.0.2.6:2380" ETCD_LISTEN_PEER_URLS="http://192.0.2.6:2380,http://127.0.0.1:7001" ETCD_LISTEN_CLIENT_URLS="http://192.0.2.6:2379,http://127.0.0.1:2379" ETCD_ADVERTISE_CLIENT_URLS="http://192.0.2.6:2379" ETCD_DATA_DIR="/var/lib/etcd" ETCD_ELECTION_TIMEOUT="5000" ETCD_HEARTBEAT_INTERVAL="1000" ETCD_ENABLE_V2="true"
-
新增成員至 pg-etcd-01。
etcdctl member add pg-etcd-02 --peer-urls=http://192.0.2.5:2380 etcdctl member add pg-etcd-03 --peer-urls=http://192.0.2.6:2380
-
執行下列指令以顯示成員清單。
etcdctl member list
-
建立服務。
vi /etc/systemd/system/etcd.service [Unit] Description=Etcd Server After=network.target After=network-online.target Wants=network-online.target [Service] Type=notify WorkingDirectory=/var/lib/etcd EnvironmentFile=-/etc/etcd/etcd.conf User=etcd # set GOMAXPROCS to number of processors ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/local/bin/etcd" Restart=on-failure LimitNOFILE=65536 IOSchedulingClass=best-effort IOSchedulingPriority=0 [Install] WantedBy=multi-user.target systemctl daemon-reload systemctl enable etcd
-
-
在所有節點上安裝 Postgres。執行下列程序檔以安裝 Postgres:
-
注意:若為 Replica,請停止 postgresql 並刪除當 Patroni 組態完成後,將從領導者複製的資料目錄。
/opt/pgsql/bin/pg_ctl -D /opt/pgsql/data/$MAJORVERSION stop cd /opt/pgsql/data/ rm *
-
-
安裝擴充功能:pg_squeeze 和 pgaudit。
-
安裝 PGAUDIT
cd /usr/local/src/postgresql-12.6/contrib/ wget https://github.com/pgaudit/pgaudit/archive/refs/heads/REL_12_STABLE.zip unzip REL_12_STABLE.zip make install USE_PGXS=1 PG_CONFIG=/opt/pgsql/bin/pg_config
-
安裝 PG_SQUEEZE
cd /usr/local/src/postgresql-12.6/contrib/ wget https://github.com/cybertec-postgresql/pg_squeeze/archive/refs/heads/master.zip unzip master.zip make install USE_PGXS=1 PG_CONFIG=/opt/pgsql/bin/pg_config
-
-
在所有節點上安裝 Patroni。
yum update –y yum -y install epel-release yum -y install python3 yum install -y python3-devel yum install -y psutils yum install -y gcc yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm yum install python3-psycopg2 pip3 install python-etcd pip3 install patroni
-
在所有節點上安裝和設定 pgBackrest。
-
安裝 Pgbackrest
yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm sudo yum install pgbackrest -y
-
設定所有節點的 Pgbackrest
/etc/pgbackrest.conf [global] repo1-type=s3 repo1-path=/backup repo1-s3-uri-style=path repo1-s3-region=us-ashburn-1 repo1-s3-endpoint=https://xxxxx0011.compat.objectstorage.us-ashburn-1.oraclecloud.com repo1-s3-key=0000000a90d57eddexxxxxa3dc7c4f700000ed2e6 repo1-s3-key-secret=1UhXj69xxxx1e6OyF+00000cccccyyyuuu= repo1-s3-bucket=pg_backup repo1-retention-full=10 log-level-console=info log-level-file=debug log-path=/var/log/pgbackrest/ [stanza-name] pg1-path=/opt/pgsql/data pg1-user=Postgres
-
在所有節點上建立啟動安裝檔案
vi /etc/patroni/boot_pgbackrest.sh #!/ usr / bin /env bash while getopts ": -:" optchar ; do [[ "${ optchar }" == "-" ]] || continue case "${ OPTARG }" in datadir =* ) DATA_DIR =${ OPTARG #*=} ;; scope =* ) SCOPE =${ OPTARG #*=} ;; esac done /bin/pgbackrest --stanza=$SCOPE --link-all restore
-
-
在所有節點上設定 Patroni。
主機名稱 IP 位址 可用性網域 pg-db-01 192.0.2.1 AD1 pg-db-02 192.0.2.2 AD2 pg-db-03 192.0.2.3 AD3 注意:根據需求修改 IP。
mkdir -p /etc/patroni mkdir -p /opt/pgsql/patroni chown postgres:postgres -R /opt/pgsql/patroni chmod 700 /opt/pgsql/patroni vi /etc/patroni/patroni.yml scope:pg-ha-cluster name:pg-db-01 namespace:/opt/pgsql/patroni/ ### restapi: listen: "192.0.2.1:8008" connect_address: "192.0.2.1:8008" ###ETCD Configuration etcd: hosts: "192.0.2.4:2379,192.0.2.5:2379, 192.0.2.6:2379" ###Bootstrap bootstrap: dcs: ttl: 120 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 postgresql: use_pg_rewind: true use_slots: true parameters: archive_command: "pgbackrest --stanza=<stanza-name> archive-push %p" archive_mode: on archive_timeout: 900s log_file_mode: "0640" log_filename: postgresql-%u.log log_rotation_age: 1d log_truncate_on_rotation: "on" logging_collector: "on" max_connections: 2000 max_replication_slots: 10 max_wal_senders: 10 max_wal_size: 5GB max_worker_processes: 40 min_wal_size: 1GB wal_level: "replica" password_encryption: scram-sha-256 superuser_reserved_connections: 200 create_replica_methods: - pgbackrest pgbackrest: command: "/usr/bin/pgbackrest --stanza=<stanza-name> restore --delta --link-all" keep_data: True no_params: True recovery_conf: recovery_target_timeline: latest restore_command: '/usr/bin/pgbackrest --stanza=<stanza-name> archive-get %f %P' method: pgbackrest pgbackrest: command: /etc/patroni/boot_pgbackrest.sh keep_existing_recovery_conf: False recovery_conf: recovery_target_timeline: latest restore_command: '/usr/bin/pgbackrest --stanza=<stanza-name> archive-get %f %P' initdb: - encoding: UTF8 - data-checksums pg_hba: - host replication replicator 127.0.0.1/32 md5 - host replication replicator 192.0.2.1/32 md5 - host replication replicator 192.0.2.2/32 md5 - host replication replicator 192.0.2.3/32 md5 - host all all x.x.x.0/0 md5 users: admin: password: admin options: - createrole - createdb #####Local Postgresql Parameters postgresql: listen: "192.0.2.1:5432" connect_address: "192.0.2.1:5432" data_dir: /opt/pgsql/data pgpass: /opt/pgsql/patroni/pgpass authentication: replication: username: replicator password: password superuser: username: postgres password: password # rewind: # username: replicator # password: password parameters: unix_socket_directories: "/var/run/postgresql, /tmp" ###Any Tags tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
注意:分別變更每個節點的 IP。
chmod 640 /etc/patroni/patroni.yml chown postgres:postgres -R /etc/patroni/patroni.yml
- 在所有節點上建立 Patroni 服務
vi /etc/systemd/system/patroni.service [Unit] Description=Runners to orchestrate a high-availability PostgreSQL - patroni After=syslog.target network.target [Service] Type=simple User=postgres Group=postgres # Read in configuration file if it exists, otherwise proceed EnvironmentFile=-/etc/patroni_env.conf WorkingDirectory=~ # Where to send early-startup messages from the server # This is normally controlled by the global default set by systemd # StandardOutput=syslog
# Pre-commands to start watchdog device # Uncomment if watchdog is part of your patroni setup #ExecStartPre=-/usr/bin/sudo /sbin/modprobe softdog #ExecStartPre=-/usr/bin/sudo /bin/chown postgres /dev/watchdog # Start the patroni process ExecStart=/usr/local/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=60 # Do not restart the service if it crashes, we want to manually inspect database on failure Restart=no [Install] WantedBy=multi-user.target sudo systemctl daemon-reload sudo systemctl enable patroni sudo systemctl start patroni sudo systemctl status patroni
注意:在 Replica 節點上設定 Patroni,但不要啟動服務。
-
執行下列命令,查看 Master 上的 Patroni 叢集狀態。
patronictl -c /etc/patroni/patroni.yml list [root@pg-db-01 ~]# /usr/local/bin/patronictl -c /etc/patroni/patroni.yml list +--------------+-------------+---------+---------+----+-----------+ | Member | Host | Role | State | TL | Lag in MB | + Cluster: pg-ha-cluster (7089354141421597068) --+----+-----------+ | pg-db-01 | 192.0.2.1 | Leader | running | 1 | | +--------------+-------------+---------+---------+----+-----------+
-
建立 Stanza 並完整備份 。
pgbackrest --stanza=<stanza-name> stanza-create pgbackrest --type=full --stanza= pgha --process-max=10 backup pgbackrest info
-
在 Replica 節點上啟動 Patroni,而且應該從 Leader 自動擷取。
sudo systemctl start patroni sudo systemctl status patroni
- 執行下列命令以查看叢集狀態:
patronictl -c /etc/patroni/patroni.yml list
狀態應如下:
[root@pg-db-01 ~]# /usr/local/bin/patronictl -c /etc/patroni/patroni.yml list +--------------+-------------+---------+---------+----+-----------+ | Member | Host | Role | State | TL | Lag in MB | + Cluster: pg-ha-cluster (7089354141421597068) --+----+-----------+ | pg-db-01 | 192.0.2.1 | Leader | running | 2 | | | pg-db-02 | 192.0.2.2 | Replica | running |2 | 0 | | pg-db-03 | 192.0.2.3 | Replica | running | 2 | 0 | +--------------+-------------+---------+---------+----+-----------+
-
最後,請設定 cron 工作以清除日誌、備份等等。
crontab –e #Pgbackrest FULL Backup on Sunday @1AM 00 01 * * 0 postgres pgbackrest --type=full --stanza=ash1-adeprod1-pgcluster --process-max=10 backup &> /dev/null #Pgbackrest INC Backup on Mon-Sat @1AM 00 01 * * 1-6 postgres pgbackrest --type=diff --stanza=ash1-adeprod1-pgcluster --process-max=10 backup &> /dev/null #Delete PostgreSQL logs 08 * * * find /opt/pgsql/log/* -mtime +15 -exec rm {} \; &>/dev/null
其他 Patroni 命令
-
List Members - 清單成員
patronictl -c /etc/patroni/patroni.yml list
-
容錯移轉 / 重新啟動 / 切換
patronictl -c /etc/patroni/patroni.yml failover patronictl -c /etc/patroni/patroni.yml restart patronictl -c /etc/patroni/patroni.yml switchover
-
更新參數
patronictl -c /etc/patroni/patroni.yml edit-config -p log_directory='/opt/pgsql/log/' patronictl -c /etc/patroni/patroni.yml show-config
-
重新載入
patronictl -c /etc/patroni/patroni.yml reload <cluster_name>
相關連結
確認
- 作者:Deepika Nayak、Shreyas Rane、Divya Das
其他學習資源
探索 docs.oracle.com/learn 上的其他實驗室,或存取 Oracle Learning YouTube 通道上的更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。
如需產品文件,請瀏覽 Oracle Help Center 。
Deploy a highly available Postgres cluster on Oracle Cloud Infrastructure
F74179-01
November 2022
Copyright © 2022, Oracle and/or its affiliates.