Et PAF, ça bascule!
Stefan Fercot
26 juin 2018
Qui suis-je?
Stefan Fercot
aka. pgstef
utilise PostgreSQL depuis 2010
dans la communauté depuis 2016
@dalibo depuis 2017
PostgreSQL et la réplication en flux
système robuste et performant
sécurité des données
pas de service hautement disponible
PostgreSQL bénéficie aujourd’hui d’un système de réplication en flux robuste et performant. Bien que cela assure une très bonne sécurité en terme de perte de données, cela ne rend pas le service PostgreSQL hautement disponible pour autant.
Bascule automatique - complexité
comment détecter une vraie défaillance ?
le maître ne répond plus ?
est-il vraiment éteint ?
est-il vraiment inactif ?
comment réagir à une panne réseau ?
comment éviter les split brain ?
Pacemaker
est LA référence de la HA sous Linux
est un “Cluster Resource Manager”
supporte les fencing, quorum et watchdog
s’interface avec n’importe quel service
multi-service, avec dépendances, ordre, contraintes, règles, etc
chaque service a son Resource Agent
Et PAF dans tout ça?
garder Pacemaker: il fait tout et bien à notre place
se concentrer sur notre métier: PostgreSQL
PAF est un Resource Agent utilisé par Pacemaker
Installation
La documentation fourni plusieurs guides d’installation rapide: http://clusterlabs.github.io/PAF/documentation.html
Prérequis
2 nœuds ou plus
PostgreSQL installé
réplication fonctionnelle
template recovery.conf.pcmk
standby_mode = on
primary_conninfo = 'host=ha-vip application_name=hostname'
recovery_target_timeline = 'latest'
Pour cette démo, 3 machines virtuelles ont été créées avec qemu-kvm.
Il s’agit de 3 serveurs sous CentOS 7 (hanode1, hanode2, hanode3).
PostgreSQL 10 y a été installé via les paquets du PGDG.
# yum install -y https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm
# yum install -y postgresql10-server
# firewall-cmd --permanent --add-service=high-availability
# firewall-cmd --permanent --add-service=postgresql
# firewall-cmd --reload
Création des templates:
# cat ~postgres/recovery.conf.pcmk
standby_mode = on
primary_conninfo = 'host=ha-vip application_name=hanode1'
recovery_target_timeline = 'latest'
# chown postgres:postgres ~postgres/recovery.conf.pcmk
# chmod 700 ~postgres/recovery.conf.pcmk
Initialisation du primaire:
# /usr/pgsql-10/bin/postgresql-10-setup initdb
# echo "listen_addresses = '*'" >> /var/lib/pgsql/10/data/postgresql.conf
# echo "host replication all all trust" >> /var/lib/pgsql/10/data/pg_hba.conf
# systemctl start postgresql-10.service
Création des secondaires:
# pg_basebackup -h hanode1 -D /var/lib/pgsql/10/data -R
# chown -R postgres:postgres /var/lib/pgsql/10/data/
# systemctl start postgresql-10.service
Dès lors que la réplication est fonctionnelle, arrêter proprement les services PostgreSQL:
# systemctl stop postgresql-10.service
Remarque: il faut également interdire à chaque nœud de se répliquer lui-même.
[root@hanode1 ~]# cat /var/lib/pgsql/10/data/pg_hba.conf |grep reject
host replication all hanode1 reject
Installer Pacemaker et PAF
yum install -y pacemaker resource-agents pcs
yum install -y fence-agents-all fence-agents-virsh
yum install -y resource-agents-paf
systemctl disable corosync
systemctl disable pacemaker
Le paquet resource-agents-paf
est disponible directement dans le dépôt PGDG.
Il est recommandé de désactiver Pacemaker et Corosync au démarrage du serveur. Cela permet à l’administrateur de s’assurer de l’état du nœud avant de le réintégrer au cluster suite à un incident.
L’outil pcs
fonctionne désormais très bien sur les distributions Debian récentes.
Authentifier chaque nœud à l’aide de l’outil d’administration pcs
systemctl enable pcsd
systemctl start pcsd
passwd hacluster
pcs cluster auth hanode1 hanode2 hanode3 -u hacluster
Le daemon pcsd
s’occupe de propager les configurations et commandes sur tous les nœuds.
L’outil pcs
se sert de l’utilisateur système hacluster
pour s’authentifier auprès de pcsd. Puisque les commandes de gestion du cluster peuvent être exécutées depuis n’importe quel membre du cluster, il est recommandé de configurer le même mot de passe pour cet utilisateur sur tous les nœuds pour éviter les confusions.
Créer le cluster
pcs cluster setup --name cluster_pgsql hanode1 hanode2 hanode3
pcs cluster start --all
pcs resource defaults migration-threshold=3
pcs resource defaults resource-stickiness=10
État du cluster - 1
Fencing
chaque brique doit toujours être dans un état déterminé
garantie de pouvoir sortir du système un élément défaillant
implémenté dans Pacemaker au travers du daemon stonithd
Lorsqu’un serveur n’est plus accessible au sein d’un cluster, il est impossible aux autres nœuds de déterminer l’état réel de ce dernier:
a-t-il crashé ?
est-ce un problème réseau ?
subit-il une forte charge temporaire ?
Le seul moyen de répondre à ces questions est d’éteindre ou d’isoler le serveur. Cette action permet de déterminer de façon certaine son statut.
Passer outre ce mécanisme, c’est s’exposer de façon certaine à des situations de split brain
où deux instances PostgreSQL sont accessibles en écriture au sein du cluster, mais ne répliquent pas entre elles. Réconcilier les données entre ces deux instances peut devenir un véritable calvaire et provoquer une ou plusieurs indisponibilités.
Configuration du fencing
Une ressource de fencing pour chaque nœud
pcs stonith create fence_vm_hanode1 fence_virsh \
pcmk_host_check="static-list" pcmk_host_list="hanode1" \
ipaddr="192.168.122.1" login="root" port="hanode1" \
action="reboot" identity_file="/root/.ssh/id_rsa"
Une contrainte d’exclusion pour chacune de ces ressources
pcs constraint location fence_vm_hanode1 avoids hanode1=INFINITY
Création d’une ressource de fencing pour chaque nœud. Ici spécifique à la technologie de virtualisation utilisée pour la démo.
Ajout ensuite de contraintes d’exclusion pour que chaque STONITH évite le nœud dont il est responsable.
# pcs cluster cib cluster1.xml
# pcs -f cluster1.xml stonith create fence_vm_hanode1 fence_virsh \
pcmk_host_check="static-list" pcmk_host_list="hanode1" \
ipaddr="192.168.122.1" login="root" port="hanode1" \
action="reboot" identity_file="/root/.ssh/id_rsa"
# pcs -f cluster1.xml stonith create fence_vm_hanode2 fence_virsh \
pcmk_host_check="static-list" pcmk_host_list="hanode2" \
ipaddr="192.168.122.1" login="root" port="hanode2" \
action="reboot" identity_file="/root/.ssh/id_rsa"
# pcs -f cluster1.xml stonith create fence_vm_hanode3 fence_virsh \
pcmk_host_check="static-list" pcmk_host_list="hanode3" \
ipaddr="192.168.122.1" login="root" port="hanode3" \
action="reboot" identity_file="/root/.ssh/id_rsa"
# pcs -f cluster1.xml constraint location fence_vm_hanode1 avoids hanode1=INFINITY
# pcs -f cluster1.xml constraint location fence_vm_hanode2 avoids hanode2=INFINITY
# pcs -f cluster1.xml constraint location fence_vm_hanode3 avoids hanode3=INFINITY
# pcs cluster cib-push cluster1.xml
État du cluster - 2
Création des ressources PostgreSQL - 1
pgsqld
propriétés de l’instance PostgreSQL
pcs resource create pgsqld ocf:heartbeat:pgsqlms \
bindir=/usr/pgsql-10/bin pgdata=/var/lib/pgsql/10/data \
recovery_template=/var/lib/pgsql/recovery.conf.pcmk \
op start timeout=60s \
op stop timeout=60s \
op promote timeout=30s \
op demote timeout=120s \
op monitor interval=15s timeout=10s role="Master" \
op monitor interval=16s timeout=10s role="Slave" \
op notify timeout=60s
PostgreSQL ne disposant pas de demote à chaud, le timeout demote correspond à stop + start.
État du cluster - 3
Création des ressources PostgreSQL - 2
pgsql-ha
clone la ressource pgsqld
sur l’ensemble des nœuds du cluster
décide où est promue l’instance primaire,…
pcs resource master pgsql-ha pgsqld notify=true
État du cluster - 4
Création des ressources PostgreSQL - 3
pgsql-master-ip
contrôle l’IP virtuelle ha-vip (192.168.122.110)
doit être démarrée sur le nœud hébergeant la ressource maître
pcs resource create pgsql-master-ip ocf:heartbeat:IPaddr2 \
ip=192.168.122.110 cidr_netmask=24 \
op monitor interval=10s
pcs constraint colocation add pgsql-master-ip \
with master pgsql-ha INFINITY
L’utilisation d’une IP virtuelle n’est pas obligatoire. Il s’agit toutefois de la méthode la plus couramment employée.
D’autres technologies plus ou moins complexes à mettre en œuvre existent pour permettre de rediriger les connexions vers l’instance maître.
Ajout de contraintes d’ordre
l’IP virtuelle doit rester fonctionnelle sur le maître pendant le demote
l’IP virtuelle ne doit être démarrée sur le nouveau maître qu’après promote
L’ordre de start/stop et promote/demote doit donc être asymétrique.
pcs constraint order promote pgsql-ha \
then start pgsql-master-ip symmetrical=false kind=Mandatory
pcs constraint order demote pgsql-ha \
then stop pgsql-master-ip symmetrical=false kind=Mandatory
État du cluster - 5
Validation - 1
Cluster name: cluster_pgsql
Stack: corosync
Current DC: hanode2 (version 1.1.16-12.el7_4.8-94ff4df)
- partition with quorum
Last updated: ...
Last change: ... by root via crm_attribute on hanode1
3 nodes configured
7 resources configured
Online: [ hanode1 hanode2 hanode3 ]
...
Validation - 2
...
Full list of resources:
fence_vm_hanode1 (stonith:fence_virsh): Started hanode2
fence_vm_hanode2 (stonith:fence_virsh): Started hanode1
fence_vm_hanode3 (stonith:fence_virsh): Started hanode1
Master/Slave Set: pgsql-ha [pgsqld]
Masters: [ hanode1 ]
Slaves: [ hanode2 hanode3 ]
pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1
Vérification
$ psql -h ha-vip
postgres=# SELECT application_name, client_addr, state, sync_state
FROM pg_stat_replication;
application_name | client_addr | state | sync_state
------------------+-----------------+-----------+------------
hanode3 | 192.168.122.113 | streaming | async
hanode2 | 192.168.122.112 | streaming | async
(2 rows)
postgres=# SELECT pg_is_in_recovery();
pg_is_in_recovery
-------------------
f
(1 row)
Afficher les ressources
Master/Slave Set: pgsql-ha [pgsqld]
Masters: [ hanode1 ]
Slaves: [ hanode2 hanode3 ]
pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1
Stop
pcs resource disable pgsql-ha
pcs cluster stop --all
Start
pcs cluster start --all
pcs resource enable pgsql-ha
Exclure un nœud du cluster
pcs resource ban --wait pgsql-ha hanode2
pcs resource clear pgsql-ha hanode2
Forcer le déplacement d’une ressource
pcs resource move --wait --master pgsql-ha hanode1
pcs resource clear pgsql-ha
Failover 1 - démo
kill -9 des processus postgres
Your browser does not support the video tag.
Failover 1 - explications
Failover 2 - démo
Suppression du fichier /var/lib/pgsql/10/data/global/pg_control
Your browser does not support the video tag.
Failover 2 - explications
PAF détecte une erreur car il vérifie toujours la cohérence entre l’état du cluster et ce qui est écrit dans le fichier pg_control.
L’erreur remontée est ici : “Could not read all datas from controldata file”.
Failover 3 - démo
echo c > /proc/sysrq-trigger
Your browser does not support the video tag.
Failover 3 - explications
Switchover - démo
Your browser does not support the video tag.
Switchover - explications
hanode2 : demote de pgsql-ha
et arrêt de pgsql-master-ip
hanode1 : promotion de PostgreSQL
Promotion de hanode1
Démarrage de la vip sur hanode1
PAF va prendre le temps de s’assurer que le nouveau maître a bien reçu toutes les transactions afin que l’ancien maître puisse être raccroché en nouveau standby.
Conclusion
RPO (“recovery point objective”): Streaming Replication
RTO (“recovery time objective”) : bascule automatique
La bascule automatique apporte de la complexité.
En avez-vous vraiment besoin?
Des questions ?