Patroni haproxy architecture

What is Patroni?

Patroni is an open source cluster management tool developed with python that provides a high availability solution for postgresql. It is a very important and useful tool in terms of managing switchover-failover scenarios quite successfully. We will have three postgresql nodes and two haproxy servers, database connections will be established over virtual ip’s directed to the haproxy servers. The architecture is as follows, I will prepare special posts for pgbackrest and percona.

Advantages of Patroni

What is ETCD?

ETCD is used as a distributed configuration store (DCS). It stores the PostgreSQL cluster state. Whenever there is a change in the state of any PostgreSQL node, the boss updates the state change in the etcd key-value store. ETCD uses this information to select the leader node and keeps the cluster up and running. For High Availability it is recommended to install 3 etcd for 3 db servers separately. During installation, custom parameters should be defined in patroni.yaml

Servers:

10.30.10.118 - Node1
10.30.10.119 - Node2
10.30.10.120 - Node3
10.30.10.121 - HAProxy1
10.30.10.122 - HAProxy2

Instalasi etcd dari repository apt / package

root@mylabs-db-01:~# sudo apt-get update
Hit:1 http://id.archive.ubuntu.com/ubuntu jammy InRelease
Get:2 http://id.archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
Hit:3 http://id.archive.ubuntu.com/ubuntu jammy-backports InRelease
Get:4 http://id.archive.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
Get:5 http://id.archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [1,268 kB]
Get:6 http://id.archive.ubuntu.com/ubuntu jammy-updates/restricted amd64 Packages [1,259 kB]
Get:7 http://id.archive.ubuntu.com/ubuntu jammy-updates/restricted Translation-en [205 kB]
Get:8 http://id.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 Packages [1,021 kB]
Get:9 http://id.archive.ubuntu.com/ubuntu jammy-updates/multiverse amd64 Packages [42.1 kB]
Get:10 http://id.archive.ubuntu.com/ubuntu jammy-updates/multiverse Translation-en [10.1 kB]
Get:11 http://id.archive.ubuntu.com/ubuntu jammy-security/main amd64 Packages [1,058 kB]
Get:12 http://id.archive.ubuntu.com/ubuntu jammy-security/main Translation-en [200 kB]
Get:13 http://id.archive.ubuntu.com/ubuntu jammy-security/restricted amd64 Packages [1,237 kB]
Get:14 http://id.archive.ubuntu.com/ubuntu jammy-security/restricted Translation-en [202 kB]
Get:15 http://id.archive.ubuntu.com/ubuntu jammy-security/universe amd64 Packages [824 kB]
Get:16 http://id.archive.ubuntu.com/ubuntu jammy-security/multiverse amd64 Packages [37.1 kB]
Get:17 http://id.archive.ubuntu.com/ubuntu jammy-security/multiverse Translation-en [7,476 B]
Fetched 7,601 kB in 2s (5,025 kB/s)
Reading package lists... Done
root@mylabs-db-01:~#

root@mylabs-db-01:~# apt install etcd
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  etcd-client etcd-server pipexec
The following NEW packages will be installed:
  etcd etcd-client etcd-server pipexec
0 upgraded, 4 newly installed, 0 to remove and 102 not upgraded.
Need to get 10.4 MB of archives.
After this operation, 34.9 MB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://id.archive.ubuntu.com/ubuntu jammy/universe amd64 pipexec amd64 2.5.5-2 [17.5 kB]
Get:2 http://id.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 etcd-server amd64 3.3.25+dfsg-7ubuntu0.22.04.1 [5,843 kB]
Get:3 http://id.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 etcd-client amd64 3.3.25+dfsg-7ubuntu0.22.04.1 [4,575 kB]
Get:4 http://id.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 etcd all 3.3.25+dfsg-7ubuntu0.22.04.1 [2,296 B]
Fetched 10.4 MB in 2s (6,941 kB/s)
Selecting previously unselected package pipexec.
(Reading database ... 109337 files and directories currently installed.)
Preparing to unpack .../pipexec_2.5.5-2_amd64.deb ...
Unpacking pipexec (2.5.5-2) ...
Selecting previously unselected package etcd-server.
Preparing to unpack .../etcd-server_3.3.25+dfsg-7ubuntu0.22.04.1_amd64.deb ...
Unpacking etcd-server (3.3.25+dfsg-7ubuntu0.22.04.1) ...
Selecting previously unselected package etcd-client.
Preparing to unpack .../etcd-client_3.3.25+dfsg-7ubuntu0.22.04.1_amd64.deb ...
Unpacking etcd-client (3.3.25+dfsg-7ubuntu0.22.04.1) ...
Selecting previously unselected package etcd.
Preparing to unpack .../etcd_3.3.25+dfsg-7ubuntu0.22.04.1_all.deb ...
Unpacking etcd (3.3.25+dfsg-7ubuntu0.22.04.1) ...
Setting up pipexec (2.5.5-2) ...
Setting up etcd-client (3.3.25+dfsg-7ubuntu0.22.04.1) ...
Setting up etcd-server (3.3.25+dfsg-7ubuntu0.22.04.1) ...
Adding system user `etcd' (UID 113) ...
Adding new group `etcd' (GID 118) ...
Adding new user `etcd' (UID 113) with group `etcd' ...
Creating home directory `/var/lib/etcd/' ...
Created symlink /etc/systemd/system/etcd2.service → /lib/systemd/system/etcd.service.
Created symlink /etc/systemd/system/multi-user.target.wants/etcd.service → /lib/systemd/system/etcd.service.
Setting up etcd (3.3.25+dfsg-7ubuntu0.22.04.1) ...
Processing triggers for man-db (2.10.2-1) ...
Scanning processes...
Scanning candidates...
Scanning linux images...

Restarting services...
 /etc/needrestart/restart.d/systemd-manager
 systemctl restart cron.service irqbalance.service multipathd.service open-vm-tools.service packagekit.service polkit.service rsyslog.service snapd.service systemd-journald.service systemd-networkd.service systemd-resolved.service systemd-timesyncd.service systemd-udevd.service udisks2.service vgauth.service
Service restarts being deferred:
 systemctl restart ModemManager.service
 /etc/needrestart/restart.d/dbus.service
 systemctl restart networkd-dispatcher.service
 systemctl restart systemd-logind.service
 systemctl restart unattended-upgrades.service
 systemctl restart [email protected]

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.
root@mylabs-db-01:~#
root@mylabs-db-01:~# systemctl status etcd.service
● etcd.service - etcd - highly-available key value store
     Loaded: loaded (/lib/systemd/system/etcd.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2024-01-08 23:40:55 UTC; 32s ago
       Docs: https://etcd.io/docs
             man:etcd
   Main PID: 102660 (etcd)
      Tasks: 9 (limit: 9365)
     Memory: 5.4M
        CPU: 116ms
     CGroup: /system.slice/etcd.service
             └─102660 /usr/bin/etcd

Jan 08 23:40:55 mylabs-db-01 etcd[102660]: 8e9e05c52164694d received MsgVoteResp from 8e9e05c52164694d at term 2
Jan 08 23:40:55 mylabs-db-01 etcd[102660]: 8e9e05c52164694d became leader at term 2
Jan 08 23:40:55 mylabs-db-01 etcd[102660]: raft.node: 8e9e05c52164694d elected leader 8e9e05c52164694d at term 2
Jan 08 23:40:55 mylabs-db-01 etcd[102660]: setting up the initial cluster version to 3.3
Jan 08 23:40:55 mylabs-db-01 etcd[102660]: ready to serve client requests
Jan 08 23:40:55 mylabs-db-01 etcd[102660]: published {Name:mylabs-db-01 ClientURLs:[http://localhost:2379]} to cluster >
Jan 08 23:40:55 mylabs-db-01 systemd[1]: Started etcd - highly-available key value store.
Jan 08 23:40:55 mylabs-db-01 etcd[102660]: serving insecure client requests on 127.0.0.1:2379, this is strongly dis>
Jan 08 23:40:55 mylabs-db-01 etcd[102660]: set the initial cluster version to 3.3
Jan 08 23:40:55 mylabs-db-01 etcd[102660]: enabled capabilities for version 3.3

root@mylabs-db-01:~#
root@mylabs-db-01:~# etcd --version
etcd Version: 3.3.25
Git SHA: Not provided (use ./build instead of go build)
Go Version: go1.18.1
Go OS/Arch: linux/amd64
root@mylabs-db-01:~#

Instalasi etcd dari source

Mendownload binary etcd dari github

root@mylabs-db-01:~# wget -q --show-progress "https://github.com/etcd-io/etcd/releases/download/v3.5.14/etcd-v3.5.14-linux-amd64.tar.gz"
etcd-v3.5.14-linux-amd64.tar.gz                     100%[=============================================================================================================>]  18.49M  27.4MB/s    in 0.7s
root@mylabs-db-01:~# 

Melakukan extract dan copy binary kedalam directory bin, kemudian memberikan permission executable ke file binary dari etcd sebagaimana console berikut:

root@mylabs-db-01:~#  tar zxf etcd-v3.5.14-linux-amd64.tar.gz
root@mylabs-db-01:~# 
root@mylabs-db-01:~#  mv etcd-v3.5.14-linux-amd64/etcd* /usr/bin/
root@mylabs-db-01:~#  chmod +x /usr/bin/etcd*
root@mylabs-db-01:~# 

Membuat directory /etc/etcd dan membuat file etcd untuk menyimpan konfigurasi environment

root@mylabs-db-01:~#  mkdir /etc/etcd
root@mylabs-db-01:~#  nano /etc/etcd/etcd
root@mylabs-db-01:~# 

Membuat user etcd

root@mylabs-db-01:~# groupadd --system etcd
root@mylabs-db-01:~# useradd -s /sbin/nologin --system -g etcd etcd
root@mylabs-db-01:~#

Membuat directory untuk data etcd

root@mylabs-db-01:~# mkdir -p /var/lib/etcd
root@mylabs-db-01:~# chown -R etcd:etcd /var/lib/etcd
root@mylabs-db-01:~# chmod -R 700 /var/lib/etcd

Konfigrasi node-1 pada file /etc/etcd/etcd

ETCD_NAME=etcd1
ETCD_DATA_DIR=/var/lib/etcd
ETCD_LISTEN_CLIENT_URLS=http://10.30.10.118:2379,http://127.0.0.1:2379
ETCD_LISTEN_PEER_URLS=http://10.30.10.118:2380
ETCD_ADVERTISE_CLIENT_URLS=http://10.30.10.118:2379
ETCD_INITIAL_ADVERTISE_PEER_URLS=http://10.30.10.118:2380
ETCD_INITIAL_CLUSTER=etcd1=http://10.30.10.118:2380,etcd2=http://10.30.10.119:2380,etcd3=http://10.30.10.120:2380
ETCD_INITIAL_CLUSTER_STATE=new
ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-xpass
ETCD_ENABLE_V2=true

Konfigrasi node-2 pada file /etc/etcd/etcd

ETCD_NAME=etcd2
ETCD_DATA_DIR=/var/lib/etcd
ETCD_LISTEN_CLIENT_URLS=http://10.30.10.119:2379,http://127.0.0.1:2379
ETCD_LISTEN_PEER_URLS=http://10.30.10.119:2380
ETCD_ADVERTISE_CLIENT_URLS=http://10.30.10.119:2379
ETCD_INITIAL_ADVERTISE_PEER_URLS=http://10.30.10.119:2380
ETCD_INITIAL_CLUSTER=etcd1=http://10.30.10.118:2380,etcd2=http://10.30.10.119:2380,etcd3=http://10.30.10.120:2380
ETCD_INITIAL_CLUSTER_STATE=new
ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-xpass
ETCD_ENABLE_V2=true

Konfigrasi node-3 pada file /etc/etcd/etcd

ETCD_NAME=etcd3
ETCD_DATA_DIR=/var/lib/etcd
ETCD_LISTEN_CLIENT_URLS=http://10.30.10.120:2379,http://127.0.0.1:2379
ETCD_LISTEN_PEER_URLS=http://10.30.10.120:2380
ETCD_ADVERTISE_CLIENT_URLS=http://10.30.10.120:2379
ETCD_INITIAL_ADVERTISE_PEER_URLS=http://10.30.10.120:2380
ETCD_INITIAL_CLUSTER=etcd1=http://10.30.10.118:2380,etcd2=http://10.30.10.119:2380,etcd3=http://10.30.10.120:2380
ETCD_INITIAL_CLUSTER_STATE=new
ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-xpass
ETCD_ENABLE_V2=true

Menyalakan service etcd

# cat /etc/systemd/system/etcd.service

[Unit]
Description=etcd - highly-available key value store
Documentation=https://etcd.io/docs
Documentation=man:etcd
After=network.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=/etc/etcd/etcd
ExecStart=/usr/bin/etcd
Restart=on-failure
RestartSec=5
Type=notify
User=etcd
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
Alias=etcd2.service

Mereload daemon systemctl, mensetting enable pada restart dan menyalakan services

root@mylabs-db-01:~# systemctl daemon-reload
root@mylabs-db-01:~# systemctl enable etcd
root@mylabs-db-01:~# systemctl start etcd

Melakukan pengecekan kesehatan

root@mylabs-db-01:~# etcdctl --cluster=true endpoint health
http://10.30.10.120:2379 is healthy: successfully committed proposal: took = 2.034444ms
http://10.30.10.119:2379 is healthy: successfully committed proposal: took = 2.056611ms
http://10.30.10.118:2379 is healthy: successfully committed proposal: took = 1.858091ms
root@mylabs-db-01:~#

Melakukan pengecekan cluster etcd

root@mylabs-db-01:~# ENDPOINTS=10.30.10.118:2379,10.30.10.119:2379,10.30.10.120:2379
root@mylabs-db-01:~# etcdctl endpoint status --write-out=table --endpoints=$ENDPOINTS
+-------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|     ENDPOINT      |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+-------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| 10.30.10.118:2379 | d422b005b01747ce |   3.5.0 |   20 kB |     false |      false |         3 |         19 |                 19 |        |
| 10.30.10.119:2379 | 3f2ffd9d700ef386 |   3.5.0 |   20 kB |     false |      false |         3 |         19 |                 19 |        |
| 10.30.10.120:2379 | e91ce6ea3bacdd72 |   3.5.0 |   20 kB |      true |      false |         3 |         19 |                 19 |        |
+-------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
root@mylabs-db-01:~#

Instalasi database postgresql

root@mylabs-db-01:~# apt-get install postgresql postgresql-contrib -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
  etcd-client etcd-server libflashrom1 libftdi1-2 pipexec
...
...
...
No VM guests are running outdated hypervisor (qemu) binaries on this host.
root@mylabs-db-01:~#
root@mylabs-db-01:~# systemctl stop postgresql
root@mylabs-db-01:~# systemctl disable postgresql
root@mylabs-db-01:~# mv /var/lib/postgresql/14/main{,-bck}
root@mylabs-db-01:~#

Lakukan pada node 2 dan node 3 juga

Instalasi pgbackrest

root@mylabs-db-01:~# apt install pgbackrest
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
  etcd-client etcd-server libflashrom1 libftdi1-2 pipexec
Use 'sudo apt autoremove' to remove them.
Suggested packages:
  pgbackrest-doc check-pgbackrest
The following NEW packages will be installed:
  pgbackrest
0 upgraded, 1 newly installed, 0 to remove and 4 not upgraded.
Need to get 426 kB of archives.
After this operation, 1,095 kB of additional disk space will be used.
Get:1 http://id.archive.ubuntu.com/ubuntu jammy/universe amd64 pgbackrest amd64 2.37-1 [426 kB]
Fetched 426 kB in 1s (490 kB/s)
Selecting previously unselected package pgbackrest.
(Reading database ... 118909 files and directories currently installed.)
Preparing to unpack .../pgbackrest_2.37-1_amd64.deb ...
Unpacking pgbackrest (2.37-1) ...
Setting up pgbackrest (2.37-1) ...
Processing triggers for man-db (2.10.2-1) ...
Scanning processes...
Scanning linux images...

Running kernel seems to be up-to-date.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.
root@mylabs-db-01:~#

Patroni Installation

root@mylabs-db-01:~# apt-get install python3-pip python3-dev libpq-dev -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
  etcd-client etcd-server libflashrom1 libftdi1-2 pipexec
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  build-essential bzip2 cpp cpp-11 dpkg-dev fakeroot fontconfig-config fonts-dejavu-core g++ g++-11 gcc gcc-11 gcc-11-base javascript-common libalgorithm-diff-perl libalgorithm-diff-xs-perl
  libalgorithm-merge-perl libasan6 libatomic1 libc-dev-bin libc-devtools libc6-dev libcc1-0 libcrypt-dev libdeflate0 libdpkg-perl libexpat1-dev libfakeroot libfile-fcntllock-perl libfontconfig1
  libgcc-11-dev libgd3 libgomp1 libisl23 libitm1 libjbig0 libjpeg-turbo8 libjpeg8 libjs-jquery libjs-sphinxdoc libjs-underscore liblsan0 libmpc3 libnsl-dev libpython3-dev libpython3.10-dev
  libquadmath0 libssl-dev libstdc++-11-dev libtiff5 libtirpc-dev libtsan0 libubsan1 libwebp7 libxpm4 linux-libc-dev lto-disabled-list make manpages-dev python3-wheel python3.10-dev rpcsvc-proto
  zlib1g-dev
....
....
....
Processing triggers for man-db (2.10.2-1) ...
Processing triggers for libc-bin (2.35-0ubuntu3.5) ...
Scanning processes...
Scanning linux images...

Running kernel seems to be up-to-date.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.
root@mylabs-db-01:~#

Melakukan upgrade pip

root@mylabs-db-01:~# pip3 install --upgrade pip
Requirement already satisfied: pip in /usr/lib/python3/dist-packages (22.0.2)
Collecting pip
  Downloading pip-23.3.2-py3-none-any.whl (2.1 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 13.3 MB/s eta 0:00:00
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 22.0.2
    Not uninstalling pip at /usr/lib/python3/dist-packages, outside environment /usr
    Can't uninstall 'pip'. No files were found to uninstall.
Successfully installed pip-23.3.2
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

Menginstall patroni dengan pip

root@mylabs-db-01:~# pip install patroni
Collecting patroni
  Downloading patroni-3.2.1-py3-none-any.whl.metadata (11 kB)
Requirement already satisfied: urllib3!=1.21,>=1.19.1 in /usr/lib/python3/dist-packages (from patroni) (1.26.5)
Requirement already satisfied: PyYAML in /usr/lib/python3/dist-packages (from patroni) (5.4.1)
Requirement already satisfied: click>=4.1 in /usr/lib/python3/dist-packages (from patroni) (8.0.3)
Collecting prettytable>=0.7 (from patroni)
  Downloading prettytable-3.9.0-py3-none-any.whl.metadata (26 kB)
Collecting python-dateutil (from patroni)
  Downloading python_dateutil-2.8.2-py2.py3-none-any.whl (247 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 247.7/247.7 kB 5.0 MB/s eta 0:00:00
Collecting psutil>=2.0.0 (from patroni)
  Downloading psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (21 kB)
Collecting ydiff>=1.2.0 (from patroni)
  Downloading ydiff-1.2.tar.gz (42 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 42.8/42.8 kB 5.3 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
Collecting wcwidth (from prettytable>=0.7->patroni)
  Downloading wcwidth-0.2.13-py2.py3-none-any.whl.metadata (14 kB)
Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil->patroni) (1.16.0)
Downloading patroni-3.2.1-py3-none-any.whl (317 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 317.3/317.3 kB 13.3 MB/s eta 0:00:00
Downloading prettytable-3.9.0-py3-none-any.whl (27 kB)
Downloading psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (285 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 285.5/285.5 kB 32.7 MB/s eta 0:00:00
Downloading wcwidth-0.2.13-py2.py3-none-any.whl (34 kB)
Building wheels for collected packages: ydiff
  Building wheel for ydiff (setup.py) ... done
  Created wheel for ydiff: filename=ydiff-1.2-py3-none-any.whl size=16646 sha256=98bf570701624a3544d39c8d2ab3fc6059f337ceeb8c96bf4b413175506e4546
  Stored in directory: /root/.cache/pip/wheels/90/7e/61/6522f5bd67c80b8327ade6945c29042b6cd077a2683b8dd47c
Successfully built ydiff
Installing collected packages: ydiff, wcwidth, python-dateutil, psutil, prettytable, patroni
Successfully installed patroni-3.2.1 prettytable-3.9.0 psutil-5.9.7 python-dateutil-2.8.2 wcwidth-0.2.13 ydiff-1.2
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
root@ocp-db-01:~#
root@ocp-db-01:~# pip install python-etcd pip install psycopg2
Collecting python-etcd
  Downloading python-etcd-0.4.5.tar.gz (37 kB)
  Preparing metadata (setup.py) ... done
Requirement already satisfied: pip in /usr/local/lib/python3.10/dist-packages (23.3.2)
Collecting install
  Downloading install-1.3.5-py3-none-any.whl (3.2 kB)
Collecting psycopg2
  Downloading psycopg2-2.9.9.tar.gz (384 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 384.9/384.9 kB 7.2 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
Collecting dnspython>=1.13.0 (from python-etcd)
  Downloading dnspython-2.4.2-py3-none-any.whl.metadata (4.9 kB)
Requirement already satisfied: urllib3>=1.7.1 in /usr/lib/python3/dist-packages (from python-etcd) (1.26.5)
Downloading dnspython-2.4.2-py3-none-any.whl (300 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 300.4/300.4 kB 24.8 MB/s eta 0:00:00
Building wheels for collected packages: python-etcd, psycopg2
  Building wheel for python-etcd (setup.py) ... done
  Created wheel for python-etcd: filename=python_etcd-0.4.5-py3-none-any.whl size=38501 sha256=c0d89a209f3df05efde9b87d3c4d77d56ac13d5b68ecd4924dbad37e40512d4c
  Stored in directory: /root/.cache/pip/wheels/93/5f/1b/056db07a0ab1c0b7efe175928d2a10b614e0e00d7bab0b6496
  Building wheel for psycopg2 (setup.py) ... done
  Created wheel for psycopg2: filename=psycopg2-2.9.9-cp310-cp310-linux_x86_64.whl size=499025 sha256=57f3718037ae73352f3f85486fba93effe22e5f809d7c42303225991cd48ecf4
  Stored in directory: /root/.cache/pip/wheels/7d/75/13/da1c6d88687ae81bf5e3cfa07d702981ba137963163472b050
Successfully built python-etcd psycopg2
Installing collected packages: psycopg2, install, dnspython, python-etcd
Successfully installed dnspython-2.4.2 install-1.3.5 psycopg2-2.9.9 python-etcd-0.4.5
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
root@mylabs-db-01:~#
root@mylabs-db-01:~# pip install python-etcd pip install psycopg2
Collecting python-etcd
  Downloading python-etcd-0.4.5.tar.gz (37 kB)
  Preparing metadata (setup.py) ... done
Requirement already satisfied: pip in /usr/local/lib/python3.10/dist-packages (23.3.2)
Collecting install
  Downloading install-1.3.5-py3-none-any.whl (3.2 kB)
Collecting psycopg2
  Downloading psycopg2-2.9.9.tar.gz (384 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 384.9/384.9 kB 7.2 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
Collecting dnspython>=1.13.0 (from python-etcd)
  Downloading dnspython-2.4.2-py3-none-any.whl.metadata (4.9 kB)
Requirement already satisfied: urllib3>=1.7.1 in /usr/lib/python3/dist-packages (from python-etcd) (1.26.5)
Downloading dnspython-2.4.2-py3-none-any.whl (300 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 300.4/300.4 kB 24.8 MB/s eta 0:00:00
Building wheels for collected packages: python-etcd, psycopg2
  Building wheel for python-etcd (setup.py) ... done
  Created wheel for python-etcd: filename=python_etcd-0.4.5-py3-none-any.whl size=38501 sha256=c0d89a209f3df05efde9b87d3c4d77d56ac13d5b68ecd4924dbad37e40512d4c
  Stored in directory: /root/.cache/pip/wheels/93/5f/1b/056db07a0ab1c0b7efe175928d2a10b614e0e00d7bab0b6496
  Building wheel for psycopg2 (setup.py) ... done
  Created wheel for psycopg2: filename=psycopg2-2.9.9-cp310-cp310-linux_x86_64.whl size=499025 sha256=57f3718037ae73352f3f85486fba93effe22e5f809d7c42303225991cd48ecf4
  Stored in directory: /root/.cache/pip/wheels/7d/75/13/da1c6d88687ae81bf5e3cfa07d702981ba137963163472b050
Successfully built python-etcd psycopg2
Installing collected packages: psycopg2, install, dnspython, python-etcd
Successfully installed dnspython-2.4.2 install-1.3.5 psycopg2-2.9.9 python-etcd-0.4.5
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
root@mylabs-db-01:~#
root@mylabs-db-01:~# mkdir /etc/patroni
root@mylabs-db-01:~# NAMESPACE="my_xlab"
root@mylabs-db-01:~# SCOPE="cluster_1"
root@mylabs-db-01:~# export NODE_NAME=`hostname -f`
root@mylabs-db-01:~# export NODE_IP=`hostname -i | awk '{print $1}'`
root@mylabs-db-01:~# DATA_DIR="/var/lib/postgresql/14/main"
root@mylabs-db-01:~# PG_BIN_DIR="/usr/lib/postgresql/14/bin"
root@mylabs-db-01:~# echo "
namespace: ${NAMESPACE}
scope: ${SCOPE}
name: ${NODE_NAME}

restapi:
    listen: 0.0.0.0:8008
    connect_address: ${NODE_IP}:8008

etcd:
    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

  # Additional script to be launched after initial cluster creation (will be passed the connection URL as parameter)
# post_init: /usr/local/bin/setup_cluster.sh
  # Some additional users users which needs to be created after initializing new cluster
  users:
      admin:
          password: M4s0kB0sQu^_&
          options:
              - createrole
              - createdb
      admins:
          password: M4s0kB0sQu^_&
          options:
              - createrole
              - createdb 

postgresql:
    cluster_name: cluster_1
    listen: 0.0.0.0:5432
    connect_address: ${NODE_IP}:5432
    data_dir: ${DATADIR}
    bin_dir: ${PG_BIN_DIR}
    pgpass: /tmp/pgpass
    authentication:
        replication:
            username: replicator
            password: repsM4s0kB0sQu^_&
        superuser:
            username: postgres
            password: P0sM4s0kB0sQu^_&
    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


root@mylabs-db-01:~#
root@mylabs-db-01:~# cat /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=/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=30

# Do not restart the service if it crashes, we want to manually inspect database on failure
Restart=no

[Install]
WantedBy=multi-user.target
root@mylabs-db-01:~#

Start service patroni pada node 01 s.d 03

root@mylabs-db-01:~# systemctl start patroni
root@mylabs-db-01:~# systemctl enable patroni
Created symlink /etc/systemd/system/multi-user.target.wants/patroni.service → /etc/systemd/system/patroni.service.
root@mylabs-db-01:~# systemctl status patroni

Pengecekan status database

root@mylabs-db-01:~# patronictl -c /etc/patroni/patroni.yml list $SCOPE
+ Cluster: cluster_1 (7322051624797784337) ------+----+-----------+
| Member    | Host         | Role    | State     | TL | Lag in MB |
+-----------+--------------+---------+-----------+----+-----------+
| ocp-db-01 | 10.30.10.118 | Leader  | running   |  1 |           |
| ocp-db-02 | 10.30.10.119 | Replica | streaming |  1 |         0 |
| ocp-db-03 | 10.30.10.120 | Replica | streaming |  1 |         0 |
+-----------+--------------+---------+-----------+----+-----------+
root@mylabs-db-01:~#

Instalasi Haproxy

root@mylabs-db-01:~# apt install haproxy
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  liblua5.3-0
Suggested packages:
  vim-haproxy haproxy-doc
The following NEW packages will be installed:
  haproxy liblua5.3-0
0 upgraded, 2 newly installed, 0 to remove and 102 not upgraded.
Need to get 1,788 kB of archives.
After this operation, 4,210 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://id.archive.ubuntu.com/ubuntu jammy/main amd64 liblua5.3-0 amd64 5.3.6-1build1 [140 kB]
...
...
No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.
root@mylabs-db-01:~#
root@ocp-db-haproxy:~# mv /etc/haproxy/haproxy.cfg{,-bck}
root@ocp-db-haproxy:~#
root@ocp-db-haproxy:~# nano /etc/haproxy/haproxy.cfg
root@ocp-db-haproxy:~#

Konfigurasi haproxy

root@ocp-db-haproxy:~# cat /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
    mode http
    bind *:7000
    stats enable
    stats uri /

listen primary
    bind *:5432
    option httpchk OPTIONS /master
    http-check expect status 200
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    server node1 ocp-db-01:5432 maxconn 100 check port 8008
    server node2 ocp-db-02:5432 maxconn 100 check port 8008
    server node3 ocp-db-03:5432 maxconn 100 check port 8008

listen standbys
    balance roundrobin
    bind *:5433
    option httpchk OPTIONS /replica
    http-check expect status 200
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    server node1 ocp-db-01:5432 maxconn 100 check port 8008
    server node2 ocp-db-02:5432 maxconn 100 check port 8008
    server node3 ocp-db-03:5432 maxconn 100 check port 8008
root@ocp-db-haproxy:~#

Tampilan statistik Haproxy

Switchover

root@mylabs-db-01:~# patronictl -c /etc/patroni/patroni.yml switchover
Current cluster topology
+ Cluster: cluster_1 (7322051624797784337) ------+----+-----------+
| Member       | Host         | Role    | State     | TL | Lag in MB |
+--------------+--------------+---------+-----------+----+-----------+
| mylabs-db-01 | 10.30.10.118 | Leader  | running   |  1 |           |
| mylabs-db-02 | 10.30.10.119 | Replica | streaming |  1 |         0 |
| mylabs-db-03 | 10.30.10.120 | Replica | streaming |  1 |         0 |
+--------------+--------------+---------+-----------+----+-----------+
Primary [mylabs-db-01]:
Candidate ['mylabs-db-01', 'mylabs-db-03'] []: mylabs-db-01
When should the switchover take place (e.g. 2024-01-09T13:42 )  [now]: now
Are you sure you want to switchover cluster cluster_1, demoting current leader mylabs-db-01? [y/N]: y
2024-01-09 12:42:48.82044 Successfully switched over to "mylabs-db-02"
+ Cluster: cluster_1 (7322051624797784337) ------+----+-----------+
| Member       | Host         | Role    | State     | TL | Lag in MB |
+--------------+--------------+---------+-----------+----+-----------+
| mylabs-db-01 | 10.30.10.118 | Replica | stopped   |    |   unknown |
| mylabs-db-02 | 10.30.10.119 | Leader  | running   |  1 |           |
| mylabs-db-03 | 10.30.10.120 | Replica | streaming |  1 |         0 |
+--------------+--------------+---------+-----------+----+-----------+
root@mylabs-db-01:~#

Pengecekan Cluster database

root@mylabs-db-03:~# patronictl -c /etc/patroni/patroni.yml list
+ Cluster: cluster_1 (7322051624797784337) ------+----+-----------+
| Member       | Host         | Role    | State     | TL | Lag in MB |
+--------------+--------------+---------+-----------+----+-----------+
| mylabs-db-01 | 10.30.10.118 | Replica | streaming |  2 |         0 |
| mylabs-db-02 | 10.30.10.119 | Leader  | running   |  2 |           |
| mylabs-db-03 | 10.30.10.120 | Replica | streaming |  2 |         0 |
+--------------+--------------+---------+-----------+----+-----------+
root@mylabs-db-03:~#

Keepalived Installation

With the Keepalived installation, you will be able to connect to the proxy server via virtual ip

[root@haproxy ~]# dnf install -y keepalived
[root@haproxy ~]# cd /etc/keepalived

The following lines are added and edited in the keepalived conf file. If more than one proxy server is to be used, these changes should be made to the others as well. Two proxy nodes were used in this setup

Keepalived services are started for both nodes[root@haproxy keepalived]# systemctl start keepalived
[root@haproxy keepalived]# systemctl enable keepalived

[root@haproxy keepalived]# vi keepalived.conf
global_defs {
}
vrrp_script chk_haproxy {
script "/usr/bin/killall -0 haproxy" # widely used idiom
interval 2 # check every 2 seconds
weight 2 # add 2 points of prio if OK
}
vrrp_instance VI_1 {
interface enp0s3
state MASTER # or "BACKUP" on backup
priority 101 # 101 on master, 100 on backup
virtual_router_id 51
authentication {
auth_type PASS
auth_pass Xtr54sdD
}
virtual_ipaddress {
192.168.1.30
}
unicast_src_ip 192.168.1.28 # This haproxy node
unicast_peer {
192.168.1.29 # Other haproxy nodes
}
track_script {
chk_haproxy
}
}

https://docs.percona.com/postgresql/14/solutions/ha-setup-apt.html#next-steps
https://www.techsupportpk.com/2022/01/set-up-highly-available-postgresql13-cluster-ubuntu.html
https://www.alibabacloud.com/blog/how-to-set-up-a-highly-available-postgresql-cluster-using-patroni-on-ubuntu-16-04_594477
https://snapshooter.com/learn/postgresql/postgresql-cluster-patroni
https://www.percona.com/blog/pgbackrest-restoration-scenarios/

Leave a Reply

Your email address will not be published. Required fields are marked *