wiki/HowtoPatroni.md

224 lines
9.2 KiB
Markdown
Raw Permalink Normal View History

2022-08-10 17:45:48 +02:00
---
title: Howto Patroni
categories: databases
...
* Documentation : <https://patroni.readthedocs.io/en/latest/>
* Dépôt Github : <https://github.com/zalando/patroni>
[Patroni](https://github.com/zalando/patroni) est un outil qui permet de créer votre propre système de haute disponibilité, utilisant Python, et sappuyant sur un stockage distribué comme etcd, Zookeeper, Consul ou Kubernetes.
Cela permet aux administrateurs de base de données, de déployer des clusters PostgreSQL de manière simple et rapide.
**ATTENTION : Documentation en cours d'écriture !**
# Installation
2024-02-05 10:34:17 +01:00
En Debian 12 la version de Patroni est la 3.0.2, on installe simplement le paquet `patroni` :
2022-08-10 17:45:48 +02:00
~~~
# apt install patroni
~~~
2024-02-05 10:34:17 +01:00
Attention : la syntaxe de configuration à pas mal changer entre les versions 2.x et 3.x !
2022-08-10 17:45:48 +02:00
# Configuration
La syntaxe de la configuration de Patroni est en Yaml.
Le paquet Debian installe une configuration de base dans `/etc/patroni/config.yml.in` et dans `/etc/patroni/dcs.yml` mais nous préférons créer notre propre fichier de configuration dans `/etc/patroni/config-patroni.yml`
Voici un exemple de configuration dans `/etc/patroni/config-patroni.yml` :
~~~
scope: cluster-foo
name: cluster-foo1
restapi:
listen: 10.0.0.1:8008
connect_address: 10.0.0.1:8008
etcd:
hosts: 10.0.0.1:2379,10.0.0.2:2379,10.0.0.3:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
hot_standby: "on"
wal_keep_segment: 8
max_wal_senders: 5
max_relication_slots: 5
checkpoint_timeout: 30
initdb:
- encoding: UTF8
- data-checksums
pg_hba:
- host replication repl 127.0.0.1/32 md5
- host replication repl 10.0.0.1/0 md5
- host replication repl 10.0.0.2/0 md5
- host replication repl 10.0.0.3/0 md5
- host all all 0.0.0.0/0 md5
users:
admin:
password: passforadmin
options:
- createrole
- createdb
repl:
password: passforrepl
options:
- replication
postgresql:
listen: 10.0.0.1:5432
connect_address: 10.0.0.1:5432
bin_dir: /usr/lib/postgresql/13/bin/
data_dir: /home/cluster-foo1
pgpass: /tmp/cluster-foo1-pgpass
authentication:
replication:
username: repl
password: passforrepl
superuser:
username: admin
password: passforadmin
parameters:
unix_socket_directories: '/tmp'
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
~~~
La configuration se découpe en plusieurs parties que nous allons décrire.
- `restapi` : configuration de l'API REST de Patroni
- `listen` : IP et port d'écoute de l'API REST
- `connect_address` : IP et port de connexion à l'API REST
- `etcd` : Configuration des noeuds etcd ( peut être remplacer par consul)
- `hosts` : liste des hôtes etcd
- `bootstrap` : Défini les paramètres qui vont amorcer l'instance PostgreSQL
- `maximum_lag_on_failover` : Taille maximale, en octet, pour que le secondaire soit éligible a l'élection pour pouvori être leader.
- `ttl` : Défini le TTL du verrouillage du leader, en secondes, à considéré comme le temps avant que le processus de bascule soit déclenché.
- `loop_wait` : Temps d'attente de la boucle de rafraîchissement de l'état de cluster, en secondes.
- `initdb` : Liste des options qui peuvent être passé à l'initdb :
- `data-checksums` : doit être activé si l'on veux utilisé `pg_rewind`
- `encoding: UTF8` : encodage par défaut des bases
- ` locale: UTF8:` : locale par défaut pour les nouvelles bases de données.
- `pg_hba` : liste les autorisations que l'on veux ajouté dans le fichier `pg_hba.conf`
- `users` : Défini les utilisateurs qui sont créer à l'initialisation du cluster
- `options` : listes les droits de chaque utilisateurs lors de la déclaration du `CREATE ROLE`
- `postgresql` : Défini les options passé à PostgreSQL
- `listen` : IP et port d'écoute de PostgreSQL
- `connect_address` : IP et port sur lequel PostgreSQL est accessible
- `bin_dir` : chemin où les binaires de PostgreSQL sont accessible
- `data_dir` : chemin du datadir de PostgreSQL
- `pgpass` : chemin du .pgpass
- `authentication` : défini les rôles de chaque utilisateur qui peuvent s'authentifié sur le cluster
- `parameters` : liste des paramètres de configuration de PostgreSQL
- `tags` : Défini des `tags` sur le cluster
- `nofailover` : contrôle si ce nœud est autorisé a devenir leader
- `noloadbalance` : Si c'est défini sur `true`, le nœud renverra un code HTTP 503 pour la vérification de l'API REST sur GET /replica, il sera donc exclu de l'équilibrage de charge
- `clonefrom` : Si c'est défini sur `true`, d'autres nœuds peuvent préférer utiliser ce nœud pour l'amorçage (pg_basebackup). S'il y a plusieurs nœuds avec la balise clonefrom définie sur true, le nœud à partir duquel amorcer sera choisi au hasard.
- `nosync` : S'il est défini sur `true`, le nœud ne sera jamais sélectionné en tant que réplique synchrone.
Il faut également mettre en place un unité systemd dans `/etc/systemd/system/patroni.service` comme celle-ci par exemple :
~~~
[Unit]
Description=Runners to orchestrate a high-availability PostgreSQL
After=syslog.target network.target
[Service]
Type=simple
User=postgres
Group=postgres
ExecStart=/usr/bin/patroni /etc/patroni/config.yml
KillMode=process
TimeoutSec=30
Restart=no
[Install]
WantedBy=multi-user.targ
~~~
Puis on recharge la configuration de systemd et on démarre patroni sur chaque nœud :
~~~
# systemctl daemon-reload
# systemctl start patroni.service
~~~
A ce stade Patroni va lancer PostgreSQL, on peux regarder s'il a des erreurs dans `/var/log/syslog`
On peux vérifié l'état du cluster, sur un des noeuds, avec la commande suivante :
~~~
# patronictl -c /etc/patroni/config.yml list
+ Cluster: cluster (7120522414311271133) -------+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+-----------------+----------------+---------+---------+----+-----------+
| cluster1 | 10.0.0.1 | Replica | running | 1 | 0 |
| cluster2 | 10.0.0.2 | Replica | running | 1 | 0 |
| cluster3 | 10.0.0.3 | Leader | running | 1 | |
+-----------------+----------------+---------+---------+----+-----------+
~~~
## Fonctionnement de l'initialisation du cluster
Lors du premier démarrage de Patroni sur les machines du cluster, Patroni va contacter etcd et définir le leader, en général c'est l'instance qui répond en premier.
Sur les Replica, Patroni va lancer un `pg_basebackup` depuis le replica vers le leader pour copier l'instance PostgreSQL et la redémarré en mode recovery.
C'est identique a ce qu'on fait lorsque on initialise une [Streaming Réplication](https://wiki.evolix.org/HowtoPostgreSQL/ReplicationPhysique#synchronisation-initiale-des-donn%C3%A9es-m%C3%A9thode-courante)
## Fonctionnement du délai de bascule HA
Patroni effectue de temps en temps ce que nous appelons un cycle HA.
À chaque cycle HA, il se charge d'effectuer une série de vérifications sur le cluster pour déterminer son état de santé et, en fonction de l'état, il peut prendre des mesures, comme le basculement vers un serveur de réplica.
Ce comportement se configure dans la partie `dcs:` de la configuration :
~~~
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
~~~
`loop_wait` détermine combien de temps, en secondes, Patroni effectue un nouveau cycle de vérifications HA.
`retry_timeout` définit le délai d'attente pour les opérations de nouvelle tentative sur le DCS et sur Postgres. Par exemple : si le DCS ne répond pas pendant plus de `retry_timeout` secondes, Patroni peut rétrograder le nœud principal (Leader) en tant qu'action de sécurité.
`ttl` définit la durée du bail sur le verrou leader dans le DCS. Si le leader actuel du cluster n'est pas en mesure de renouveler le bail pendant ses cycles HA pour une durée supérieure à ttl, alors le bail expirera et cela déclenchera une bascule du leader dans le cluster.
On peut donc modifier les variables `loop_wait`, `retry_timeout` et `ttl`, pour réduire le temps de bascule d'un leader en cas de l'indisponibilité d'un nœud.
Il faut toujours respecter la règle suivante : `loop_wait + 2*retry_timeout` doit être inférieur ou égale à la valeur de `ttl`.
Il y a toujours un compromis entre un basculement rapide et la capacité à tolérer du lags au niveau réseau. Il faut donc veiller à ne pas trop mettre de valeurs basses, car il va effectivement avoir un basculement rapide, mais il peut aussi avoir un basculement au moindre lag de réseau, et donc provoquer potentiellement un splitbrain.
`maximum_lag_on_failover` est la valeur en octet maximale qu'un réplica peut prendre en retard pour pouvoir participer à l'élection du leader.