Réplication asynchrone par log streaming

Durant ce TP, nous allons nous baser sur ce qui a été vu dans le TP sauvegardes physiques pour mettre en place une réplication asynchrone par log streaming vers un seul secondaire.

Configuration de l'utilisateur de réplication

La réplication par log streaming nécessite une connexion du secondaire vers le primaire. Pour que cette connexion puisse se faire, nous allons devoir créer un utilisateur et vérifier les paramètres de connexion dans pg_hba.conf

  • Sur le principal, créer l'utilisateur repli, mot de passe repli avec les droits associés à la réplication
createuser -p 5432 --no-superuser --no-createrole --no-createdb --replication -P repli
  • Vérifier le fichier pg_hba.conf du principal
$ cat /var/lib/postgresql/main/pg_hba.conf # Ce chemin peut varier selon la distribution

Les paramètres suivants doivent être présents :

# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     trust
host    replication     all             127.0.0.1/32            trust
host    replication     all             ::1/128                 trust
  • Si besoin, recharger la configuration du principal
psql -p 5432 -c 'SELECT pg_reload_conf()'
  • Ajouter les paramètres d'authentification pour l'utilisateur repli dans le fichier .pgpass de l'utilisateur système postgres

~/.pgpass

echo "*:*:*:repli:confidentiel" > ~/.pgpass
chmod 600 ~/.pgpass

Création de l'instance secondaire

Nous allons garder notre primaire tel quel et créer un secondaire dédié à la réplication.

  • Créer une instance dédiée à la réplication avec pg_createuser, son répertoire de données doit être /var/lib/postgresql/repli, son port 5434 et son nom postgres_repli

Initialisation du secondaire

Pour initialiser le serveur secondaire nous allons créer un backup avec pg_basebackup et le restaurer dans le répertoire de données du secondaire nouvellement créé

  • Supprimer le contenu du répertoire de données de l'instance secondaire
  • Créer une sauvegarde du primaire en se basant sur les étapes vues au TP précédent. On ajoutera simplement l'option -R (--write-recovery-conf) à la commande pg_basebackup pour que l'outil prépare lui-même la configuration de restauration.

Configuration du secondaire

Notre backup étant prêt, il ne nous reste qu'à ajuster les paramètres de l'instance secondaire dans son fichier de configuration /etc/postgresql/13/postgres_repli/postgresql.conf

Le répertoire de données créé par pg_basebackup contient un fichier postgresql.auto.conf dans lequel on trouve le paramètre primary_conninfo à utiliser tel quel dans le secondaire. Le répertoire contient également un fichier recovery.signal déjà prêt.

  • Renseigner le paramètre primary_conninfo
  • Démarrer l'instance
  • Vérifier que l'instance démarre bien et que la réplication est en cours
cat /var/log/postgresql/postgresql-13-postgres_repli.log
ps -o pid,cmd fx

Les logs doivent montrer successivement la restauration des données depuis les journaux, le passage en mode standby, l'activation du streaming :

[3203] LOG:  entering standby mode
[3203] LOG:  redo starts at 1/44000028
[3203] LOG:  consistent recovery state reached at 1/44000138
[3202] LOG:  database system is ready to accept read only connections
[3207] LOG:  started streaming WAL from primary at 1/45000000 on timeline 1

La liste des processus doit montrer la présence d'un arbre de processus contenant le processus walreceiver

3202 /usr/lib/postgresql/13/bin/postgres -D /var/lib/postgresql/repli -c config_file=/etc/postgresql/13/postgre
 3203  \_ postgres: 13/postgres_repli: startup recovering 000000010000000100000045
 3204  \_ postgres: 13/postgres_repli: checkpointer
 3205  \_ postgres: 13/postgres_repli: background writer
 3206  \_ postgres: 13/postgres_repli: stats collector
 3207  \_ postgres: 13/postgres_repli: walreceiver streaming 1/45000148
  • Créer quelques données dans le principal
  • Se connecter sur le secondaire et vérifier que les données apparaissent quasiment instantanément
  • Essayer d'insérer des données dans le secondaire et constater que ce n'est pas possible

Promotion du secondaire

En cas de problème avec le serveur primaire, il est possible de basculer le secondaire comme nouveau primaire.

  • Arrêter l'instance primaire
  • Vérifier que les deux instances sont bien synchronisées
/usr/lib/postgresql/13/bin/pg_controldata -D /var/lib/postgresql/data | grep REDO
/usr/lib/postgresql/13/bin/pg_controldata -D /var/lib/postgresql/repli | grep REDO

Le résultat de chaque commande doit montrer le même emplacement de checkpoint :

# principal
Latest checkpoint's REDO location:    1/450192D8
Latest checkpoint's REDO WAL file:    000000010000000100000045

# secondaire
Latest checkpoint's REDO location:    1/450192D8
Latest checkpoint's REDO WAL file:    000000010000000100000045
  • Une fois ces pré-requis validé, on peut promouvoir le secondaire :
pg_ctlcluster 13 postgres_repli promote
  • Afficher les logs, on doit voir passer l'évènement de promotion :
[3207] FATAL:  terminating walreceiver process due to administrator command
[3203] LOG:  invalid record length at 1/450193C0: wanted 24, got 0
[3203] LOG:  redo done at 1/45019388
[3203] LOG:  last completed transaction was at log time 2021-06-30 11:52:11.083996+00
[3203] LOG:  selected new timeline ID: 2
[3203] LOG:  archive recovery complete
[3202] LOG:  database system is ready to accept connections
  • On doit maintenant pouvoir se connecter au secondaire et effectuer des écritures