We will install and configure HAProxy & Keepalived
HAProxy does not need SSL certificates – traffic is pure TCP passthrough.
TLS terminates on PostgreSQL, not on HAProxy.
ETCD uses full TLS, so all etcdctl commands must use--cacert, --cert, --key
The following installation will be carried out on HAProxy nodes (192.168.204.11 haproxy01 & 192.168.204.12 haproxy02)
Install HAProxy on both servers
sudo su
apt update
apt -y install haproxy
nano /etc/haproxy/haproxy.cfg
Paste the following config at the end of haproxy.cfg (the same on both nodes):
frontend postgres_frontend
bind *:5432 #HAProxy listens on port 5432.
timeout client 30s
mode tcp
option tcplog
default_backend postgres_backend
backend postgres_backend
mode tcp
option httpchk GET /primary # patroni provides an endpoint to check node roles
http-check expect status 200 # expect 200 for the primary node
#It checks Patroni REST API on port 8008 (/primary) to identify the leader. Only the leader node receives traffic.
server postgres01 192.168.204.16:5432 check port 8008
server postgres02 192.168.204.17:5432 check port 8008
server postgres03 192.168.204.18:5432 check port 8008
HAProxy listens to the request on port 5432 and checks the primary backend node and then forwards the request to its primary backend node. It checks the backend nodes' health by using port 8008.
Check HAProxy config whether it is valid and reload the service
haproxy -c -f /etc/haproxy/haproxy.cfg # validate first
systemctl reload haproxy
systemctl enable haproxy
Install KeepAlived on both servers:
apt update
apt install keepalived -y
nano /etc/keepalived/keepalived.conf
Node 1 (haproxy01 – 192.168.204.11)
global_defs {
enable_script_security
script_user keepalived_script
}
vrrp_script check_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 2
fall 3
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 34Istanb
}
virtual_ipaddress {
192.168.204.10
}
track_script {
check_haproxy
}
}
Node 2 (haproxy02 – 192.168.204.12)
global_defs {
enable_script_security
script_user keepalived_script
}
vrrp_script check_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 2
fall 3
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface ens33 # update with your nic
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 34Istanb # change
}
virtual_ipaddress {
192.168.204.10
}
track_script {
check_haproxy
}
}
Create a check script on each node. This script will check if HAProxy is up or down. If down keepalived consider its node as down and will not get requests.
#!/bin/bash
PORT=5432
# Check if HAProxy process is running
if ! pidof haproxy > /dev/null; then
echo "HAProxy process is not running"
exit 1
fi
# Check if HAProxy is listening on 5432
if ! ss -ltn | grep -q ":${PORT}"; then
echo "HAProxy is not listening on port ${PORT}"
exit 2
fi
exit 0
We need to add a user to execute these scripts. Set ownerships and permissions. Restart keepalived.
useradd -r -s /bin/false keepalived_script
chmod +x /etc/keepalived/check_haproxy.sh
chown keepalived_script:keepalived_script /etc/keepalived/check_haproxy.sh
chmod 700 /etc/keepalived/check_haproxy.sh
systemctl restart keepalived
journalctl -u keepalived -f
Journalctl command above will show the nodes' keepalived status (MASTER or BACKUP). Also we should be able to ping 192.168.204.10 (Virtual IP) at this moment. We can stop the haproxy service on Node1 and check if the service moves to node2 without problems.
systemctl stop haproxy
Node2 successfully takes the MASTER role

To add our Postgres cluster to PGAdmin, Right click Servers > Register > Server.
We add Virtual IP as the host address. The password is the one that we defined in /etc/patroni/config.yml file.

Make sure SSL mode is selected as require

