ich bastele mir gerade ein PostgresSQL mit Master + HotStandby zusammen. Wichtig ist mir dabei, das der Failover mit minimaler Downtime funktioniert, damit man da ab und an am einen oder anderen Knoten mal eine Wartung vornehmen kann.
Der Thread ist dazu da, die Erkenntnisse zu dokumentieren und gerne auch Anregungen zu bekommen.
Ich habe mir bis jetzt pg_rewind angelesen und erfolgreich getestet. Auch die Umschaltung mittels pg_ctl promote klappt einwandfrei. Jetzt heisst es nur noch, das Ganze zu automatisieren.
Zusätzlich habe ich noch eine Cluster-IP konfiguriert, die ich mittels UCARP betreibe. Das nächste Mal mache ich das vielleicht komplett mit Corosync / Pacemaker. Da muss ich mich aber noch etwas mehr mit beschäftigen.
Mein zugrundeliegendes System ist CentOS 7 und die aktuelle Postgres-Version 9.6 aus dem Repository von postgresql.org. Für CentOS 7 gibt's keine UCARP Pakete, aber die Pakete von CentOS 6 funktionieren auch, da UCARP ein eher winziges Stück Software ohne grosse Abhängigkeiten ist. Die systemd-Konfiguration musste ich mir halt selber basteln. Mit Debian ist es einfacher, da ucarp direkt verfügbar und über /etc/network/interfaces konfiguriert werden kann. In der vorhandenen Konfiguration ist die virtuelle IP träge. D. h. dort, wo die IP ist, bleibt sie erst einmal. Keine Umschaltung, wenn ein Knoten nach Abwesenheit wiederkommt.
UCARP-Konfiguration
/etc/ucarp.conf
Code: Alles auswählen
INTERFACE=enp3s0f1
SRCIP=10.200.50.35
VHID=1
PASSWORD=lsdhfsk6sdf
VIP=10.200.50.37
UPSCRIPT=/etc/vip-up.sh
DOWNSCRIPT=/etc/vip-down.sh
Code: Alles auswählen
#!/bin/bash
/sbin/ip addr add dev $1 $2/24
/etc/vip-down.sh
Code: Alles auswählen
#!/bin/bash
/sbin/ip addr del dev $1 $2/24
Code: Alles auswählen
[Unit]
Description=UCARP Virtual IP for Postgres
After=network.service
[Service]
EnvironmentFile=/etc/ucarp.conf
ExecStartPre=/bin/echo /usr/sbin/ucarp --interface=${INTERFACE} --srcip=${SRCIP} --vhid=${VHID} --pass=${PASSWORD} --addr=${VIP} --upscript=${UPSCRIPT} --downscript=${DOWNSCRIPT}
ExecStart=/usr/sbin/ucarp --interface=${INTERFACE} --srcip=${SRCIP} --vhid=${VHID} --pass=${PASSWORD} --addr=${VIP} --upscript=${UPSCRIPT} --downscript=${DOWNSCRIPT}
# "reload" führt zu einer Umschaltung der virtuellen IP auf den anderen Knoten
ExecReload=/bin/kill -SIGUSR2 $MAINPID
# systemd beschwert sich wenn ich ${DOWNSCRIPT} direkt eintrage, weil es nicht mit / beginnt, mit dem Hinweis, dass da ein absoluter Pfad eingetragen werden muss. Deswegen habe ich halt /bin/bash -c davor gesetzt.
ExecStop=/bin/bash -c "${DOWNSCRIPT} ${INTERFACE} ${VIP}"
[Install]
WantedBy=multi-user.target
- Bisherigen Master sanft herunterfahren (Alle Transaktionen sollen sich beenden können. Lang laufende Abfragen werden beendet. Also pg_ctl stop -m smart und nach einer Wartezeit dann pg_ctl stop -m fast)
- iptables Sperren auf auf beide DB-Server so dass nur die Master und Slave via gegenseitig via postgres-Port Kommunizieren können und keine Client-Anfragen rein kommen
- Bisherigen Master wieder hochfahren
- recovery.conf auf dem Master anlegen
- pg_ctl promote auf dem bisherigen Slave durchführen(Wird zum neuen Master)
- Postgres auf dem bisherigen Master herunterfahren
- pg_rewind auf dem bisherigen Master ausführen
- recovery.conf auf dem Master erneut anlegen
- Postgres auf dem bisherigen Master wieder starten. Der Server sollte sofort wieder ein synchronisierter Slave werden
- iptables-Sperren wieder aufheben. Damit ist der Normalzustand wieder hergestellt.