Atelier: Haute Disponibilité avec Patroni
Atelier: Haute Disponibilité avec Patroni
18.06
Dalibo & Contributors
http://dalibo.com/formations
Workshop Patroni
TITRE : Haute disponibilité de service ‐ Patroni
SOUS‐TITRE : Workshop Patroni
REVISION: 18.06
LICENCE: PostgreSQL
Table des Matières
1 Haute disponibilité de service avec Patroni 6
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2 Principes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.1 DCS : Etcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.2 Service PostgreSQL et Patroni . . . . . . . . . . . . . . . . . . . . . 7
1.3 Mise en place de l'infrastructure . . . . . . . . . . . . . . . . . . . . . . 8
1.3.1 Connexion à votre machine virtuelle . . . . . . . . . . . . . . . . . . 8
1.3.2 Playbook Ansible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.3 Installation d'Etcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.3.1 Installation des paquets . . . . . . . . . . . . . . . . . . . . 11
1.3.3.2 Configuration du service Etcd . . . . . . . . . . . . . . . . 12
1.3.3.3 Démarrage du service . . . . . . . . . . . . . . . . . . . . . 13
1.3.4 Installation de PostgreSQL / Patroni . . . . . . . . . . . . . . . . . . 15
1.3.4.1 Configuration de Patroni . . . . . . . . . . . . . . . . . . . 15
1.3.4.2 Création de l'agrégat . . . . . . . . . . . . . . . . . . . . . 16
1.4 Création d'incidents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.4.1 Perte totale du DCS . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.4.2 Perte du nœud primaire Patroni . . . . . . . . . . . . . . . . . . . . 19
1.5 Modification de la configuration . . . . . . . . . . . . . . . . . . . . . . 21
1.6 Sauvegardes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.6.1 Détermination du primaire . . . . . . . . . . . . . . . . . . . . . . . 23
1.6.2 Configuration de pgBackrest . . . . . . . . . . . . . . . . . . . . . . 24
1.6.2.1 Configuration de l'archivage . . . . . . . . . . . . . . . . . 24
1.6.2.2 Configuration sur la machine hébergeant les sauvegardes . 25
1.7 Références . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5
Haute disponibilité de service ‐ Patroni
Figure 1: PostgreSQL
1.1 INTRODUCTION
• Principes
• Mise en place
• Installation et configuration des services
• Construction d'un agrégat à bascule automatique
• Création d'incidents
6
1.2 Principes
1.2 PRINCIPES
• Arbitrage par un quorum : DCS Etcd
• Service PostgreSQL : désactivé
• Contrôle complet par Patroni
Le service PostgreSQL doit être désactivé pour ne pas se lancer au démarrage, le contrôle
total de l'instance est délégué à Patroni :
$ for node in pg-1 pg-2 pg-3; do
sudo systemctl disable --now postgresql
sudo systemctl status postgresql
done
Vous disposez d'une machine virtuelle dédiée dans laquelle nous construirons 7 con‐
teneurs lxc :
• 3 Etcd
• 3 Patroni
• 1 backup optionnel : (sauvegardes, archivage)
# .ssh/config
Host vm38
Hostname eformation.dalibo.com
User dalibo
port 2238
$ ssh vm38
8
1.3 Mise en place de l'infrastructure
Fichier Description
Le script warmup.sh permet de précharger une image debian pour accélérer la création
des autres conteneurs :
$ sudo ./warmup.sh
Vous pouvez suivre l'évolution de la création des conteneurs dans un autre terminal :
$ watch -n 1 sudo lxc-ls -f
$ sudo lxc-ls -f
NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED
backup STOPPED 0 - - - false
e1 STOPPED 0 - - - false
e2 STOPPED 0 - - - false
e3 STOPPED 0 - - - false
pg-1 STOPPED 0 - - - false
pg-2 STOPPED 0 - - - false
pg-3 STOPPED 0 - - - false
L'état final de chaque conteneur étant RUNNING avec une adresse IPV4 attribuée :
$ sudo lxc-ls -f
NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED
backup RUNNING 0 - 10.0.3.204 - false
http://dalibo.com/formations 9
Haute disponibilité de service ‐ Patroni
Sur tous les conteneurs, le fichier /etc/hosts est automatiquement renseigné par le play‐
book et devrait contenir au moins :
10.0.3.101 e1
10.0.3.102 e2
10.0.3.103 e3
10.0.3.201 pg-1
10.0.3.202 pg-2
10.0.3.203 pg-3
10.0.3.204 backup
10
1.3 Mise en place de l'infrastructure
• Paquets essentiels :
– etcd
– curl
– jq
– iputils‐ping
$ for node in e1 e2 e3; do
sudo ssh $node sudo apt install etcd curl iputils-ping jq
done
Active: active (running) since Wed 2021-11-10 17:48:26 UTC; 3min 28s ago
Active: active (running) since Wed 2021-11-10 17:48:36 UTC; 3min 18s ago
Active: active (running) since Wed 2021-11-10 17:48:46 UTC; 3min 8s ago
1.3.3.1.1 Vérification
Les nœuds sont tous des leaders indépendants, ce qui ne nous intéresse pas. Il faut donc
les configurer pour qu'ils fonctionnent en agrégat.
Active: inactive (dead) since Wed 2021-11-10 17:59:35 UTC; 2min 46s ago
Active: inactive (dead) since Wed 2021-11-10 17:59:35 UTC; 2min 46s ago
Active: inactive (dead) since Wed 2021-11-10 17:59:35 UTC; 2min 46s ago
• Fichier : /etc/default/etcd
Sur le nœud e1 :
ETCD_NAME='e1'
ETCD_DATA_DIR='/var/lib/etcd/default'
ETCD_LISTEN_PEER_URLS='http://127.0.0.1:2380,http://10.0.3.101:2380'
ETCD_LISTEN_CLIENT_URLS='http://127.0.0.1:2379,http://10.0.3.101:2379'
ETCD_INITIAL_ADVERTISE_PEER_URLS='http://10.0.3.101:2380'
ETCD_INITIAL_CLUSTER_STATE='new'
ETCD_INITIAL_CLUSTER_TOKEN='etcd-cluster'
ETCD_INITIAL_CLUSTER+='e1=http://10.0.3.101:2380'
ETCD_INITIAL_CLUSTER+='e2=http://10.0.3.102:2380'
ETCD_INITIAL_CLUSTER+='e3=http://10.0.3.103:2380'
ETCD_ADVERTISE_CLIENT_URLS+='http://10.0.3.101:2379'
ETCD_ADVERTISE_CLIENT_URLS+='http://10.0.3.102:2379'
ETCD_ADVERTISE_CLIENT_URLS+='http://10.0.3.103:2379'
Sur le nœud e2 :
ETCD_NAME='e2'
12
1.3 Mise en place de l'infrastructure
ETCD_DATA_DIR='/var/lib/etcd/default'
ETCD_LISTEN_PEER_URLS='http://127.0.0.1:2380,http://10.0.3.102:2380'
ETCD_LISTEN_CLIENT_URLS='http://127.0.0.1:2379,http://10.0.3.102:2379'
ETCD_INITIAL_ADVERTISE_PEER_URLS='http://10.0.3.102:2380'
ETCD_INITIAL_CLUSTER_STATE='new'
ETCD_INITIAL_CLUSTER_TOKEN='etcd-cluster'
ETCD_INITIAL_CLUSTER+='e1=http://10.0.3.101:2380'
ETCD_INITIAL_CLUSTER+='e2=http://10.0.3.102:2380'
ETCD_INITIAL_CLUSTER+='e3=http://10.0.3.103:2380'
ETCD_ADVERTISE_CLIENT_URLS+='http://10.0.3.101:2379'
ETCD_ADVERTISE_CLIENT_URLS+='http://10.0.3.102:2379'
ETCD_ADVERTISE_CLIENT_URLS+='http://10.0.3.103:2379'
Sur le nœud e3 :
ETCD_NAME='e3'
ETCD_DATA_DIR='/var/lib/etcd/default'
ETCD_LISTEN_PEER_URLS='http://127.0.0.1:2380,http://10.0.3.103:2380'
ETCD_LISTEN_CLIENT_URLS='http://127.0.0.1:2379,http://10.0.3.103:2379'
ETCD_INITIAL_ADVERTISE_PEER_URLS='http://10.0.3.103:2380'
ETCD_INITIAL_CLUSTER_STATE='new'
ETCD_INITIAL_CLUSTER_TOKEN='etcd-cluster'
ETCD_INITIAL_CLUSTER+='e1=http://10.0.3.101:2380'
ETCD_INITIAL_CLUSTER+='e2=http://10.0.3.102:2380'
ETCD_INITIAL_CLUSTER+='e3=http://10.0.3.103:2380'
ETCD_ADVERTISE_CLIENT_URLS+='http://10.0.3.101:2379'
ETCD_ADVERTISE_CLIENT_URLS+='http://10.0.3.102:2379'
ETCD_ADVERTISE_CLIENT_URLS+='http://10.0.3.103:2379'
Avant de démarrer le service sur chaque nœud, il faut réinitialiser les répertoires de don‐
nées des nœuds, afin qu'ils reparte sur un répertoire neuf.
Le nœud e1, que nous considérons comme premier leader sera démarré en premier :
$ for node in e1 e2 e3; do
echo "$node :" ; sudo ssh $node "rm -rf ~etcd/default/member"
done
sur e1 :
736293150f1cffb7: name=e1 peerURLs=http://10.0.3.101:2380
clientURLs=http://10.0.3.101:2379,http://10.0.3.102:2379,http://10.0.3.103:2379
isLeader=true
7ef9d5bb55cefbcc: name=e3 peerURLs=http://10.0.3.103:2380
clientURLs=http://10.0.3.101:2379,http://10.0.3.102:2379,http://10.0.3.103:2379
isLeader=false
97463691c7858a7b: name=e2 peerURLs=http://10.0.3.102:2380
clientURLs=http://10.0.3.101:2379,http://10.0.3.102:2379,http://10.0.3.103:2379
isLeader=false
sur e2 :
736293150f1cffb7: name=e1 peerURLs=http://10.0.3.101:2380
clientURLs=http://10.0.3.101:2379,http://10.0.3.102:2379,http://10.0.3.103:2379
isLeader=true
7ef9d5bb55cefbcc: name=e3 peerURLs=http://10.0.3.103:2380
clientURLs=http://10.0.3.101:2379,http://10.0.3.102:2379,http://10.0.3.103:2379
isLeader=false
97463691c7858a7b: name=e2 peerURLs=http://10.0.3.102:2380
clientURLs=http://10.0.3.101:2379,http://10.0.3.102:2379,http://10.0.3.103:2379
isLeader=false
sur e3 :
736293150f1cffb7: name=e1 peerURLs=http://10.0.3.101:2380
clientURLs=http://10.0.3.101:2379,http://10.0.3.102:2379,http://10.0.3.103:2379
isLeader=true
14
1.3 Mise en place de l'infrastructure
• Installation
– PostgreSQL
– Patroni
– pgBackrest
Le dépôt pgdg est déjà préconfiguré dans les conteneurs pg‐1, pg‐2 et pg‐3, l'installation
est donc triviale :
$ for node in pg-1 pg-2 pg-3; do
sudo ssh $node "apt-get update && apt-get install -y postgresql patroni pgbackrest"
done
Vérification :
$ for node in pg-1 pg-2 pg-3; do sudo ssh $node "dpkg -l postgresql patroni
pgbackrest | grep ^ii | cut -d ' ' -f 1,3"; done
ii patroni
ii pgbackrest
ii postgresql
ii patroni
ii pgbackrest
ii postgresql
ii patroni
ii pgbackrest
ii postgresql
Le service PostgreSQL doit êtrre désactivé car la gestion totale de l'instance sera déléguée
à Patroni :
$ for node in pg-1 pg-2 pg-3; do
sudo ssh $node "systemctl disable --now postgresql@14-main"
done
http://dalibo.com/formations 15
Haute disponibilité de service ‐ Patroni
# /etc/patroni/dcs.yml
etcd:
hosts: e1:2379, e2:2379, e3:2379
• Démarrage du primaire
• Création de l'utilisateur de réplication
• Suppression des instances secondaires
• Démarrage des instances secondaires
La création de l'agrégat commence par la mise en route du primaire sur le nœud pg-1,
c'est lui qui sera la référence pour les secondaires.
L'utilisateur permettant la mise en réplication doit être créé sur ce nœud, avec le mot de
passe renseigné dans la configuration de Patroni :
$ sudo ssh pg-1 "sudo -iu postgres psql -c \"create user replicator replication
password 'rep-pass'\" "
16
1.3 Mise en place de l'infrastructure
Les instances secondaires ont été initialisées lors de l'installation du paquet Debian, il faut
donc vider leur répertoire de données :.
1.3.4.2.5 Vérifications
export PATRONICTL_CONFIG_FILE=/etc/patroni/14-main.yml
Master [pg-1]:
Candidate ['pg-2', 'pg-3'] []: pg-2
When should the switchover take place (e.g. 2021-11-12T12:21 ) [now]:
Current cluster topology
+ Cluster: 14-main (7029596050496494965) -+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+--------+------------+---------+---------+----+-----------+
| pg-1 | 10.0.3.201 | Leader | running | 3 | |
| pg-2 | 10.0.3.202 | Replica | running | 3 | 0 |
| pg-3 | 10.0.3.203 | Replica | running | 3 | 0 |
+--------+------------+---------+---------+----+-----------+
Are you sure you want to switchover cluster 14-main, demoting current master
pg-1? [y/N]: y
2021-11-12 11:21:20.08091 Successfully switched over to "pg-2"
+ Cluster: 14-main (7029596050496494965) -+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+--------+------------+---------+---------+----+-----------+
| pg-1 | 10.0.3.201 | Replica | stopped | | unknown |
| pg-2 | 10.0.3.202 | Leader | running | 3 | |
| pg-3 | 10.0.3.203 | Replica | running | 3 | 0 |
+--------+------------+---------+---------+----+-----------+
pg-1 :
pg_is_in_recovery
-------------------
t
(1 ligne)
pg-2 :
pg_is_in_recovery
-------------------
t
(1 ligne)
pg-3 :
pg_is_in_recovery
-------------------
t
(1 ligne)
Nous constatons que l'intégralité des nœuds est passée en lecture seule (stand‐by).
Dans un autre terminal, nous observons l'état de l'agrégat sur le nœud pg-2 :
Nous observons la disparition de pg-1 de la liste des nœuds et une bascule automatique
se déclenche vers un des nœuds secondaires disponibles :
http://dalibo.com/formations 19
Haute disponibilité de service ‐ Patroni
Pour un retour à l'état nominal, il suffit de procéder à une bascule manuelle (adapter la
commande si votre primaire n'est pas pg-3) :
postgres@pg-1:~$ patronictl switchover --master pg-3 --candidate pg-1 --force
20
1.5 Modification de la configuration
L'un des avantages de bénéficier d'une configuration distribuée est qu'il est possible de
modifier cette configuration pour tous les nœuds en une seule opération.
Si la modification nécessite un redémarrage, l' drapeau pending restart sera positionné sur
toutes les instances et attendrons une action de votre part pour l'effectuer.
loop_wait: 10
maximum_lag_on_failover: 1048576
postgresql:
parameters:
max_connections: 123
...
patronictl edit-config
---
+++
@@ -1,7 +1,8 @@
loop_wait: 10
maximum_lag_on_failover: 1048576
postgresql:
- parameters: null
+ parameters:
+ max_connections: 123
pg_hba:
- local all all peer
- host all all 127.0.0.1/32 md5
pg-1 :
max_connections
-----------------
123
(1 ligne)
22
1.6 Sauvegardes
pg-2 :
max_connections
-----------------
123
(1 ligne)
pg-3 :
max_connections
-----------------
123
(1 ligne)
1.6 SAUVEGARDES
• Installation pgBackrest
• Configuration
• Détermination du primaire
• Archivage
• Sauvegarde
Nous proposons de déclencher la sauvegarde sur le primaire courant, il faut donc d'abord
l'identifier.
Le script suivant est une solution permettant de récupérer le primaire de notre agrégat à
partir d'un nœud Etcd ezt de l'API mise à disposition :
#! /bin/bash
SCOPE=$(grep -i scope: /etc/patroni/14-main.yml | cut -d '"' -f 2)
curl -s http://e1:2379/v2/keys/postgresql-common/"$SCOPE"/leader | jq -r .node.value
http://dalibo.com/formations 23
Haute disponibilité de service ‐ Patroni
[global]
log-level-file=detail
log-level-console=detail
repo1-host=backup
repo1-host-user=postgres
Tous les nœuds doivent permettre la connexion ssh sans mot de passe, le playbook Ansible
nommé exchange_ssh_keys permet de faire ce travail rapidement :
$ sudo ansible-playbook -i inventory.yml exchange_ssh_keys.yml -f 7
Toutes les instances doivent être en mesure d'archiver leurs journaux de transactions au
moyen de pgBackrest :
postgres@pg-1:~$ patronictl edit-config
postgresql:
parameters:
max_connections: 123
archive_mode: 'on'
archive_command: pgbackrest --stanza=main archive-push %p
Notre configuration n'a pas encore été appliquée sur les instances car un redémarrage est
requis :
postgres@pg-1:~$ patronictl list -e
Sur la machine backup, créer le script de détermination du leader (le rendre exécutable) :
postgres@backup:~$ vim ~/leader.sh && chmod +x leader.sh
#! /bin/bash
SCOPE='14-main'
curl -s http://e1:2379/v2/keys/postgresql-common/"$SCOPE"/leader | jq -r .node.value
[global]
repo1-path=/var/lib/pgbackrest
repo1-retention-full=2
start-fast=y
log-level-console=detail
[main]
pg1-path=/var/lib/postgresql/14/main
pg1-host-user=postgres
pg1-user=postgres
pg1-port=5432
stanza: main
status: ok
cipher: none
db (current)
wal archive min/max (14): 000000010000000000000001/00000008000000000000000B
1.7 RÉFÉRENCES
• Etcd : https://etcd.io/docs/
• Patroni : https://patroni.readthedocs.io/en/latest/
• Dalibo : https://dalibo.com
http://dalibo.com/formations 27
NOTES
NOTES
NOS AUTRES PUBLICATIONS
FORMATIONS
• DBA1 : Administra on PostgreSQL
https://dali.bo/dba1
LIVRES BLANCS
• Migrer d’Oracle à PostgreSQL
• Industrialiser PostgreSQL
TÉLÉCHARGEMENT GRATUIT
Les versions électroniques de nos publica ons sont disponibles gratuitement sous licence
open-source ou sous licence Crea ve Commons. Contactez-nous à l’adresse contact@
dalibo.com pour plus d’informa on.
DALIBO, L’EXPERTISE POSTGRESQL
Depuis 2005, DALIBO met à la disposi on de ses clients son savoir-faire dans le domaine
des bases de données et propose des services de conseil, de forma on et de support aux
entreprises et aux ins tu onnels.