Table des matières
2021/04/03 (Neutriton) : PostgreSQL HA
Présences :
- Liberfix
- Celo
- Hgo
- Tharyrok
Jitsi : https://jitsi.belnet.be/neutriton Caldarium : https://caldarium.be/fr:contact
Météo
Moment informel durant lequel on exprime en peu de mots comment on se sent et si on a une attente forte pour la réunion.
Ce n'est pas un moment de discussion mais d'expression individuelle et ce n'est pas obligatoire
Attente(s) forte(s)
Si l'une ou l'autre personne exprime une attente forte, merci de vous en occuper en priorité ou de la noter dans le hub ou dans un point approprié.
- Pouvoir decider de la solution du ha de psql
Ordre du jour
Resources
Résumé des différents modes de HA: https://www.postgresql.org/docs/13/different-replication-solutions.html#HIGH-AVAILABILITY-MATRIX
Présentation de Patroni
Il faut vraiment voir Patroni comme un framework. Il va utiliser plusieurs pièces.
Etcd : permet à patroni de mettre dans la configuration et faire le quorum. Comme une db clé-valeur mais avec une notion de quorum. C'est simple à utiliser. Patroni supporte d'autres solutions pour gérer le quorum (voir la doc de Patroni). Il en faut trois pour avoir un quorum, mais pas obligé d'avoir trois PostgreSQL.
Debian fournit une commande magique qui boostrap tout pour nous :
- snippet.shell
pg_createconfig_patroni 11 neutrinet
Patroni va communiquer avec la db qu'il gère et etcd. Il communique aussi avec les autres Patroni pour leur dire de synchroniser leurs données.
HAProxy va contacter Patroni pour lui demander qui est le primary et qui sont les replicas. Un des patroni va répondre, et HAProxy va rediriger les requêtes SQL vers la DB en primary.
Si la DB primary est déficiente, alors un des replicas va être élu en primary pour prendre le relais (c'est patroni qui s'occupe d'élire le primary).
Installation de etcd
On commence par etcd, qui est dans les repos debian Bien entendu, on le fait pour les trois serveurs:
- snippet.shell
apt install etcd
On crée un réseau privé pour etcd et patroni. psql-01 → 10.0.0.4 psql-02 → 10.0.0.3 psql-03 → 10.0.0.2
Dans /etc/default/etcd
se trouve la config de etcd.
On donne un nom au cluster (ex : ǹeutrinet
)
- snippet.conf
# nom du serveur ETCD_NAME="psql-0X" # port d'écoute pour d'autres etcd # on doit définir tout ça pour lui dire d'écouter sur localhost ET sur son ip privée ETCD_LISTEN_PEER_URLS="http://10.0.0.4:2380" ETCD_LISTEN_CLIENT_URLS="http://localhost:2379, http://10.50.20.41:2379" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.4:2380" # on définit tous les membres du cluster ETCD_INITIAL_CLUSTER="psql-01=http://10.0.0.4:2380,psql-02=http://10.0.0.3:2380,psql-03=http://10.0.0.2:2380" # si pas de configuration, tu fais quoi ? ben tu crées un nouveau cluster ETCD_INITIAL_CLUSTER_STATE="new" # token utilisé pour initialiser le cluster ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" # clients peuvent savoir combien de clients dans le cluster existent, comme ça le client est capable d'aller sur un autre serveur ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379, http://10.0.0.4:2379"
Quand on parle de client, ce sont les patroni (ce sont eux qui vont parler à etcd).
On supprime la config par défaut de etcd:
- snippet.shell
rm /var/lib/etcd/default
On redémarre les etcd :
- snippet.shell
systemctl restart etcd
Dans cette config, on n'a pas configuré la communication TLS, mais bon c'est qu'une démo
Commandes pour vérifier le statut du cluster:
- cluster-health → doit renvoyer cluster is healthy
- member list → doit renvoyer la liste des serveurs
Dans les logs on va voir quel serveur devient leader. Chaque serveur possède un id unique (on voit à qui correspond l'id avec la commande member list
)
Installation de patroni
- snippet.shell
apt install patroni postgresql-contrib postgresql-client postgresql haproxy
Il faut détruire le cluster db postgresql par défaut. Par défaut, Debian créé un cluster main et le démarre. Donc :
pg_ctlcluster 11 main stop pg_lsclusters pg_dropcluster 11 main
Pour manipuler le cluster, Debian fournit une commande patroni :
pg_createconfig_patroni 11 neutrinet
Patroni a déjà des valeurs par défaut. Par contre, il faut lui dire comment se connecter à etcd.
Patroni peut utiliser soit zookeeper, consul ou etcd pour gérer le quorum du cluster. Patroni peut juste se connecter à son etcd local et apprendre où se trouvent les autres Patroni.
Par défaut, Patroni crée deux utilisateurs : - postgres - replica
Dans /etc/patroni/11-neutrinet.yml
on va modifier les IP publiques par les IP privées du cluster.
pg_hba : définit comment les clients psql peuvent se connecter à la db. En mode tcp, il faut définir un mot de passe. En mode socket, on utilise le système de permissions Unix. Colonne 1: tcp vs socket (host vs local), et puis j'ai plus suivi
On active le cluster puis on redémarre le patroni:
systemctl enable patroni@11-neutrinet systemctl restart patroni@11-neutrinet
Dans les logs, Patroni va fanfaronner que c'est lui le chef en agitant un cadenas: i am the leader with the lock
Et les autres vont dire qu'ils sont secondaires et qu'ils suivent leur chef…
Patroni possède une API REST avec laquelle on va un peu jouer. Notamment, des healtcheck pour savoir qui est le primary ou qui sont les replicas. On peut aussi forcer un primary à devenir replicas, etc.
On doit viser l'url sur l'IP privée (sur localhost ça ne va pas marcher) :
- snippet.shell
curl http://10.0.0.4:8008/patroni | jq .
Pour avoir les infos du cluster:
- snippet.shell
curl http://10.0.0.4:8008/cluster | jq .
Installation de HAProxy
On accélère, de toute façon la config va tenir sur quelques lignes.
On active les metrics prometheus fournies par HAProxy… Enfin si la version est suffisamment récente
Puis on va faire un reverse proxy du port par défaut de psql (5432) vers le port défini dans patroni (ici on met 5442). HAProxy va regarder le endpoint /master
pour savoir qui est le master parmi les trois serveurs. Si le serveur ne répond pas 200 OK, alors HAProxy va considérer que ce serveur n'est pas primary.
On fait pareil pour les replicas, sauf qu'on écoute sur le port 5433 et on regarde le endpoint /replica
.
Dans les logs de HAProxy, on va bien que psql-02 et psql-03 sont considérés DOWN sur /master (code http 503 Service unavailable), et psql-01 est considéré DOWN sur /replica (donc c'est lui le primary).
- Il est plus important d'avoir un monitoring ?
- Quel genre de problème peut-il y avoir quand il n'y a qu'un serveur physique ? (3 psql sur le même serveur) Qu'est-ce que ça apporte de plus à part de la charge sur le serveur ?
- Patroni a l'air simple d'utilisation, les différents niveaux semblent logique.
- Est-ce que Patroni va simplifier les choses ou rajouter de la complexité ? Notamment au niveau de la maintenance…
- Patroni a beaucoup d'options et il y a moyen de tuner des choses. La configuration de base est sans doute suffisante pour Neutrinet.
Raison de la HA : ne pas courir en cas d'incident. Si un des deux Proxmox crash, cela ne doit pas générer de la panique chez Neutrinet. L'autre aspect, ce sont les mises à jour. Sans réplication, on doit couper tous les services pour mettre à jour.
En résumé : On a une VIP gérée par keepalived qui va se coller à une VM encore UP, et le HAProxy va détecter qui est le primary et qui sont les secondary. Mais, si on n'utilise pas le mode read-only, alors on peut virer le HAProxy. Mais alors comment on détecte le primary ? c'est keepalived qui peut tester ça grâce à l'API de patroni.
- snippet.shell
curl -X OPTIONS -I http://10.0.0.3:8008/primary
Patroni simplifie les backups : on peut prendre un replica et le sortir du cluster mais il est tout de même mis à jour. C'est sur celui-là qu'on envoit les backups.
Comparaison avec d'autres outils de PostgreSQL HA
Alternatives sont - PAF (Postgresql Automatic Failover) - repmgr → pas vraiment HA
Patroni est sous licence MIT. PAF a pas vraiment de licence claire…
Personne n'a de connaissance sur PAF, donc on irait plutôt vers Patroni.
On décide d'utiliser Patroni \o/ ./ \°/
Prochaine réunion
Prochain Neutriton (pfsense NAT) : 25/04 à 14h
Lieu : Jitsi et/ou Caldarium
Après ça, on aimerait faire un atelier dans la serre pour installer les VMs. On commencerait avec les sites statics (mediawiki, wikijs).
Météo de fin
Moment informel durant lequel on exprime en peu de mots comment, à titre personnel, la réunion a été vécue que ce soit positif ou négatif. Si une ou plusieurs tension est née durant la réunion, il est peut-être nécessaire d'envisager l'une ou l'autre réunion pour y remédier.