Configurer la réplication d'un serveur PostgreSQL

Magazine
Marque
GNU/Linux Magazine
Numéro
184
Mois de parution
juillet 2015
Spécialité(s)


Résumé

« Un seul serveur vous manque et tout est dépeuplé... » écrivait le poète-sysadmin Lamartine au début du 19ème siècle.


Body

L'objectif

Depuis Lamartine, des solutions logicielles ont été développées pour ne pas trop souffrir de l'indisponibilité d'un serveur. Nous allons voir comment améliorer la résilience de nos bases de données en répliquant notre serveur PostgreSQL.

Les outils

- Deux systèmes GNU/Linux Debian ou dérivé (Ubuntu 13.10 ici)

- Le serveur de secours doit être de même architecture que le serveur principal (32 ou 64 bits)

- PostgreSQL 9.x (paquet postgresql-9.x) sur les deux systèmes (version 9.1 ici)

Phase 1. Comprendre les concepts-clés

Plusieurs modes de réplication sont possibles :

- Master / Master : chaque serveur peut recevoir une requête d'écriture, auquel cas il met à jour sa base puis se synchronise avec l'autre serveur ;

- Master / Slave : seul le serveur maître peut recevoir une requête d'écriture.

Nous allons nous intéresser au cas le plus répandu : le couple Master / Slave, comme dans Fifty Shades of Grey.

Lorsque le Master reçoit une requête SQL, toutes les modifications de données sont enregistrées dans des journaux de transactions : les WAL (Write-Ahead Log) xlogs. Ces journaux sont transférés au Slave (log shipping), qui les rejoue continuellement de façon à retrouver le même état que le Master. Cette restauration continue lui permet d'être prêt à prendre la relève en cas de défaillance du Master : on dit du Slave qu'il est en standby. Encore plus fort, le Slave peut répondre à des requêtes SQL en lecture seule si on le configure en hot standby.

À noter que ce mode de réplication est dit asynchrone parce qu'il y a un temps de délai entre le commit des transactions sur le Master et leurs applications sur le Slave.

Depuis la version 9.0 de PostgreSQL, ce temps de délai peut être considérablement réduit grâce à la streaming replication : plutôt que d'attendre que le fichier WAL entier (16 Mio par défaut) ne soit rempli, les WAL seront transmis en flux tendu via une connexion SSL dédiée entre le Master et le Slave.

Phase 2. Configuration commune au Master et au Slave

On va modifier le fichier de configuration principal /etc/postgresql/9.1/main/postgresql.conf exactement de la même manière sur le Master et le Slave, de façon à pouvoir rapidement passer de l'un à l'autre en cas de besoin :

wal_level = hot_standby

 

max_wal_senders = 1

 

wal_keep_segments = 256

checkpoint_segments = 8

 

hot_standby = on

Le wal_level définit le niveau de richesse des informations sauvegardées dans les WAL. Défini à hot_standby, il permettra au Slave de répondre aux requêtes en lecture seule.

On active d'ailleurs le mode hot_standby, même si ce paramètre n'est pris en compte que sur le Slave.

Supposons maintenant que le Slave soit indisponible pendant 1 heure. Il peut se passer beaucoup de choses en 1 heure. Le risque est que le Slave n'accumule trop de retard par rapport au Master. On aurait alors une erreur de ce type à son redémarrage :

2015-04-30 12:35:10 CEST FATAL: could not receive data from WAL stream: FATAL: requested WAL

segment 000000020000005A000000DB has already been removed

C'est pourquoi on choisit de conserver 256 xlogs via le paramètre wal_keep_segments. Chaque xlog faisant 16Mio, assurez-vous d'avoir assez d'espace disque disponible.

Phase 3. Configuration du Master

On crée un utilisateur dédié à la réplication :

$ sudo -u postgres psql -c "CREATE USER replication REPLICATION LOGIN CONNECTION LIMIT 1 ENCRYPTED PASSWORD 'motdepasse';"

On modifie /etc/postgresql/9.1/main/pg_hba.conf pour autoriser le Slave à se connecter via SSL (pour récupérer les WAL) :

hostssl replication replication ip_du_slave/32 md5

On redémarre le serveur PostgreSQL pour prendre en compte tous ces changements :

$ sudo service postgresql restart

Phase 4. Configuration du Slave

On arrête le serveur PostgreSQL :

$ sudo service postgresql stop

On modifie /etc/postgresql/9.1/main/pg_hba.conf pour autoriser le Master à se connecter via SSL (au cas où les rôles seraient inversés) :

hostssl replication replication ip_du_master/32 md5

On va maintenant faire la base backup, sauvegarde complète des bases :

$ sudo -u postgres rm -fr /var/lib/postgresql/9.1/main
$ sudo -u postgres pg_basebackup -h ip_du_master -D /var/lib/postgresql/9.1/main -U replication -v -P --xlog

motdepasse

Concrètement, le script pg_basebackup s'occupe de :

- exécuter la fonction SQL pg_start_backup() pour forcer un checkpoint ;

- transférer les fichiers des bases (via une connexion SSL) ;

- exécuter la fonction SQL pg_stop_backup().

Pendant le transfert des fichiers, la base a pu subir des modifications. Le paramètre --xlog ordonne à pg_basebackup de transférer également les derniers journaux de transactions pour les rejouer sur la base backup.

Il ne reste plus qu'à configurer la restauration continue. On crée le fichier /var/lib/postgresql/9.1/main/recovery.conf :

standby_mode = on
primary_conninfo = 'host=ip_du_master port=5432 user=replication password=motdepasse sslmode=require'
trigger_file = '/var/lib/postgresql/9.1/postgresql.trigger'

Quelques commentaires s'imposent !

On active le standby_mode : la restauration se fait continuellement.

Le paramètre primary_conninfo contient les informations nécessaires pour se connecter au Master pour récupérer les WAL.

La création du trigger_file déclenchera l'arrêt de la restauration. Attention, certains tutoriels placent le trigger_file dans /tmp : n'importe quel utilisateur peut alors créer le fichier !

Tout est prêt, on lance le serveur PostgreSQL :

$ sudo service postgresql start

Les logs devraient ressembler à ça :

$ sudo tail /var/log/postgresql/postgresql-9.1-main.log

2015-04-30 12:59:04 CEST LOG: database system was interrupted; last known up at 2015-04-30 12:54:50 CEST
2015-04-30 12:59:04 CEST LOG: creating missing WAL directory "pg_xlog/archive_status"
2015-04-30 12:59:04 CEST LOG: entering standby mode
2015-04-30 12:59:04 CEST LOG: redo starts at 61/37000020
2015-04-30 12:59:04 CEST LOG: consistent recovery state reached at 61/3701B9E0
2015-04-30 12:59:04 CEST LOG: database system is ready to accept read only connections
2015-04-30 12:59:04 CEST LOG: streaming replication successfully connected to primary
2015-04-30 12:59:04 CEST LOG: incomplete startup packet

À noter que l'erreur incomplete startup packet n'en est pas une : « it's harmless, it's been there for years. » [http://www.postgresql.org/message-id/8262g133ri.fsf@mid.bfk.de]. Elle serait liée à la couche réseau et non à la réplication.

Phase 5. S'assurer que tout fonctionne

5.1 Création d'une table temporaire

On va créer une table temporaire sur le Master :

$ sudo -u postgres psql

CREATE TABLE rep_test (test varchar(40));
INSERT INTO rep_test VALUES ('allo quoi');

On s'assure qu'elle est bien répliquée sur le Slave :

$ sudo -u postgres psql

SELECT * FROM rep_test;

N'oubliez pas de la supprimer ensuite sur le Master :

DROP TABLE rep_test;

5.2 Modification d'une valeur

Au niveau applicatif, on peut modifier une valeur en base :

> c = Client.objects.get(id=1)
> c.name = 'Jules'
> c.save()

Et voir si la modification est bien répercutée côté Slave :

$ sudo -u postgres psql
\c mabase
select name from front_client where id=1;

5.3 Quelques informations de monitoring

Côté Master, pour savoir où en est la réplication :

$ sudo -u postgres psql -x -c "select * from pg_stat_replication;"

Côté Slave, pour savoir à quand remonte la dernière synchronisation :

$ sudo -u postgres psql -x -c "SELECT now() - pg_last_xact_replay_timestamp() AS time_lag;"

Attention, si c'était il y a 2 heures, c'est peut-être que rien n'a été modifié en base depuis.

Enfin, pour voir le nom de la snapshot actuelle :

$ sudo -u postgres psql -x -c "SELECT txid_current_snapshot();"

Phase 6. Un Master, plusieurs slaves

Pour rajouter un Slave de plus, il suffit de reprendre les instructions précédentes.

Mais côté Master, il faut permettre à un deuxième utilisateur replication de se connecter :

$ sudo -u postgres psql -x -c "ALTER ROLE replication CONNECTION LIMIT 2;"

Et il faut également modifier /etc/postgresql/9.1/main/postgresql.conf pour ajouter un processus walsender :

~~~conf
max_wal_senders = 2

~~~

Le redémarrage du serveur PostgreSQL est nécessaire pour prendre en compte ces changements :

$ sudo service postgresql restart

Phase 7. Tester le failover

Le Master vient de rendre l'âme ? Voici venue l'heure de gloire du Slave :

$ sudo touch /var/lib/postgresql/9.1/postgresql.trigger

La restauration continue va s'arrêter, les bases vont passer en mode read-write et recovery.conf sera renommé en recovery.done.

Il ne reste plus alors qu'à mettre à jour l'URL de la base dans l'application.

Le résultat

On a mis en œuvre la réplication continue de notre serveur PostgreSQL. On pourrait s'en contenter. Mais pour avoir l'esprit encore plus tranquille, il est conseillé d'en faire également un archivage continu.

L'idée c'est de faire une base backup à un instant t puis d'archiver tous les fichiers WAL produits par la suite. Il sera ainsi possible de restaurer la base à n'importe quel moment de son existence, aka Point-in-time Recovery. Très utile pour Benjamin Buttoniser une base après une migration catastrophique !

Nous verrons dans un prochain article comment utiliser WAL-e [https://github.com/wal-e/wal-e] à ces fins.

 



Article rédigé par

Les derniers articles Premiums

Les derniers articles Premium

Stubby : protection de votre vie privée via le chiffrement des requêtes DNS

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Depuis les révélations d’Edward Snowden sur l’espionnage de masse des communications sur Internet par la NSA, un effort massif a été fait pour protéger la vie en ligne des internautes. Cet effort s’est principalement concentré sur les outils de communication avec la généralisation de l’usage du chiffrement sur le web (désormais, plus de 90 % des échanges se font en HTTPS) et l’adoption en masse des messageries utilisant des protocoles de chiffrement de bout en bout. Cependant, toutes ces communications, bien que chiffrées, utilisent un protocole qui, lui, n’est pas chiffré par défaut, loin de là : le DNS. Voyons ensemble quels sont les risques que cela induit pour les internautes et comment nous pouvons améliorer la situation.

Surveillez la consommation énergétique de votre code

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Être en mesure de surveiller la consommation énergétique de nos applications est une idée attrayante, qui n'est que trop souvent mise à la marge aujourd'hui. C'est d'ailleurs paradoxal, quand on pense que de plus en plus de voitures permettent de connaître la consommation instantanée et la consommation moyenne du véhicule, mais que nos chers ordinateurs, fleurons de la technologie, ne le permettent pas pour nos applications... Mais c'est aussi une tendance qui s'affirme petit à petit et à laquelle à terme, il devrait être difficile d'échapper. Car même si ce n'est qu'un effet de bord, elle nous amène à créer des programmes plus efficaces, qui sont également moins chers à exécuter.

Donnez une autre dimension à vos logs avec Vector

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Avoir des informations précises et détaillées sur ce qu’il se passe dans une infrastructure, et sur les applications qu'elle héberge est un enjeu critique pour votre business. Cependant, ça demande du temps, temps qu'on préfère parfois se réserver pour d'autres tâches jugées plus prioritaires. Mais qu'un système plante, qu'une application perde les pédales ou qu'une faille de sécurité soit découverte et c'est la panique à bord ! Alors je vous le demande, qui voudrait rester aveugle quand l'observabilité a tout à vous offrir ?

Les listes de lecture

9 article(s) - ajoutée le 01/07/2020
Vous désirez apprendre le langage Python, mais ne savez pas trop par où commencer ? Cette liste de lecture vous permettra de faire vos premiers pas en découvrant l'écosystème de Python et en écrivant de petits scripts.
11 article(s) - ajoutée le 01/07/2020
La base de tout programme effectuant une tâche un tant soit peu complexe est un algorithme, une méthode permettant de manipuler des données pour obtenir un résultat attendu. Dans cette liste, vous pourrez découvrir quelques spécimens d'algorithmes.
10 article(s) - ajoutée le 01/07/2020
À quoi bon se targuer de posséder des pétaoctets de données si l'on est incapable d'analyser ces dernières ? Cette liste vous aidera à "faire parler" vos données.
Voir les 102 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous