Comprendere ed Eseguire Scenari di Failover e Switchover di PostgreSQL

Scopri quando utilizzare lo switchover o il failover di PostgreSQL, come verificare la sicurezza della replica e come evitare il split-brain durante gli eventi di alta disponibilità.

Comprendere ed Eseguire Scenari di Failover e Switchover di PostgreSQL

La differenza tra failover e switchover di PostgreSQL non è accademica quando sei tu a tenere il cercapersone. Uno switchover è pianificato: hai ancora un primario sano, puoi drenare le scritture e puoi scegliere il momento migliore per spostare il ruolo scrivibile su una standby. Un failover è ciò che fai quando il primario è sparito, irraggiungibile o non sicuro per continuare a servire traffico.

Questa singola differenza cambia tutto. Durante uno switchover, il tuo compito principale è la pazienza: dimostrare che la standby ha recuperato prima della promozione. Durante un failover, il tuo compito principale è il contenimento: assicurarti che il vecchio primario non possa continuare ad accettare scritture dopo che una standby è stata promossa. La maggior parte degli incidenti brutti di HA di PostgreSQL derivano dall'affrettare uno di questi due compiti.

Fondamenti di Replica: Le Basi dell'HA

L'Alta Disponibilità di PostgreSQL è costruita sulla replica in streaming, dove un server agisce come Primario (o Master) e uno o più server agiscono come Standby (o Repliche). Il Primario trasmette i record del write-ahead log (WAL) alle Standby per mantenerle sincronizzate.

Per gestire efficacemente questi ruoli, sono necessarie impostazioni di configurazione specifiche sia sui nodi primari che su quelli replica:

Impostazioni di Configurazione Critiche

Queste impostazioni governano come opera la replica e come i nodi si identificano tra loro:

  • wal_level: Deve essere impostato su replica o superiore (idealmente logical se si utilizzano strumenti che richiedono la decodifica logica) sul Primario.
  • max_wal_senders: Definisce il numero massimo di connessioni di invio WAL concorrenti. Dimensionalo per tutte le standby fisiche, i backup di base e gli strumenti di replica che potrebbero connettersi contemporaneamente.
  • hot_standby: Deve essere impostato su on nel file postgresql.conf del server standby per consentire query di sola lettura durante la replica.
  • synchronous_commit: Controlla quando una transazione viene riconosciuta. Fornisce una maggiore durabilità solo con la replica sincrona configurata correttamente; da solo, non rende una standby aggiornata.
  • primary_conninfo: Impostato sulla standby, dettaglia le informazioni di connessione (host, porta, utente, password) per connettersi al Primario corrente.

Buona Pratica: Metti un endpoint stabile davanti a PostgreSQL, come HAProxy, PgBouncer dietro un IP virtuale, un record di service discovery o l'astrazione di servizio della tua piattaforma. Le applicazioni non dovrebbero aver bisogno di sapere quale nodo è primario oggi.

Switchover: La Transizione Pianificata

Uno Switchover è un processo controllato e graduale in cui il nodo Primario attivo viene intenzionalmente dismesso e una Standby designata viene promossa per prendere il suo posto. Questa procedura viene tipicamente utilizzata per manutenzione pianificata, upgrade di versione o sostituzioni hardware.

Passaggi per uno Switchover Controllato

L'obiettivo di uno switchover è garantire zero perdita di dati attendendo che tutte le transazioni in volo vengano replicate prima della promozione.

  1. Ferma le Scritture sul Primario Corrente: Il primo passo è impedire che nuove transazioni vengano committate sul Primario corrente. Questo si ottiene spesso impostando default_transaction_read_only = on o fermando temporaneamente le connessioni client.
  2. Attendi il Recupero della Replica: Assicurati che la Standby designata abbia ricevuto e applicato tutti i record WAL rimanenti dal Primario. Puoi controllare il ritardo di replica usando pg_stat_replication sul Primario o esaminando lo stato di recupero della standby.
  3. Avvia la Promozione della Standby: Esegui il comando per promuovere il server Standby scelto al ruolo di Primario. Il comando specifico dipende dallo strumento di gestione utilizzato (ad es., pg_ctl promote o un comando del cluster manager).
  4. Riconfigura il Vecchio Primario: Una volta che la Standby è stata promossa con successo, il vecchio Primario deve essere riconfigurato per seguire il nuovo Primario come Standby. Questo comporta l'aggiornamento del suo primary_conninfo.
  5. Reindirizza le Applicazioni: Aggiorna il load balancer o il connection pooler per indirizzare il traffico al nuovo server Primario.

Una checklist pratica per lo switchover di solito sembra più ordinaria che drammatica. Annuncia una breve pausa di scrittura, ferma i worker in background che continuano a scrivere, metti l'applicazione in modalità manutenzione o drena il pool di scrittori, e poi controlla la posizione di replica. Sul vecchio primario, pg_stat_replication mostra se la standby ha ricevuto e flushato il WAL. Sulla standby, pg_last_wal_receive_lsn() e pg_last_wal_replay_lsn() ti aiutano a vedere se il WAL è semplicemente arrivato o è stato effettivamente riprodotto.

Non promuovere una standby solo perché è connessa. Una standby può essere connessa e ancora secondi o minuti indietro se sta riproducendo una transazione grande, aspettando I/O su disco o recuperando dopo una pausa di rete. Per uno switchover pianificato, vuoi che la riproduzione sia recuperata prima della promozione. Se sulla standby sono in esecuzione sessioni di sola lettura, controlla anche se le query a lunga esecuzione stanno ritardando la riproduzione del WAL.

Dopo la promozione, testa il ruolo direttamente:

SELECT pg_is_in_recovery();

Il nodo promosso dovrebbe restituire false. Il nodo declassato, dopo essere stato ricostruito o riconnesso come standby, dovrebbe restituire true.

Il lato applicativo merita la stessa attenzione. Prima dello switchover, sappi come i client scoprono lo scrittore. Se si connettono a un nome DNS, comprendi il TTL del DNS e se i client memorizzano nella cache gli indirizzi più a lungo del previsto. Se si connettono tramite PgBouncer, decidi se devi mettere in pausa il pool, ricaricarlo o riavviarlo. Se usi HAProxy, assicurati che il controllo di salute testi lo stato scrivibile, non solo se la porta 5432 è aperta. Una standby con PostgreSQL in esecuzione non è un target di scrittura valido.

Mi piace anche annotare il punto di rollback. Prima della promozione, di solito puoi fermarti, riaprire le scritture sul vecchio primario e riprovare più tardi. Dopo la promozione, il rollback diventa un nuovo cambio di ruolo, non un semplice annullamento. Questo non significa che la promozione sia pericolosa; significa che l'operatore dovrebbe sapere da che parte della linea si trova.

Failover: La Risposta di Emergenza

Il Failover è una procedura immediata e reattiva attivata quando il server Primario corrente si guasta inaspettatamente (ad es., crash hardware, partizione di rete, errore software) e non può essere riportato online rapidamente.

Il failover comporta intrinsecamente un rischio maggiore di perdita di dati perché non c'è garanzia che le ultime transazioni committate abbiano avuto il tempo di essere trasmesse alle Standby prima del guasto.

Esecuzione di un Failover di Emergenza

Le procedure di failover sono progettate per velocità e recupero, spesso utilizzando strumenti specializzati per automatizzare la promozione.

  1. Determina la Salute del Vecchio Primario: Verifica che il Primario originale sia veramente non disponibile e non stia solo sperimentando un problema di rete transitorio (questo previene pericolosi scenari di 'split-brain').
  2. Seleziona la Migliore Standby: Scegli la Standby con il minor ritardo di replica (quella che è più avanti nel flusso WAL).
  3. Promuovi la Standby: Promuovi immediatamente la Standby selezionata usando il comando di promozione (pg_ctl promote).
  4. Gestisci la Perdita di Dati (Se Necessario): Se il cluster utilizza la replica asincrona, i dati persi sul Primario guasto potrebbero dover essere riconciliati manualmente o semplicemente accettati, a seconda della tolleranza dell'applicazione.
  5. Riconfigura l'Ex Primario: Una volta che il Primario originale è stato recuperato, deve essere pulito, reinizializzato (spesso richiedendo un backup di base dal nuovo Primario) e configurato per seguire il nuovo Primario.

La parte difficile del failover non è digitare pg_ctl promote. La parte difficile è decidere che il vecchio primario deve essere trattato come non sicuro fino a prova contraria. Se il vecchio primario è ancora in esecuzione ma tagliato fuori dall'applicazione o dalla standby, puoi ottenere split-brain: due server PostgreSQL scrivibili che accettano storie diverse. Una volta che ciò accade, PostgreSQL non unirà le storie per te. Ti trovi di fronte a una riconciliazione manuale dei dati o al ripristino di un lato dal backup.

In un incidente reale, preferirei passare un minuto in più a isolare il vecchio primario piuttosto che passare il giorno successivo a spiegare perché due record di ordini non sono d'accordo. L'isolamento può significare spegnere la vecchia VM, staccare la sua interfaccia di rete, disabilitare l'endpoint di scrittura o utilizzare un meccanismo cloud/provider che garantisca che il vecchio host non possa ricevere scritture. Il metodo esatto dipende dalla tua infrastruttura, ma il requisito è semplice: prima che i client scrivano sul nuovo primario, il vecchio primario non deve essere scrivibile da quei client.

Dopo il failover, aspettati pulizie. Se il vecchio primario torna, non puntarlo casualmente al nuovo primario sperando che recuperi. Potrebbe contenere WAL che appartiene alla vecchia timeline. In molti ambienti il percorso più sicuro è pg_rewind se i prerequisiti sono soddisfatti, o un backup di base fresco dal nuovo primario se non lo sono.

Un dettaglio che viene spesso trascurato durante il lavoro di emergenza è la storia degli slot di replica. Se il vecchio primario utilizzava slot di replica fisici per le standby, quegli slot non si spostano magicamente con la standby promossa a meno che il tuo strumento di HA non li gestisca. Dopo il failover, controlla se il nuovo primario ha gli slot di cui le tue standby sopravvissute hanno bisogno e controlla se qualche slot abbandonato sta trattenendo il WAL per sempre. Uno slot dimenticato può riempire un disco ore dopo che l'interruzione visibile è finita.

Usa la stessa disciplina per i backup. Una volta che il cluster ha un nuovo primario, conferma che i backup e l'archiviazione WAL ora seguono quel primario. Un failover che ripristina il servizio ma ferma silenziosamente i backup è solo un recupero a metà.

Strumenti per una Promozione Sicura: Repmgr vs. Patroni

Mentre la promozione manuale usando pg_ctl è possibile, gli ambienti HA robusti si affidano a strumenti dedicati per gestire la complessa coreografia richiesta per failover e switchover, gestendo automaticamente le modifiche di configurazione e lo stato del cluster.

Repmgr (Replication Manager)

repmgr è uno strumento leggero che aiuta a registrare i nodi, monitorare la replica ed eseguire cambi di ruolo controllati. I comandi esatti dipendono dalla versione e dalla disposizione del cluster, ma il pattern comune è:

  • Switchover: Esegui uno repmgr standby switchover pianificato dalla standby che dovrebbe diventare primaria, dopo aver confermato la salute della replica.
  • Failover: Lascia che repmgrd esegua il failover automatico solo se il comportamento di isolamento e witness/quorum sono compresi e testati.

Patroni

Patroni utilizza Archivi di Consenso Distribuiti (come etcd, ZooKeeper o Consul) per gestire lo stato del cluster, eleggendo automaticamente un nuovo Primario al rilevamento di un guasto. Patroni automatizza in gran parte sia gli switchover che i failover tramite chiamate API o operatori Kubernetes, riducendo drasticamente l'intervento manuale.

Esempio usando Patroni (Comando di Promozione Concettuale):

# Attivare uno switchover tramite l'API REST di Patroni
curl -X POST http://patroni-api-endpoint/switchover -H "Content-Type: application/json" -d '{"target": "standby_node_name"}'

Avvertenza sullo Split-Brain: Il pericolo maggiore durante il failover automatizzato è lo scenario di 'split-brain', in cui due nodi credono erroneamente di essere il Primario a causa di una partizione di rete. Strumenti come Patroni mitigano questo usando meccanismi di quorum, mentre le configurazioni manuali richiedono meccanismi di isolamento rigorosi (come i controlli di alimentazione) per garantire che esista un solo Primario.

Riepilogo delle Differenze

Caratteristica Switchover (Pianificato) Failover (Emergenza)
Innesco Manutenzione, upgrade, scelta amministrativa Guasto del Primario (crash, interruzione)
Rischio di Perdita Dati Quasi Zero (se tempizzato correttamente) Medio-Alto (dipende dalla modalità di replica)
Aspettativa di Downtime Downtime breve e controllato Downtime immediato e reattivo
Preparazione Richiede coordinamento preventivo e conferma della sincronizzazione WAL Richiede azione immediata e affidamento sulla salute della Standby

Un Piccolo Runbook che Puoi Adattare

Per uno switchover pianificato, un runbook compatto potrebbe essere così:

  1. Conferma che la standby scelta sia sana e stia riproducendo il WAL.
  2. Metti in pausa le scritture dell'applicazione e i job in background.
  3. Conferma che la riproduzione della replica sia recuperata.
  4. Promuovi la standby tramite lo strumento HA.
  5. Sposta l'endpoint di scrittura.
  6. Conferma che pg_is_in_recovery() sia false sul nuovo primario.
  7. Ricostruisci o riavvolgi il vecchio primario come standby.
  8. Riprendi le scritture e monitora errori, replica e conteggi delle connessioni.

Per il failover, l'ordine cambia:

  1. Conferma che il primario sia guasto o non sicuro.
  2. Isola il vecchio primario.
  3. Scegli la standby più avanzata.
  4. Promuovila tramite lo strumento HA.
  5. Sposta l'endpoint di scrittura una volta.
  6. Conferma che le scritture funzionino sul nuovo primario.
  7. Verifica repliche, slot, backup e archiviazione WAL.
  8. Reintroduci il vecchio primario solo tramite riavvolgimento o ricostruzione.

I comandi variano in base agli strumenti, ma le proprietà di sicurezza no. Un primario scrivibile, stato di replica noto, routing client testato e un modo pulito per riportare i nodi guasti.

Prima di fidarti di qualsiasi progetto HA, prova entrambi i percorsi in un ambiente non di produzione. Un drill di switchover dovrebbe dimostrare che le applicazioni si riconnettono pulitamente, il vecchio primario può diventare di nuovo una standby e il monitoraggio segue il nuovo ruolo. Un drill di failover dovrebbe dimostrare qualcosa di più rigoroso: il primario guasto è isolato, la standby scelta per la promozione è il miglior candidato disponibile, l'endpoint di scrittura dell'applicazione si sposta una volta e il vecchio primario non può riunirsi senza riavvolgimento o ricostruzione.

I team di HA di PostgreSQL più sicuri trattano il failover come un flusso di lavoro operativo testato, non come un comando eroico digitato durante un'interruzione.