Démo interne
ioguix
listen prod
bind *:5432
server srv1 srv1:5434
server srv2 srv2:5434
server srv3 srv3:5434
listen stdby
bind *:5433
server srv1 srv1:5434
server srv2 srv2:5434
server srv3 srv3:5434
cat<<'EOF' > /etc/systemd/system/pgsql-state@.service
[Unit]
Description=Local PostgreSQL state
[Service]
User=postgres
ExecStart=/usr/pgsql-12/bin/psql -p 5434 -Atc \
"SELECT CASE WHEN pg_is_in_recovery() THEN 'standby' \
ELSE 'production' END"
StandardOutput=socket
EOF
systemctl --now enable pgsql-state.socket
Test simpliste depuis l’un des serveurs:
Tests de défaillance autour de pgsql-state
:
# socket arrêté
srv2:~# nc --recv-only srv3 5431
Ncat: Connection refused.
# PostgreSQL arrêté
srv2:~# nc --recv-only srv3 5431
psql: error: could not connect to server: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5434"?
listen prod
bind *:5432
option tcp-check
tcp-check connect port 5431
tcp-check expect string production
default-server inter 2s fastinter 1s rise 2 fall 1 on-marked-down shutdown-sessions
server srv1 srv1:5434 check
server srv2 srv2:5434 check
server srv3 srv3:5434 check
inter 2s
: vérifie toutes les 2sfastinter 1s
: toutes les secondes en période de transitionrise 2
: deux check valides pour devenir accessiblefall 1
: inaccessible dès le premier check échouéon-marked-down shutdown-sessions
: déconnecte tous les clients si le backend devient inaccessiblelisten stdby
bind *:5433
balance leastconn
option tcp-check
tcp-check connect port 5431
tcp-check expect string standby
default-server inter 2s fastinter 1s rise 2 fall 1 on-marked-down shutdown-sessions
server srv1 srv1:5434 check
server srv2 srv2:5434 check
server srv3 srv3:5434 check
Récapitulons en image pour eg. le pool prod
.
Jamais plus d’une instance est désignée comme primaire…vraiment ?
default-server [...] rise 2 fall 1 [...]
Mais pas suffisant:
race condition possible entre deux health check
un standby pourrait s’auto-repliquer !
solution (comme avec une vIP):
local replication all reject
host replication all $NODENAME reject
host replication all 127.0.0.1/32 reject
host replication all ::1/128 reject
listen stats
mode http
bind *:7000
stats enable
stats uri /
timeout connect 15s
timeout client 15s
timeout server 15s
Configuration:
global
stats socket ipv4@*:9999
stats socket /var/lib/haproxy/stats
Utilisation:
3nodes-vip
par 3nodes-haproxy
pgsql-state
ouvert à tous
failed
check-pgsql
intégré
portblock