Comprendre et exécuter les scénarios de basculement PostgreSQL : Failover vs Switchover

Apprenez quand utiliser un switchover ou un failover PostgreSQL, comment vérifier la sécurité des réplicas et comment éviter le split-brain lors des événements HA.

Comprendre et exécuter les scénarios de basculement PostgreSQL : Failover vs Switchover

La différence entre un failover et un switchover PostgreSQL n'est pas théorique lorsque vous êtes la personne qui tient le bipeur. Un switchover est planifié : vous avez encore un primaire sain, vous pouvez drainer les écritures et choisir le meilleur moment pour transférer le rôle d'écriture à un standby. Un failover est ce que vous faites lorsque le primaire est parti, injoignable ou dangereux à laisser servir le trafic.

Cette unique différence change tout. Lors d'un switchover, votre tâche principale est la patience : prouver que le standby a rattrapé son retard avant la promotion. Lors d'un failover, votre tâche principale est le confinement : garantir que l'ancien primaire ne peut plus accepter d'écritures après la promotion d'un standby. La plupart des incidents PostgreSQL HA désagréables proviennent de la précipitation sur l'une de ces deux tâches.

Fondamentaux de la réplication : le socle de la HA

La haute disponibilité PostgreSQL repose sur la réplication en continu (streaming replication), où un serveur agit comme Primaire (ou Maître) et un ou plusieurs serveurs comme Standbys (ou Réplicas). Le Primaire diffuse les enregistrements du journal d'écriture anticipée (WAL) aux Standbys pour les maintenir synchronisés.

Pour gérer efficacement ces rôles, des paramètres de configuration spécifiques sont nécessaires sur les nœuds primaire et réplica :

Paramètres de configuration critiques

Ces paramètres régissent le fonctionnement de la réplication et la manière dont les nœuds s'identifient mutuellement :

  • wal_level : Doit être défini sur replica ou plus (idéalement logical si vous utilisez des outils nécessitant un décodage logique) sur le Primaire.
  • max_wal_senders : Définit le nombre maximum de connexions d'expéditeurs WAL simultanées. Dimensionnez-le pour tous les standbys physiques, les sauvegardes de base et les outils de réplication qui peuvent se connecter en même temps.
  • hot_standby : Doit être défini sur on dans le fichier postgresql.conf du serveur standby pour autoriser les requêtes en lecture seule pendant la réplication.
  • synchronous_commit : Contrôle le moment où une transaction est acquittée. Il n'offre une durabilité renforcée qu'avec une réplication synchrone correctement configurée ; seul, il ne garantit pas qu'un standby soit à jour.
  • primary_conninfo : Défini sur le standby, détaillant les informations de connexion (hôte, port, utilisateur, mot de passe) pour se connecter au Primaire actuel.

Meilleure pratique : Placez un point d'accès stable devant PostgreSQL, comme HAProxy, PgBouncer derrière une IP virtuelle, un enregistrement de découverte de service ou l'abstraction de service de votre plateforme. Les applications ne devraient pas avoir besoin de savoir quel nœud est le primaire aujourd'hui.

Switchover : la transition planifiée

Un Switchover est un processus contrôlé et gracieux où le nœud Primaire actif est intentionnellement désaffecté, et un Standby désigné est promu pour prendre sa place. Cette procédure est généralement utilisée pour la maintenance planifiée, les mises à niveau de version ou les remplacements matériels.

Étapes pour un switchover contrôlé

L'objectif d'un switchover est de garantir zéro perte de données en attendant que toutes les transactions en cours soient répliquées avant la promotion.

  1. Arrêter les écritures sur le Primaire actuel : La première étape consiste à empêcher toute nouvelle transaction d'être validée sur le Primaire actuel. Cela se fait souvent en définissant default_transaction_read_only = on ou en arrêtant temporairement les connexions client.
  2. Attendre le rattrapage de la réplication : Assurez-vous que le Standby désigné a reçu et appliqué tous les enregistrements WAL restants du Primaire. Vous pouvez vérifier le retard de réplication en utilisant pg_stat_replication sur le Primaire ou en examinant l'état de récupération du standby.
  3. Initier la promotion du Standby : Exécutez la commande pour promouvoir le serveur Standby choisi au rôle de Primaire. La commande spécifique dépend de l'outil de gestion utilisé (par exemple, pg_ctl promote ou une commande du gestionnaire de cluster).
  4. Reconfigurer l'ancien Primaire : Une fois le Standby promu avec succès, l'ancien Primaire doit être reconfiguré pour suivre le nouveau Primaire en tant que Standby. Cela implique la mise à jour de son primary_conninfo.
  5. Rediriger les applications : Mettez à jour l'équilibreur de charge ou le pooler de connexions pour diriger le trafic vers le nouveau serveur Primaire.

Une checklist pratique de switchover est généralement plus ordinaire que dramatique. Annoncez une brève pause d'écriture, arrêtez les workers en arrière-plan qui continuent d'écrire, mettez l'application en mode maintenance ou videz le pool d'écriture, puis vérifiez la position de réplication. Sur l'ancien primaire, pg_stat_replication indique si le standby a reçu et vidé le WAL. Sur le standby, pg_last_wal_receive_lsn() et pg_last_wal_replay_lsn() vous aident à voir si le WAL est simplement arrivé ou a réellement été rejoué.

Ne promouvez pas un standby simplement parce qu'il est connecté. Un standby peut être connecté et pourtant avoir des secondes ou des minutes de retard s'il rejoue une grosse transaction, attend sur les E/S disque ou récupère après une pause réseau. Pour un switchover planifié, vous voulez que le rejeu soit à jour avant la promotion. Si des sessions en lecture seule sont en cours sur le standby, vérifiez également si des requêtes de longue durée ne retardent pas le rejeu du WAL.

Après la promotion, testez le rôle directement :

SELECT pg_is_in_recovery();

Le nœud promu doit retourner false. Le nœud rétrogradé, après avoir été reconstruit ou reconnecté en tant que standby, doit retourner true.

Le côté application mérite la même attention. Avant le switchover, sachez comment les clients découvrent l'écrivain. S'ils se connectent à un nom DNS, comprenez le TTL DNS et si les clients mettent en cache les adresses plus longtemps que prévu. S'ils se connectent via PgBouncer, décidez si vous devez mettre en pause le pool, le recharger ou le redémarrer. Si vous utilisez HAProxy, assurez-vous que la vérification de santé teste l'état d'écriture, pas seulement si le port 5432 est ouvert. Un standby avec PostgreSQL en cours d'exécution n'est pas une cible d'écriture valide.

J'aime aussi noter le point de retour arrière. Avant la promotion, vous pouvez généralement vous arrêter, rouvrir les écritures sur l'ancien primaire et réessayer plus tard. Après la promotion, le retour arrière devient un nouveau changement de rôle, pas une simple annulation. Cela ne signifie pas que la promotion est dangereuse ; cela signifie que l'opérateur doit savoir de quel côté de la ligne il se trouve.

Failover : la réponse d'urgence

Le Failover est une procédure immédiate et réactive déclenchée lorsque le serveur Primaire actuel tombe en panne de manière inattendue (par exemple, crash matériel, partition réseau, erreur logicielle) et ne peut pas être remis en ligne rapidement.

Le failover comporte intrinsèquement un risque plus élevé de perte de données car rien ne garantit que les dernières transactions validées aient eu le temps d'être diffusées vers les Standbys avant la panne.

Exécution d'un failover d'urgence

Les procédures de failover sont conçues pour la rapidité et la récupération, utilisant souvent des outils spécialisés pour automatiser la promotion.

  1. Déterminer l'état de santé de l'ancien Primaire : Vérifiez que le Primaire d'origine est vraiment indisponible et non pas simplement victime d'un problème réseau transitoire (cela évite les scénarios dangereux de 'split-brain').
  2. Sélectionner le meilleur Standby : Choisissez le Standby avec le moins de retard de réplication (celui qui est le plus en avance dans le flux WAL).
  3. Promouvoir le Standby : Promouvez immédiatement le Standby sélectionné à l'aide de la commande de promotion (pg_ctl promote).
  4. Gérer la perte de données (si nécessaire) : Si le cluster utilise la réplication asynchrone, les données perdues sur le Primaire défaillant peuvent devoir être réconciliées manuellement ou simplement acceptées, selon la tolérance de l'application.
  5. Reconfigurer l'ancien Primaire : Une fois le Primaire d'origine récupéré, il doit être nettoyé, réinitialisé (nécessitant souvent une sauvegarde de base depuis le nouveau Primaire) et configuré pour suivre le nouveau Primaire.

La partie difficile du failover n'est pas de taper pg_ctl promote. La partie difficile est de décider que l'ancien primaire doit être traité comme dangereux jusqu'à preuve du contraire. Si l'ancien primaire est toujours en cours d'exécution mais coupé de l'application ou du standby, vous pouvez obtenir un split-brain : deux serveurs PostgreSQL accessibles en écriture acceptant des historiques différents. Une fois que cela se produit, PostgreSQL ne fusionnera pas les historiques pour vous. Vous êtes confronté à une réconciliation manuelle des données ou à la restauration d'un côté à partir d'une sauvegarde.

Dans un incident réel, je préfère passer une minute supplémentaire à isoler l'ancien primaire plutôt que de passer le lendemain à expliquer pourquoi deux enregistrements de commande ne concordent pas. L'isolement peut signifier éteindre l'ancienne VM, détacher son interface réseau, désactiver le point d'accès d'écriture ou utiliser un mécanisme cloud/fournisseur qui garantit que l'ancien hôte ne peut pas recevoir d'écritures. La méthode exacte dépend de votre infrastructure, mais l'exigence est simple : avant que les clients n'écrivent sur le nouveau primaire, l'ancien primaire ne doit pas pouvoir être écrit par ces clients.

Après un failover, attendez-vous à du nettoyage. Si l'ancien primaire revient, ne le pointez pas négligemment vers le nouveau primaire en espérant qu'il rattrape son retard. Il peut contenir du WAL appartenant à l'ancienne timeline. Dans de nombreux environnements, la voie la plus sûre est pg_rewind si les prérequis sont remplis, ou une nouvelle sauvegarde de base depuis le nouveau primaire s'ils ne le sont pas.

Un détail souvent oublié lors du travail d'urgence est l'histoire des slots de réplication. Si l'ancien primaire utilisait des slots de réplication physiques pour les standbys, ces slots ne se déplacent pas magiquement avec le standby promu, à moins que vos outils HA ne les gèrent. Après le failover, vérifiez si le nouveau primaire a les slots dont vos standbys survivants ont besoin, et vérifiez si un slot abandonné ne retient pas le WAL indéfiniment. Un slot oublié peut remplir un disque des heures après la fin de la panne visible.

Utilisez la même discipline pour les sauvegardes. Une fois que le cluster a un nouveau primaire, confirmez que les sauvegardes et l'archivage WAL suivent désormais ce primaire. Un failover qui rétablit le service mais arrête silencieusement les sauvegardes n'est qu'une demi-récupération.

Outils pour une promotion sûre : Repmgr vs Patroni

Bien que la promotion manuelle avec pg_ctl soit possible, les environnements HA robustes s'appuient sur des outils dédiés pour gérer la chorégraphie complexe requise pour le failover et le switchover, en gérant automatiquement les changements de configuration et l'état du cluster.

Repmgr (Replication Manager)

repmgr est un outil léger qui aide à enregistrer les nœuds, surveiller la réplication et effectuer des changements de rôle contrôlés. Les commandes exactes dépendent de la version et de la disposition du cluster, mais le modèle courant est :

  • Switchover : Exécutez un repmgr standby switchover planifié à partir du standby qui doit devenir primaire, après avoir confirmé l'état de santé de la réplication.
  • Failover : Laissez repmgrd effectuer un failover automatique uniquement si le comportement d'isolement et de témoin/quorum est compris et testé.

Patroni

Patroni utilise des magasins de consensus distribués (comme etcd, ZooKeeper ou Consul) pour gérer l'état du cluster, en élisant automatiquement un nouveau Primaire lors de la détection d'une panne. Patroni automatise largement les switchovers et les failovers via des appels API ou des opérateurs Kubernetes, réduisant considérablement l'intervention manuelle.

Exemple avec Patroni (commande de promotion conceptuelle) :

# Déclencher un switchover via l'API REST de Patroni
curl -X POST http://patroni-api-endpoint/switchover -H "Content-Type: application/json" -d '{"target": "standby_node_name"}'

Avertissement sur le Split-Brain : Le plus grand danger lors d'un failover automatisé est le scénario 'split-brain', où deux nœuds croient à tort être le Primaire en raison d'un partitionnement réseau. Des outils comme Patroni atténuent ce risque en utilisant des mécanismes de quorum, tandis que les configurations manuelles nécessitent des mécanismes d'isolement stricts (comme des contrôles d'alimentation) pour garantir qu'un seul Primaire existe.

Résumé des différences

Caractéristique Switchover (Planifié) Failover (Urgence)
Déclencheur Maintenance, mise à niveau, choix administratif Panne du Primaire (crash, indisponibilité)
Risque de perte de données Quasi nul (si correctement chronométré) Moyen à élevé (dépend du mode de réplication)
Temps d'arrêt attendu Arrêt court et contrôlé Arrêt immédiat et réactif
Préparation Nécessite une coordination préalable et une confirmation de la synchronisation WAL Nécessite une action immédiate et une confiance dans l'état de santé du Standby

Un petit runbook que vous pouvez adapter

Pour un switchover planifié, un runbook compact pourrait ressembler à ceci :

  1. Confirmer que le standby choisi est sain et rejoue le WAL.
  2. Mettre en pause les écritures de l'application et les jobs en arrière-plan.
  3. Confirmer que le rejeu de la réplication a rattrapé son retard.
  4. Promouvoir le standby via l'outil HA.
  5. Déplacer le point d'accès d'écriture.
  6. Confirmer que pg_is_in_recovery() est false sur le nouveau primaire.
  7. Reconstruire ou rembobiner l'ancien primaire en tant que standby.
  8. Reprendre les écritures et surveiller les erreurs, la réplication et les compteurs de connexions.

Pour un failover, l'ordre change :

  1. Confirmer que le primaire est en panne ou dangereux.
  2. Isoler l'ancien primaire.
  3. Choisir le standby le plus avancé.
  4. Le promouvoir via l'outil HA.
  5. Déplacer le point d'accès d'écriture une fois.
  6. Confirmer que les écritures fonctionnent sur le nouveau primaire.
  7. Vérifier les réplicas, les slots, les sauvegardes et l'archivage WAL.
  8. Réintroduire l'ancien primaire uniquement via un rembobinage ou une reconstruction.

Les commandes varient selon les outils, mais les propriétés de sécurité ne changent pas. Un seul primaire accessible en écriture, un état de réplication connu, un routage client testé et un moyen propre de ramener les nœuds défaillants.

Avant de faire confiance à une conception HA, répétez les deux chemins dans un environnement hors production. Un exercice de switchover doit prouver que les applications se reconnectent proprement, que l'ancien primaire peut redevenir un standby et que la surveillance suit le nouveau rôle. Un exercice de failover doit prouver quelque chose de plus strict : l'ancien primaire défaillant est isolé, le standby choisi pour la promotion est le meilleur candidat disponible, le point d'accès d'écriture de l'application est déplacé une fois, et l'ancien primaire ne peut pas se réintégrer sans rembobinage ou reconstruction.

Les équipes PostgreSQL HA les plus sûres traitent le failover comme un workflow opérationnel testé, et non comme une commande héroïque tapée lors d'une panne.