Questa è la terza ed ultima parte dell’articolo dedicato a pg_rewind
. Negli ultimi due abbiamo visto come pg_rewind
può essere utile per correggere uno "split-brain" causato erroneamente durante la procedura di scambio dei ruoli tra un master ed uno standby, evitando di dover risincronizzare i nodi tramite un nuovo base backup. Abbiamo anche visto che questo è possibile per cluster di replica semplici che non coinvolgono più di due standby. In questo caso solo due nodi possono essere allineati dopo lo switchover, mentre gli altri necessitano di essere risincronizzati con un base backup. Dalla versione 9.6 di PostgreSQL, adesso è possibile utilizzare pg_rewind
su cluster di replica più complessi.
A partire da PostgreSQL 9.6, pg_rewind
ha una nuova funzionalità che gli permette di estendere l’orizzonte di visibilità della timeline di un intero cluster di alta disponibilità (HA), come quello di esempio nel mio precedente articolo. Adesso è infatti in grado di individuare il punto più recente nella timeline condiviso tra due o più nodi e risincronizzarli (e non più solo dall’ultimo checkpoint eseguito sul master prima della promozione dello standby, come nella versione 9.5).
Consideriamo quindi lo stesso esempio, ma adesso basato su PostgreSQL 9.6:
~$ # Set PATH variable
~$ export PATH=/usr/pgsql-9.6/bin:${PATH}
~$
~$ # This is the directory where we will be working on
~$ # Feel free to change it and the rest of the script
~$ # will adapt itself
~$ WORKDIR=/var/lib/pgsql/9.6
~$
~$ # Environment variables for PGDATA and archive directories
~$ MASTER_PGDATA=${WORKDIR}/master
~$ STANDBY1_PGDATA=${WORKDIR}/standby1
~$ STANDBY2_PGDATA=${WORKDIR}/standby2
~$ ARCHIVE_DIR=${WORKDIR}/archive
~$
~$ # Create the archive directory
~$ mkdir -p ${ARCHIVE_DIR}
~$
~$ # Create the HA cluster
~$ initdb --data-checksums -D ${WORKDIR}/master
~$ cat >> ${MASTER_PGDATA}/postgresql.conf <<EOF
~$ archive_command = 'cp %p ${ARCHIVE_DIR}/%f'
~$ archive_mode = on
~$ wal_level = hot_standby
~$ max_wal_senders = 10
~$ min_wal_size = '32MB'
~$ max_wal_size = '32MB'
~$ hot_standby = on
~$ wal_log_hints = on
~$ EOF
~$ cat >> ${MASTER_PGDATA}/pg_hba.conf <<EOF
~$ # Trust local access for replication
~$ # BE CAREFUL WHEN DOING THIS IN PRODUCTION
~$ local replication replication trust
~$ EOF
~$ pg_ctl -D /var/lib/pgsql/9.6/master -l ${WORKDIR}/master.log start
~$ psql -c "CREATE USER replication WITH replication"
~$ pg_basebackup -D ${STANDBY1_PGDATA} -R -c fast -U replication -x
~$ echo "port = 5433" >> ${STANDBY1_PGDATA}/postgresql.conf
~$ pg_ctl -D ${STANDBY1_PGDATA} -l ${WORKDIR}/standby.log start
~$ pg_basebackup -D ${STANDBY2_PGDATA} -R -c fast -U replication -x
~$ echo "port = 5434" >> ${STANDBY2_PGDATA}/postgresql.conf
~$ pg_ctl -D ${STANDBY2_PGDATA} -l ${WORKDIR}/standby2.log start
Simuliamo una promozione non voluta di uno dei due standby come nuovo master, lasciando gli altri nodi a formare un cluster HA indipendente:
~$ pg_ctl -D ${STANDBY1_PGDATA} promote
Adesso lo standby promosso procede nella timeline 2, mentre gli altri continuano sulla 1.
Completiamo lo "split-brain" creando una nuova tabella sul master che ha ancora in replica il secondo standby, e che non sarà visibile sul nodo appena promosso.
L’obiettivo adesso è quello di ricreare il cluster HA originale, con un master allineato alla situazione precedente lo "split-brain" (ovviamente senza la nuova tabella), che replichi due standby.
Dal momento che pg_rewind
, con PostgreSQL 9.6, permette di rendere ogni nodo un master nel cluster HA, l’idea è di:
pg_rewind
port
e primary_conninfo
nella configurazione (del vecchio master), in modo da seguire lo standby promossopg_rewind
port
e primary_conninfo
nella configurazione, in modo da seguire lo standby promosso a nuovo master del cluster HAVediamo come:
~$ pg_ctl -D ${STANDBY2_PGDATA} stop
waiting for server to shut down.... done
server stopped
~$ pg_ctl -D ${MASTER_PGDATA} stop
waiting for server to shut down.... done
server stopped
~$ pg_rewind --target-pgdata=${MASTER_PGDATA} --source-server="port=5433 user=postgres dbname=postgres"
servers diverged at WAL position 0/A0002C8 on timeline 1
rewinding from last common checkpoint at 0/A000220 on timeline 1
Done!
~$ pg_rewind --target-pgdata=${STANDBY2_PGDATA} --source-server="port=5433 user=postgres dbname=postgres"
servers diverged at WAL position 0/A0002C8 on timeline 1
rewinding from last common checkpoint at 0/A000220 on timeline 1
Done!
Una volta cambiate le configurazioni del vecchio master e dell’altro standby non promosso, riavviarli:
~$ pg_ctl -D ${MASTER_PGDATA} start
~$ pg_ctl -D ${STANDBY2_PGDATA} start
Adesso tutti e tre i nodi sono attivi e:
Ottimo!! Pensate se avessimo dovuto risincronizzare due nodi utilizzando un backup completo… :S
pg_rewind
è uno degli strumenti più utili in ambito HA: permette di evitare la risincronizzazione tramite l’esecuzione di nuovi base backup, in caso di "split-brain" accidentali. PostgreSQL 9.6 aggiunge nuove e potenti funzionalità a pg_rewind
, e permette nel caso di cluster HA complessi di ricreare lo stato originale a seguito di split-brain accidentali, partendo da qualsiasi nodo nel cluster per la resincronizzazione.
Come raccomandazione finale: prendete cura dell’archiviazione dei WAL! Generalmente, con la replica fisica, gli amministratori di database basano la loro architettura in contesto alta disponibilità solo sulla connessione streaming. Per poter usare pg_rewind
è necessario aver configurata l’archiviazione dei WAL, in modo da poterli prelevare in caso non siano più presenti sul master. Vi consiglio di considerare l’utilizzo di Barman, e la sua funzionalità get-wal
, per facilitare la gestione degli archivi e l’eventuale recupero dei WAl necessari.
This Post Has 0 Comments