Architetture per l'alta disponibilità dei cluster PostgreSQL su Compute Engine

Last reviewed 2023-10-09 UTC

Questo articolo descrive diverse architetture che offrono alta disponibilità (alta disponibilità) per i deployment PostgreSQL su Google Cloud. L'alta disponibilità è la misura della resilienza del sistema in risposta a guasti dell'infrastruttura sottostante. In questo documento, l'alta disponibilità si riferisce alla disponibilità dei cluster PostgreSQL all'interno di una singola regione cloud o tra più regioni, a seconda dell'architettura ad alta disponibilità.

Questo documento è destinato agli amministratori di database, ai Cloud Architect e ai tecnici DevOps che vogliono imparare ad aumentare l'affidabilità a livello di dati PostgreSQL migliorando l'uptime complessivo del sistema. Questo documento illustra i concetti relativi all'esecuzione di PostgreSQL su Compute Engine. Il documento non tratta dell'utilizzo di Cloud SQL per PostgreSQL.

Se un sistema o un'applicazione richiede uno stato permanente per gestire richieste o transazioni, il livello di persistenza dei dati (il livello dati) deve essere disponibile per gestire correttamente le richieste di query o mutazioni sui dati. Il tempo di inattività nel livello dati impedisce al sistema o all'applicazione di eseguire le attività necessarie.

A seconda degli obiettivi del livello di servizio (SLO) del sistema, potrebbe essere necessaria un'architettura che fornisca un livello di disponibilità più elevato. Esistono più modi per ottenere l'alta disponibilità, ma in generale esegui il provisioning di un'infrastruttura ridondante, che puoi rendere rapidamente accessibile alla tua applicazione.

Questo documento tratta i seguenti argomenti:

  • Definizione dei termini relativi ai concetti dei database ad alta disponibilità.
  • Opzioni per le topologie PostgreSQL ad alta disponibilità.
  • Informazioni contestuali per la considerazione di ciascuna opzione di architettura.

Terminologia

I termini e i concetti riportati di seguito sono standard di settore e sono utili da comprendere per scopi che esulano dall'ambito di questo documento.

replicazione
Il processo mediante il quale le transazioni di scrittura (INSERT, UPDATE o DELETE) e le modifiche allo schema (Data Definition Language (DDL)) vengono acquisite in modo affidabile, registrate e quindi applicate in modo seriale a tutti i nodi di replica dei database downstream nell'architettura.
nodo primario
Il nodo che fornisce una lettura con lo stato più aggiornato dei dati persistenti. Tutte le scritture del database devono essere indirizzate a un nodo primario.
nodo replica (secondario)
Una copia online del nodo del database principale. Le modifiche vengono replicate in modo sincrono o asincrono nei nodi di replica dal nodo principale. Puoi leggere dai nodi di replica con la consapevolezza che i dati potrebbero subire leggermente ritardi a causa del ritardo della replica.
ritardo della replica
Una misurazione, con numero di sequenza di log (LSN), ID transazione o ora. Il ritardo della replica esprime la differenza tra il momento in cui le operazioni di modifica vengono applicate alla replica e il momento in cui vengono applicate al nodo principale.
archiviazione continua
Un backup incrementale in cui il database salva continuamente le transazioni sequenziali in un file.
log write-ahead (WAL)
Un log write-ahead (WAL) è un file di log che registra le modifiche apportate ai file di dati prima che vengano effettivamente apportate ai file. In caso di arresto anomalo del server, WAL è un metodo standard per garantire l'integrità dei dati e la durabilità delle scritture.
record WAL
Un record di una transazione applicata al database. Un record WAL viene formattato e archiviato come serie di record che descrivono le modifiche a livello di pagina dei file di dati.
Numero di sequenza di log (LSN)
Le transazioni creano record WAL che vengono aggiunti al file WAL. La posizione in cui si verifica l'inserimento è denominata numero di sequenza di log (LSN). Si tratta di un numero intero a 64 bit rappresentato da due numeri esadecimali separati da una barra (XXXXXXXX/YYZZZZZZ). La "Z" rappresenta la posizione di offset nel file WAL.
file di segmentazione
File che contengono il maggior numero possibile di record WAL, a seconda delle dimensioni del file che configuri. I file di segmento hanno nomi file che aumentano monotonicamente e hanno una dimensione predefinita di 16 MB.
replica sincrona
Una forma di replica in cui il server principale attende la replica per confermare che i dati siano stati scritti nel log delle transazioni della replica prima di confermare un commit al client. Quando esegui la replica dei flussi di dati, puoi utilizzare l'opzione synchronous_commit di PostgreSQL per configurare le garanzie di coerenza.
replica asincrona
Una forma di replica in cui il server principale non attende la replica per verificare che la transazione sia stata ricevuta correttamente prima di confermare un commit al client. La replica asincrona ha una latenza minore rispetto alla replica sincrona. Tuttavia, se l'arresto anomalo principale e le transazioni di cui è stato eseguito il commit non vengono trasferiti alla replica, esiste la possibilità di perdere i dati. La replica asincrona è la modalità di replica predefinita su PostgreSQL, utilizzando la spedizione dei log basata su file o la replica in modalità flusso.
spedizione dei log basata su file
Un metodo di replica in PostgreSQL che trasferisce i file del segmento WAL dal server di database principale alla replica. Il servizio principale opera in modalità di archiviazione continua, mentre ogni servizio in standby opera in modalità di ripristino continuo per leggere i file WAL. Questa replica è asincrona.
replica dei flussi di dati
Un metodo di replica in cui la replica si connette all'istanza principale e riceve continuamente una sequenza continua di modifiche. Poiché gli aggiornamenti arrivano tramite un flusso, questo metodo mantiene la replica più aggiornata con l'istanza principale rispetto alla replica di spedizione dei log. Sebbene la replica sia asincrona per impostazione predefinita, in alternativa puoi configurare la replica sincrona.
replica dei flussi fisici
Un metodo di replica che trasporta le modifiche alla replica. Questo metodo utilizza i record WAL che contengono le modifiche ai dati fisici sotto forma di indirizzi di blocchi dei dischi e modifiche byte per byte.
replica dei flussi di dati logica
Un metodo di replica che acquisisce le modifiche in base alla loro identità di replica (chiave primaria), offrendo un maggiore controllo su come vengono replicati i dati rispetto alla replica fisica. A causa delle limitazioni nella replica logica PostgreSQL, la replica dei flussi di dati logici richiede una configurazione speciale per una configurazione ad alta disponibilità. Questa guida illustra la replica fisica standard e non la replica logica.
tempo di attività
La percentuale di tempo in cui una risorsa lavora ed è in grado di fornire una risposta a una richiesta.
rilevamento guasti
Il processo di identificazione che si è verificato un errore dell'infrastruttura.
failover
Il processo di promozione dell'infrastruttura di backup o standby (in questo caso, il nodo di replica) in modo che diventi l'infrastruttura principale. Durante il failover, il nodo di replica diventa il nodo primario.
passaggio
Il processo di esecuzione di un failover manuale su un sistema di produzione. Una transizione verifica che il sistema stia funzionando correttamente oppure rimuove l'attuale nodo primario dal cluster per la manutenzione.
RTO (Recovery Time Objective)
La durata in tempo reale trascorsa per il completamento del processo di failover del livello dati. L'RTO dipende dalla quantità di tempo accettabile dal punto di vista aziendale.
RPO (Recovery Point Objective)
La quantità di perdita di dati (in tempo reale trascorso) che il livello dati deve sostenere a seguito del failover. L'RPO dipende dalla quantità di perdita di dati accettabile dal punto di vista aziendale.
di riserva
Il processo di ripristino del nodo primario precedente dopo la condizione che ha causato un failover viene risolto.
guarigione automatica.
La capacità di un sistema di risolvere i problemi senza l'intervento di un operatore umano.
partizione di rete
Una condizione in cui due nodi in un'architettura, ad esempio il nodo primario e quello replica, non riescono a comunicare tra loro sulla rete.
cervello diviso
Una condizione che si verifica quando due nodi contemporaneamente ritengono di essere il nodo primario.
gruppo di nodi
Un insieme di risorse di computing che forniscono un servizio. In questo documento, quel servizio è il livello di persistenza dei dati.
nodo testimone o quorum
Una risorsa di computing separata che aiuta un gruppo di nodi a determinare cosa fare quando si verifica una condizione di ripartizione del cervello.
elezioni primarie o leader
Il processo mediante il quale un gruppo di nodi sensibili al peer, inclusi i nodi di test, determina quale nodo deve essere il nodo principale.

Quando considerare un'architettura ad alta disponibilità

Le architetture ad alta disponibilità offrono maggiore protezione contro i tempi di inattività a livello di dati rispetto alle configurazioni dei database a nodo singolo. Per selezionare l'opzione migliore per il tuo caso d'uso aziendale, devi comprendere la tua tolleranza per i tempi di inattività e i rispettivi compromessi delle varie architetture.

Utilizza un'architettura ad alta disponibilità quando vuoi fornire un uptime a livello di dati maggiore per soddisfare i requisiti di affidabilità per i carichi di lavoro e i servizi. Se il tuo ambiente tollera un certo tempo di inattività, un'architettura ad alta disponibilità potrebbe introdurre costi e complessità inutili. Ad esempio, gli ambienti di sviluppo o test raramente richiedono un'elevata disponibilità a livello di database.

Valuta i tuoi requisiti per l'alta disponibilità

Di seguito sono riportate alcune domande che possono aiutarti a decidere quale opzione ad alta disponibilità PostgreSQL è più adatta alla tua attività:

  • Quale livello di disponibilità speri di raggiungere? Hai bisogno di un'opzione che consenta al servizio di continuare a funzionare solo in una singola zona o di completare un errore a livello di regione? Alcune opzioni di alta disponibilità sono limitate a un'area geografica, mentre altre possono riguardare più regioni.
  • Quali servizi o clienti si affidano al tuo livello dati e qual è il costo per la tua azienda in caso di tempi di inattività nel livello di persistenza dei dati? Se un servizio si rivolge solo a clienti interni che richiedono l'uso occasionale del sistema, probabilmente ha requisiti di disponibilità inferiori rispetto a un servizio rivolto ai clienti finali che serve i clienti in modo continuativo.
  • Qual è il tuo budget operativo? Il costo è un aspetto importante: per fornire alta disponibilità, è probabile che i costi di infrastruttura e archiviazione aumenteranno.
  • Quanto deve essere automatizzato il processo e quanto rapidamente serve per eseguire il failover? (Qual è il tuo RTO?) Le opzioni ad alta disponibilità variano in base alla velocità con cui il sistema può eseguire il failover ed essere disponibile per i clienti.
  • Puoi permetterti di perdere dati a causa del failover? (Qual è il tuo RPO?) A causa della natura distribuita delle topologie ad alta disponibilità, esiste un compromesso tra la latenza di commit e il rischio di perdita di dati a causa di un errore.

Come funziona l'alta disponibilità

Questa sezione descrive la replica di flussi di dati sincrona e in modalità flusso che sono alla base delle architetture PostgreSQL ad alta disponibilità.

Replica dei flussi di dati

La replica in modalità flusso è un approccio di replica in cui la replica si connette all'istanza principale e riceve in modo continuo un flusso di record WAL. Rispetto alla replica di spedizione dei log, la replica dei flussi di dati consente alla replica di rimanere più aggiornata con l'istanza principale. PostgreSQL offre la replica dei flussi di dati integrata a partire dalla versione 9. Molte soluzioni PostgreSQL ad alta disponibilità utilizzano la replica di flussi di dati integrata per fornire il meccanismo affinché più nodi di replica PostgreSQL vengano mantenuti sincronizzati con il principale. Molte di queste opzioni sono trattate nella sezione Architetture ad alta disponibilità di PostgreSQL più avanti in questo documento.

Ogni nodo di replica richiede risorse di calcolo e archiviazione dedicate. L'infrastruttura del nodo di replica è indipendente da quella principale. Puoi usare i nodi di replica come hot standby per gestire query client di sola lettura. Questo approccio consente il bilanciamento del carico delle query di sola lettura tra la replica principale e una o più repliche.

Per impostazione predefinita, la replica dei flussi di dati è asincrona; l'istanza principale non attende una conferma da una replica prima di confermare il commit della transazione sul client. Se un'istanza principale riscontra un errore dopo la conferma della transazione, ma prima che una replica riceva la transazione, la replica asincrona può comportare la perdita di dati. Se la replica viene promossa a nuova istanza primaria, tale transazione non sarà presente.

Replica dei flussi di dati sincroni

Puoi configurare la replica dei flussi di dati come sincrona scegliendo una o più repliche come standby sincrono. Se configuri la tua architettura per la replica sincrona, l'istanza principale non conferma un commit della transazione fino a quando la replica non conferma la persistenza della transazione. La replica dei flussi di dati sincroni offre una maggiore durabilità in cambio di una latenza di transazione maggiore.

L'opzione di configurazione synchronous_commit consente inoltre di configurare le seguenti garanzie di durabilità della replica progressiva per la transazione:

  • on [predefinito]: le repliche in standby sincrone scrivono le transazioni impegnate nel proprio WAL prima di inviare il riconoscimento all'istanza principale. L'utilizzo della configurazione on assicura che la transazione possa andare persa solo se la replica principale e tutte le repliche in standby sincrone riscontrano errori di archiviazione simultanei. Poiché le repliche inviano una conferma solo dopo aver scritto i record WAL, i client che eseguono una query sulla replica non vedranno le modifiche finché i rispettivi record WAL non vengono applicati al database di replica.
  • remote_write: le repliche in standby sincrone confermano la ricezione del record WAL a livello di sistema operativo, ma non garantiscono che il record WAL sia stato scritto su disco. Poiché remote_write non garantisce che il WAL sia stato scritto, la transazione può andare persa in caso di errori sia nel principale che in quello secondario prima della scrittura dei record. remote_write ha una durabilità inferiore rispetto all'opzione on.
  • remote_apply: le repliche in standby sincrone confermano la ricezione della transazione e l'applicazione riuscita al database prima di confermare il commit della transazione al client. L'utilizzo della configurazione remote_apply garantisce che la transazione sia persistente nella replica e che i risultati della query del client includano immediatamente gli effetti della transazione. remote_apply offre durabilità e coerenza maggiori rispetto a on e remote_write.

Architetture ad alta disponibilità PostgreSQL

Al livello base, l'alta disponibilità del livello dati è costituito dai seguenti elementi:

  • Meccanismo per identificare se si verifica un errore nel nodo primario.
  • Un processo per eseguire un failover in cui il nodo di replica viene promosso a nodo primario.
  • Un processo per modificare il routing delle query in modo che le richieste dell'applicazione raggiungano il nuovo nodo principale.
  • Facoltativamente, un metodo per eseguire il fallback dell'architettura originale utilizzando nodi primari e di replica pre-failover nelle capacità originali.

Le seguenti sezioni forniscono una panoramica delle seguenti architetture ad alta disponibilità:

  • Il modello Patroni
  • Estensione e servizio pg_auto_failover
  • MIG stateful e disco permanente a livello di regione

Queste soluzioni ad alta disponibilità riducono al minimo i tempi di inattività in caso di interruzione dell'infrastruttura o della zona. Quando scegli tra queste opzioni, bilancia la latenza e la durabilità del commit in base alle tue esigenze aziendali.

Un aspetto critico di un'architettura ad alta disponibilità è costituito dal tempo e dall'impegno manuale necessari per preparare un nuovo ambiente standby per il successivo failover o fallback. In caso contrario, il sistema può resistere a un solo guasto e il servizio non è protetto da una violazione dello SLA (accordo sul livello del servizio). Ti consigliamo di selezionare un'architettura ad alta disponibilità in grado di eseguire failover manuali (o switchover) con l'infrastruttura di produzione.

Alta disponibilità utilizzando il modello Patroni

Patroni è un modello di software open source (con licenza MIT) maturo e attivamente gestito che fornisce gli strumenti per configurare, eseguire il deployment e gestire un'architettura ad alta disponibilità di PostgreSQL. Patroni fornisce uno stato del cluster condiviso e una configurazione dell'architettura permanente in un archivio di configurazione distribuito (DCS). Le opzioni per l'implementazione di un DCS includono: etcd, Consul, Apache ZooKeeper o Kubernetes. Il seguente diagramma mostra i componenti principali di un cluster Patroni.

Un cluster Patroni ha un'interazione tra nodi PostgreSQL, DCS e agenti Patroni.

Figura 1. Diagramma dei componenti principali di un cluster Patroni.

Nella Figura 1, i bilanciatori del carico sono a carico dei nodi PostgreSQL, mentre gli agenti DCS e Patroni operano sui nodi PostgreSQL.

Patroni esegue un processo agente su ciascun nodo PostgreSQL. Il processo dell'agente gestisce il processo PostgreSQL e la configurazione dei nodi dati. L'agente Patroni si coordina con altri nodi tramite il DCS. Il processo dell'agente Patroni espone anche un'API REST su cui puoi eseguire query per determinare l'integrità e la configurazione dei servizi PostgreSQL per ciascun nodo.

Per rivendicare il proprio ruolo di appartenenza al cluster, il nodo primario aggiorna regolarmente la chiave leader in DCS. La chiave leader include una durata (TTL). Se il TTL scade senza un aggiornamento, la chiave leader viene rimossa dal DCS e l'elezione del leader inizia a selezionare una nuova primaria dal pool di candidati.

Il seguente diagramma mostra un cluster integro in cui il Nodo A aggiorna correttamente il blocco leader.

Un leader di gruppo integro aggiorna il blocco della leader mentre i candidati leader lo guardano.

Figura 2. Diagramma di un cluster integro.

La Figura 2 mostra un cluster integro: il Nodo B e lo smartwatch del Nodo C, mentre il Nodo A aggiorna correttamente la chiave leader.

Rilevamento errori

L'agente Patroni telegrafa continuamente lo stato di salute aggiornando la sua chiave nel DCS. Allo stesso tempo, l'agente convalida l'integrità di PostgreSQL. Se rileva un problema, esegue l'auto-fencing del nodo arrestando sé stesso o fa retrocedere il nodo a una replica. Come mostrato nel diagramma seguente, se il nodo interessato è il nodo principale, la chiave leader nel DCS scade e si verifica una nuova elezione di leader.

Un cluster con problemi elegge un nuovo leader dopo la scadenza della chiave leader esistente.

Figura 3. Diagramma di un cluster con problemi.

La Figura 3 mostra un cluster con problemi: un nodo primario inattivo non ha aggiornato di recente la propria chiave leader nel DCS e le repliche non leader ricevono una notifica che indica che la chiave leader è scaduta.

Sugli host Linux, Patroni esegue anche un watchdog a livello di sistema operativo sui nodi principali. Questo watchdog resta in ascolto dei messaggi keep-alive dal processo dell'agente Patroni. Se il processo non risponde e il keep-alive non viene inviato, il watchdog riavvia l'host. Il watchdog aiuta a evitare una condizione di split cervello in cui il nodo PostgreSQL continua a servire come principale, ma la chiave leader nel DCS è scaduta a causa di un errore dell'agente ed è stato eletto un principale diverso (leader).

Processo di failover

Se il blocco leader scade nel DCS, i nodi di replica del candidato iniziano un'elezione leader. Quando una replica rileva un blocco della leader mancante, ne controlla la posizione di replica rispetto alle altre repliche. Ogni replica utilizza l'API REST per ottenere le posizioni dei log WAL degli altri nodi di replica, come mostrato nel diagramma seguente.

Durante il processo di failover di Patroni, le repliche controllano la propria posizione nel log WAL.

Figura 4. Diagramma del processo di failover di Patroni.

La Figura 4 mostra le query sulla posizione dei log WAL e i relativi risultati dai nodi di replica attivi. Il nodo A non è disponibile e i nodi in stato integro B e C restituiscono la stessa posizione WAL a vicenda.

Il nodo più aggiornato (o i nodi se si trovano nella stessa posizione) tentano contemporaneamente di acquisire il blocco leader in DCS. Tuttavia, solo un nodo può creare la chiave leader nel DCS. Il primo nodo per creare correttamente la chiave leader è il vincitore della corsa leader, come mostrato nel seguente schema.

Un nodo crea una chiave leader nel DCS e diventa il nuovo primario.

Figura 5. Diagramma della razza leader.

La Figura 5 mostra una corsa di leader: due candidati leader tentano di ottenere il blocco leader, ma solo uno dei due nodi, il Nodo C, imposta con successo la chiave leader e vince.

Dopo aver vinto le elezioni leader, la replica si promuove come nuova primaria. A partire dal momento in cui la replica viene promossa, la nuova chiave principale aggiorna la chiave leader nel DCS per mantenere il blocco leader e gli altri nodi fungono da repliche.

Patroni fornisce anche lo strumento di controllo patronictl che consente di eseguire switchover per testare il processo di failover nodale. Questo strumento consente agli operatori di testare le proprie configurazioni ad alta disponibilità in produzione.

Routing delle query

Il processo dell'agente Patroni in esecuzione su ciascun nodo espone gli endpoint API REST che rivelano il ruolo attuale del nodo: primario o replica.

Endpoint REST Codice restituito HTTP se principale Codice restituito HTTP se replica
/primary 200 503
/replica 503 200

Poiché i controlli di integrità pertinenti cambiano le loro risposte se un determinato nodo cambia il proprio ruolo, un controllo di integrità del bilanciatore del carico può utilizzare questi endpoint per fornire informazioni sul routing del traffico dei nodi primari e di replica. Il progetto Patroni fornisce configurazioni di modelli per il bilanciatore del carico del proxy ad alta disponibilità. Il bilanciatore del carico di rete passthrough interno può utilizzare questi stessi controlli di integrità per fornire una funzionalità simile.

Procedura di riserva

Se si verifica un errore del nodo, un cluster viene lasciato in uno stato con prestazioni ridotte. Il processo di fallback di Patroni aiuta a ripristinare lo stato integro di un cluster ad alta disponibilità dopo un failover. Il processo di fallback gestisce il ritorno del cluster allo stato originale inizializzando automaticamente il nodo interessato come replica del cluster.

Ad esempio, un nodo potrebbe riavviarsi a causa di un errore del sistema operativo o dell'infrastruttura sottostante. Se il nodo è il primario e impiega più tempo del TTL della chiave leader per riavviarsi, viene attivata un'elezione leader e viene selezionato e promosso un nuovo nodo primario. Quando viene avviato il processo principale inattivo di Patroni, rileva che non ha il blocco leader, retrocede automaticamente a una replica e si unisce al cluster in questa capacità.

Se si verifica un errore non recuperabile del nodo, ad esempio un errore improbabile a livello di zona, devi avviare un nuovo nodo. Un operatore di database può avviare manualmente un nuovo nodo oppure puoi utilizzare un gruppo di istanze gestite a livello di regione (MIG) con un numero minimo di nodi per automatizzare il processo. Dopo la creazione del nuovo nodo, Patroni rileva che il nuovo nodo fa parte di un cluster esistente e inizializza automaticamente il nodo come replica.

Alta disponibilità con l'estensione e il servizio pg_auto_failover

pg_auto_failover è un'estensione PostgreSQL open source (licenza PostgreSQL) sviluppata attivamente. pg_auto_failover configura un'architettura ad alta disponibilità estendendo le funzionalità PostgreSQL esistenti. pg_auto_failover non ha dipendenze diverse da PostgreSQL.

Per utilizzare l'estensione pg_auto_failover con un'architettura ad alta disponibilità, sono necessari almeno tre nodi, ciascuno con PostgreSQL in esecuzione con l'estensione abilitata. Uno qualsiasi dei nodi può restituire un errore senza influire sull'uptime del gruppo di database. Una raccolta di nodi gestita da pg_auto_failover è chiamata formation. Il seguente diagramma mostra un'architettura pg_auto_failover.

Un'architettura pg_auto_failover contiene una formazione di nodi.

Figura 6. Diagramma di un'architettura pg_auto_failover.

La Figura 6 mostra un'architettura pg_auto_failover composta da due componenti principali: il servizio Monitor e l'agente Keeper. Sia Keeper che Monitor sono contenuti nell'estensione pg_auto_failover.

Servizio di monitoraggio

Il servizio pg_auto_failover Monitor viene implementato come estensione PostgreSQL; quando il servizio crea un nodo Monitor, avvia un'istanza PostgreSQL con l'estensione pg_auto_failover abilitata. Il monitor mantiene lo stato globale della formazione, ottiene lo stato del controllo di integrità dai nodi di dati PostgreSQL dei membri e orchestra il gruppo utilizzando le regole stabilite da una macchina a stati finiti (FSM). In base alle regole FSM per le transizioni di stato, il monitor comunica istruzioni ai nodi del gruppo per azioni come l'avanzamento, il retrocessione e le modifiche alla configurazione.

Agente Keeper

Su ogni nodo dati pg_auto_failover, l'estensione avvia un processo dell'agente Keeper. Questo processo Keeper osserva e gestisce il servizio PostgreSQL. Keeper invia aggiornamenti di stato al nodo Monitor e riceve ed esegue le azioni che quest'ultimo invia in risposta.

Per impostazione predefinita, pg_auto_failover configura tutti i nodi di dati secondari del gruppo come repliche sincrone. Il numero di repliche sincrone richieste per un commit si basa sulla configurazione number_sync_standby impostata nel Monitoring.

Rilevamento errori

Gli agenti Keeper sui nodi di dati primari e secondari si connettono periodicamente al nodo Monitor per comunicare il loro stato attuale e controllare se sono presenti azioni da eseguire. Il nodo Monitor si connette inoltre ai nodi di dati per eseguire un controllo di integrità mediante l'esecuzione delle chiamate API del protocollo PostgreSQL (libpq), imitando l'applicazione client PostgreSQL pg_isready(). Se nessuna di queste azioni ha esito positivo dopo un determinato periodo di tempo (30 secondi per impostazione predefinita), il nodo Monitoraggio determina che si è verificato un errore del nodo dati. Puoi modificare le impostazioni di configurazione di PostgreSQL per personalizzare le tempistiche di monitoraggio e il numero di nuovi tentativi. Per maggiori informazioni, consulta Failover e tolleranza di errore.

Se si verifica un errore in un nodo singolo, si verifica una delle seguenti condizioni:

  • Se il nodo dati non integro è primario, il servizio Monitoring avvia un failover.
  • Se il nodo dati non integro è secondario, il servizio Monitoring disabilita la replica sincrona per il nodo non integro.
  • Se il nodo che ha avuto esito negativo è il nodo Monitor, non è possibile eseguire il failover automatico. Per evitare questo single point of failure, devi assicurarti che siano attivi il monitoraggio e il ripristino di emergenza corretti.

Il seguente diagramma mostra gli scenari di errore e gli stati dei risultati della formazione descritti nell'elenco precedente.

Gli scenari di errore pg_auto_failover per gli errori dei nodi primari, secondari e di monitoraggio.

Figura 7. Diagramma degli scenari di errore pg_auto_failover.

Processo di failover

Ogni nodo di database nel gruppo ha le seguenti opzioni di configurazione che determinano il processo di failover:

  • replication_quorum: un'opzione booleana. Se replication_quorum è impostato su true, il nodo viene considerato come un potenziale candidato di failover
  • candidate_priority: un valore intero compreso tra 0 e 100. candidate_priority ha un valore predefinito di 50 che puoi modificare per influenzare la priorità di failover. Ai nodi viene assegnata la priorità come potenziali candidati di failover in base al valore candidate_priority. I nodi con un valore candidate_priority maggiore hanno una priorità più alta. Il processo di failover richiede che almeno due nodi abbiano una priorità candidata diversa da zero in qualsiasi formazione pg_auto_failover.

In caso di errore del nodo primario, i nodi secondari vengono considerati per la promozione a primari se hanno la replica sincrona attiva e se sono membri di replication_quorum.

I nodi secondari sono considerati per la promozione in base ai seguenti criteri progressivi:

  • Nodi con la priorità candidata più alta
  • Standby con la posizione del log WAL più avanzata pubblicata sul monitor
  • Selezione casuale come pausa finale

Un candidato di failover è un candidato in ritardo quando non ha pubblicato la posizione LSN più avanzata nel WAL. In questo scenario, pg_auto_failover orchestra un passaggio intermedio nel meccanismo di failover: il candidato in ritardo recupera i byte WAL mancanti da un nodo in standby con la posizione LSN più avanzata. Il nodo standby viene quindi promosso. Postgres consente questa operazione perché la replica a cascata consente a qualsiasi standby di agire come nodo upstream per un altro standby.

Routing delle query

pg_auto_failure non fornisce funzionalità di routing delle query lato server. pg_auto_failure, invece, si basa sul routing delle query lato client che utilizza il driver client ufficiale di PostgreSQL libpq. Quando definisci l'URI della connessione, il driver può accettare più host nella relativa parola chiave host.

La libreria client utilizzata dall'applicazione deve eseguire il wrapping di libpq o implementare la capacità di fornire più host affinché l'architettura supporti un failover completamente automatico.

Processi di fallback e di passaggio

Quando il processo Keeper riavvia un nodo non riuscito o avvia un nuovo nodo di sostituzione, il processo controlla il nodo Monitoraggio per determinare l'azione successiva da eseguire. Se un nodo con esito negativo e riavviato era in precedenza il nodo principale e Monitor ha già scelto un nuovo nodo primario in base al processo di failover, Keeper reinizializza questo nodo primario inattivo come replica secondaria.

pg_auto_failure fornisce lo strumento pg_autoctl, che consente di eseguire switchover per testare il processo di failover del nodo. Oltre a consentire agli operatori di testare le loro configurazioni ad alta disponibilità in produzione, lo strumento consente di ripristinare lo stato integro di un cluster ad alta disponibilità dopo un failover.

Alta disponibilità con MIG stateful e disco permanente a livello di regione

Questa sezione descrive un approccio ad alta disponibilità che utilizza i seguenti componenti Google Cloud:

  • disco permanente a livello di regione. Quando utilizzi dischi permanenti a livello di regione, i dati vengono replicati in modo sincrono tra due zone in una regione, quindi non è necessario utilizzare la replica dei flussi. Tuttavia, l'alta disponibilità è limitata esattamente a due zone in una regione.
  • Gruppi di istanze gestite stateful. Viene utilizzata una coppia di MIG stateful come parte di un piano di controllo per mantenere in esecuzione un nodo PostgreSQL principale. Quando il gruppo di istanze gestite stateful avvia una nuova istanza, può collegare il disco permanente a livello di regione esistente. In un singolo momento, solo uno dei due gruppi di istanze gestite avrà un'istanza in esecuzione.
  • Cloud Storage. Un oggetto in un bucket Cloud Storage contiene una configurazione che indica quale dei due gruppi di istanze gestite esegue il nodo del database principale e in quale gruppo di istanze gestite deve essere creata un'istanza di failover.
  • Controlli di integrità e riparazione automatica del gruppo di istanze gestite. Il controllo di integrità monitora l'integrità dell'istanza. Se il nodo in esecuzione non è integro, il controllo di integrità avvia il processo di riparazione automatica.
  • Logging. Quando la riparazione automatica interrompe il nodo principale, viene registrata una voce in Logging. Le voci di log pertinenti vengono esportate in un argomento del sink Pub/Sub utilizzando un filtro.
  • Cloud Functions basato su eventi. Il messaggio Pub/Sub attiva le funzioni Cloud Functions. Cloud Functions utilizza la configurazione in Cloud Storage per determinare quali azioni eseguire per ogni gruppo di istanze gestite stateful.
  • Bilanciatore del carico di rete passthrough interno. Il bilanciatore del carico fornisce il routing all'istanza attualmente in esecuzione nel gruppo. Ciò garantisce che una modifica dell'indirizzo IP dell'istanza, causata dalla ricreazione dell'istanza, venga astratta dal client.

Il seguente diagramma mostra un esempio di alta disponibilità che utilizza MIG stateful e dischi permanenti a livello di regione:

Un'alta disponibilità utilizza MIG stateful e dischi permanenti a livello di regione.

Figura 8. Diagramma di un'alta disponibilità che utilizza MIG stateful e dischi permanenti a livello di regione.

La Figura 8 mostra un nodo primario integro che gestisce il traffico client. I client si connettono all'indirizzo IP statico del bilanciatore del carico di rete passthrough interno. Il bilanciatore del carico instrada le richieste client alla VM attualmente in esecuzione come parte del gruppo di istanze gestite. I volumi di dati sono archiviati su dischi permanenti a livello di regione montati.

Per implementare questo approccio, crea un'immagine VM con PostgreSQL che viene avviata all'inizializzazione da utilizzare come modello di istanza del gruppo di istanze gestite. Devi inoltre configurare un controllo di integrità basato su HTTP (ad esempio pgDoctor) sul nodo. Un controllo di integrità basato su HTTP aiuta a garantire che sia il bilanciatore del carico sia il gruppo di istanze possano determinare l'integrità del nodo PostgreSQL.

Disco permanente a livello di regione

Per eseguire il provisioning di un dispositivo di archiviazione a blocchi che fornisce la replica sincrona dei dati tra due zone di una regione, puoi utilizzare l'opzione di archiviazione del disco permanente a livello di regione di Compute Engine. Un disco permanente a livello di regione può fornire un componente di base di base per implementare un'opzione ad alta disponibilità PostgreSQL che non si basa sulla replica di flussi di dati integrata di PostgreSQL.

Se l'istanza VM del nodo principale non è più disponibile a causa di un errore dell'infrastruttura o di un'interruzione a livello di zona, puoi forzare il collegamento del disco permanente a livello di regione a un'istanza VM nella zona di backup nella stessa regione.

Per collegare il disco permanente a livello di regione a un'istanza VM nella zona di backup, puoi eseguire una delle seguenti operazioni:

  • Mantieni un'istanza VM cold standby nella zona di backup. Un'istanza VM in standby a freddo è un'istanza VM arrestata che non dispone di un Persistent Disk a livello di regione montato, ma è un'istanza VM identica all'istanza VM del nodo principale. In caso di errore, la VM in modalità standby a freddo viene avviata e il disco permanente a livello di regione viene montato al suo interno. L'istanza in standby a freddo e quella del nodo principale hanno gli stessi dati.
  • Crea una coppia di MIG stateful utilizzando lo stesso modello di istanza. I MIG forniscono controlli di integrità e fungono da parte del piano di controllo. In caso di errore del nodo primario, viene creata un'istanza di failover nel gruppo di istanze gestite di destinazione in modo dichiarativo. Il gruppo di istanze gestite di destinazione è definito nell'oggetto Cloud Storage. Per collegare il disco permanente a livello di regione, viene utilizzata una configurazione per istanza.

Se l'interruzione del servizio dati viene identificata tempestivamente, l'operazione di collegamento forzato in genere viene completata in meno di un minuto, quindi è possibile raggiungere un RTO misurato in minuti.

Se la tua azienda è in grado di tollerare il tempo di inattività aggiuntivo necessario per rilevare e comunicare un'interruzione e per eseguire il failover manualmente, non è necessario automatizzare il processo di collegamento forzato. Se la tolleranza RTO è inferiore, puoi automatizzare il processo di rilevamento e failover. In alternativa, Cloud SQL per PostgreSQL fornisce anche un'implementazione completamente gestita di questo approccio ad alta disponibilità.

Processo di rilevamento e failover degli errori

L'approccio ad alta disponibilità utilizza le funzionalità di autohealing dei gruppi di istanze per monitorare l'integrità dei nodi utilizzando un controllo di integrità. Se un controllo di integrità non riesce, l'istanza esistente viene considerata non integro e viene arrestata. Questa interruzione avvia il processo di failover utilizzando Logging, Pub/Sub e la funzione Cloud Functions attivata.

Per soddisfare il requisito in base al quale il disco a livello di regione è sempre montato in questa VM, Cloud Functions utilizzerà uno dei due gruppi di istanze gestite per creare un'istanza in una delle due zone in cui è disponibile il disco permanente a livello di regione. In caso di errore del nodo, l'istanza di sostituzione viene avviata, in base allo stato persistente in Cloud Storage, nella zona alternativa.

Durante un errore a livello di zona, viene avviata un'istanza sostitutiva.

Figura 9. Diagramma di un errore a livello di zona in un gruppo di istanze gestite.

Nella figura 9, si è verificato un errore nel nodo primario precedente nella zona A e Cloud Functions ha configurato il gruppo di istanze gestite B per avviare una nuova istanza principale nella zona B. Il meccanismo di rilevamento degli errori è configurato automaticamente per monitorare l'integrità del nuovo nodo primario.

Routing delle query

Il bilanciatore del carico di rete passthrough interno instrada i client all'istanza che esegue il servizio PostgreSQL. Il bilanciatore del carico utilizza lo stesso controllo di integrità del gruppo di istanze per determinare se l'istanza è disponibile per gestire le query. Se il nodo non è disponibile perché è in fase di nuova creazione, le connessioni non riescono. Una volta eseguito il backup dell'istanza, i controlli di integrità iniziano a essere superati e le nuove connessioni vengono instradate al nodo disponibile. Questa configurazione non contiene nodi di sola lettura perché c'è un solo nodo in esecuzione.

Procedura di riserva

Se il nodo di database non supera il controllo di integrità a causa di un problema di hardware sottostante, il nodo viene ricreato su un'istanza sottostante diversa. A quel punto, l'architettura viene ripristinata allo stato originale senza ulteriori passaggi. Tuttavia, in caso di errore a livello di zona, la configurazione continuerà a essere eseguita con uno stato ridotto fino al ripristino della prima zona. Sebbene sia altamente improbabile, se si verificano errori simultanei in entrambe le zone configurate per la replica di Persistent Disk a livello di regione e il gruppo di istanze gestite stateful, l'istanza PostgreSQL non può essere ripristinata e il database non è disponibile per gestire le richieste durante l'interruzione.

Confronto tra le opzioni ad alta disponibilità

Le seguenti tabelle forniscono un confronto delle opzioni ad alta disponibilità disponibili in Paatroni, pg_auto_failover e nei gruppi di istanze gestite Stateful con dischi permanenti a livello di regione.

Configurazione e architettura

Patroni pg_auto_failover MIG stateful con dischi permanenti a livello di regione

Richiede un'architettura ad alta disponibilità, la configurazione DCS, il monitoraggio e gli avvisi. La configurazione dell'agente sui nodi di dati è relativamente semplice.

Non richiede dipendenze esterne diverse da PostgreSQL. Richiede un nodo dedicato come monitoraggio. Il nodo di monitoraggio richiede l'alta disponibilità e RE per garantire che non si tratti di un single point of failure (SPOF). Architettura composta esclusivamente da servizi Google Cloud. Viene eseguito un solo nodo di database attivo alla volta.

Configurabilità ad alta disponibilità

Patroni pg_auto_failover MIG stateful con dischi permanenti a livello di regione
Estremamente configurabile: supporta la replica sia sincrona che asincrona e consente di specificare i nodi che devono essere sincroni e asincroni. Include la gestione automatica dei nodi sincroni. Consente configurazioni ad alta disponibilità a più zone e più regioni. Il DCS deve essere accessibile. Simile a Patroni: molto configurabile. Tuttavia, poiché il monitoraggio è disponibile solo come singola istanza, qualsiasi tipo di configurazione deve prendere in considerazione l'accesso a questo nodo. Limitato a due zone in una singola regione con replica sincrona.

Può gestire la partizione di rete

Patroni pg_auto_failover MIG stateful con dischi permanenti a livello di regione
L'auto-fencing insieme a un monitor a livello di sistema operativo offre protezione contro il cervello diviso. Qualsiasi errore di connessione al DCS determina la retrocessione dell'istanza principale a replica e l'attivazione di un failover per garantire la durabilità sulla disponibilità. Utilizza una combinazione di controlli di integrità da quello principale a quello di monitoraggio e alla replica per rilevare una partizione di rete e, se necessario, fa retrocedere il dispositivo. Non applicabile: esiste un solo nodo PostgreSQL attivo alla volta, quindi non esiste una partizione di rete.

Configurazione client

Patroni pg_auto_failover MIG stateful con dischi permanenti a livello di regione
Trasparente per il client perché si connette a un bilanciatore del carico. Richiede che una libreria client supporti la definizione di più host nella configurazione, poiché non si trova facilmente davanti a un bilanciatore del carico. Trasparente per il client perché si connette a un bilanciatore del carico.

Automation dell'inizializzazione dei nodi PostgreSQL, gestione della configurazione

Patroni pg_auto_failover MIG stateful con dischi permanenti a livello di regione
Fornisce gli strumenti per gestire la configurazione PostgreSQL (patronictl edit-config) e inizializza automaticamente nuovi nodi o nodi riavviati nel cluster. Puoi inizializzare i nodi utilizzando pg_basebackup o altri strumenti come WALL-E e Barman. Inizializza automaticamente i nodi, ma è limitato all'utilizzo esclusivo di pg_basebackup durante l'inizializzazione di un nuovo nodo di replica. La gestione delle configurazioni è limitata alle configurazioni correlate a pg_auto_failover. Il gruppo di istanze stateful con disco condiviso elimina la necessità di inizializzazione dei nodi PostgreSQL. Poiché è sempre presente un solo nodo in esecuzione, la gestione della configurazione si trova su un singolo nodo.

Personalizzazione e completezza delle funzionalità

Patroni pg_auto_failover MIG stateful con dischi permanenti a livello di regione

Fornisce un'interfaccia hook per consentire la chiamata di azioni definibili dall'utente nei passaggi chiave, come la retrocessione o la promozione.

Configurabilità ricca di funzionalità come il supporto per diversi tipi di DCS, diversi mezzi per inizializzare le repliche e diversi modi per fornire la configurazione PostgreSQL.

Consente di configurare cluster in standby che consentono replica a cascata di cluster per facilitare la migrazione tra i cluster.

Limitato perché è un progetto relativamente nuovo. Non applicabile.

Maturità

Patroni pg_auto_failover MIG stateful con dischi permanenti a livello di regione
Project è disponibile dal 2015 e viene utilizzato in produzione da grandi aziende come Zalando e GitLab. Progetto relativamente nuovo annunciato all'inizio del 2019. Composta interamente da prodotti Google Cloud in disponibilità generale.

Passaggi successivi