postgresql postgres repmgr

repmgr

Desenvolvido pela 2ndQuadrant, o repmgr é um gerenciador de cluster de alta disponibilidade com boa integração com o Barman e diversas funcionalidades.

Ele usa a própria instância para registrar o estado e saúde dos nós, então depende da criação de uma extensão em algum banco de dados da instância. Também acompanha o andamento dos nós por uma conexão de replicação. Por isso, a versão do repmgr depende da versão do servidor.

A configuração é baseada em um arquivo de texto estilo ini, como por exemplo /etc/repmgr/16/repmgr.conf:

# identificador numérico único do nó dentro do cluster
node_id=1

# nome do nó no cluster
node_name='pg-1.local'

# string de conexão que outros nós podem usar para consultar o estado deste nó
conninfo='host=pg-1.local user=repmgr dbname=repmgr'

# diretório de dados
data_directory='/var/lib/pgsql/16/data'
# diretório dos binários da mesma versão do PostgreSQL
pg_bindir='/usr/pgsql-16/bin/'

# identificador do cluster no barman
barman_server='app'

# hostname do servidor do barman
barman_host='barman@pg-a.local'

# comandos de controle do nó
service_start_command   = 'sudo systemctl start postgresql-16'
service_stop_command    = 'sudo systemctl stop postgresql-16'
service_restart_command = 'sudo systemctl restart postgresql-16'
service_reload_command  = 'sudo systemctl reload postgresql-16'

As configurações mais importantes são:

Registro do primário

Com o primário no ar, assim como usuário, banco de dados e arquivo de configuração corretos, o registro do primário é feito como:

[postgres@pg-1 ~]$ repmgr primary register
INFO: connecting to primary database...
NOTICE: attempting to install extension "repmgr"
NOTICE: "repmgr" extension successfully installed
NOTICE: primary node record (ID: 1) registered

Registro da réplica

Depois do primário registrado no cluster de alta disponibilidade, e com o Barman também devidamente configurado, é possível clonar uma réplica:

[postgres@pg-2 ~]$ repmgr -h pg-1.local -U repmgr standby clone
NOTICE: destination directory "/var/lib/pgsql/16/data" provided
INFO: connecting to Barman server to verify backup for "app"
INFO: checking and correcting permissions on existing directory "/var/lib/pgsql/16/data"
INFO: creating directory "/var/lib/pgsql/16/data/repmgr"...
INFO: connecting to Barman server to fetch server parameters
INFO: connecting to source node
DETAIL: connection string is: host=pg-1.local user=repmgr
DETAIL: current installation size is 31 MB
WARNING: data checksums are not enabled and "wal_log_hints" is "off"
DETAIL: pg_rewind requires "wal_log_hints" to be enabled
NOTICE: retrieving backup from Barman...
receiving file list ...
1298 files to consider
PG_VERSION
[...]
NOTICE: standby clone (from Barman) complete
NOTICE: you can now start your PostgreSQL server
HINT: for example: sudo systemctl start postgresql-16
HINT: after starting the server, you need to register this standby with "repmgr standby register"

Então o serviço é iniciado (sudo systemctl start postgresql-16) e a réplica é registrada:

[postgres@pg-2 ~]$ repmgr -h pg-1.local -U repmgr standby register --upstream-node-id 1
INFO: connecting to local node "pg-2.local" (ID: 2)
WARNING: database connection parameters not required when the standby to be registered is running
DETAIL: repmgr uses the "conninfo" parameter in "repmgr.conf" to connect to the standby
INFO: connecting to primary database
INFO: standby registration complete
NOTICE: standby node "pg-2.local" (ID: 2) successfully registered

Testemunha

Uma testemunha não participa da replicação dos dados, mas participa do heartbeat que é feito através do protocolo de replicação do PostgreSQL. Isso significa que precisa existir um PostgreSQL mínimo em execução na máquina da testemunha, aceitando conexões das outras máquinas do cluster de alta disponibilidade.

Primeiro, crie uma instância na máquina testemunha e configure-a como as outras, ou seja, aceitando conexões externas das outras máquinas.

Crie um arquivo de configuração do repmgr simplificado:

# identificador numérico único do nó dentro do cluster
node_id=3

# nome do nó no cluster
node_name='pg-a.local'

# conexão
conninfo='host=pg-a.local user=repmgr dbname=repmgr'

# diretório de dados
data_directory='/var/lib/pgsql/16/data'

E registre o nó no cluster:

[postgres@pg-a ~]$ repmgr -h pg-1.local -U repmgr witness register
INFO: connecting to witness node "pg-a.local" (ID: 3)
INFO: connecting to primary node
NOTICE: attempting to install extension "repmgr"
NOTICE: "repmgr" extension successfully installed
INFO: witness registration complete
NOTICE: witness node "pg-a.local" (ID: 3) successfully registered

Status

É possível consultar o estado do cluster com:

[postgres@pg-a ~]$ repmgr cluster show
 ID | Name       | Role    | Status    | Upstream   | Location | Priority | Timeline | Connection string
----+------------+---------+-----------+------------+----------+----------+----------+-------------------------------------------
 1  | pg-1.local | primary | * running |            | default  | 100      | 1        | host=pg-1.local user=repmgr dbname=repmgr
 2  | pg-2.local | standby |   running | pg-1.local | default  | 100      | 1        | host=pg-2.local user=repmgr dbname=repmgr
 3  | pg-a.local | witness | * running | pg-1.local | default  | 0        | n/a      | host=pg-a.local user=repmgr dbname=repmgr

Failover manual e switchover

É possível fazer o chaveamento manual entre o primário e a réplica:

[postgres@pg-2 ~]$ repmgr standby switchover
NOTICE: executing switchover on node "pg-2.local" (ID: 2)
WARNING: 1 sibling nodes found, but option "--siblings-follow" not specified
DETAIL: these nodes will remain attached to the current primary:
  pg-a.local (node ID: 3, witness server)
NOTICE: local node "pg-2.local" (ID: 2) will be promoted to primary; current primary "pg-1.local" (ID: 1) will be demoted to standby
NOTICE: stopping current primary node "pg-1.local" (ID: 1)
NOTICE: issuing CHECKPOINT on node "pg-1.local" (ID: 1)
DETAIL: executing server command "sudo systemctl stop postgresql-16"
INFO: checking for primary shutdown; 1 of 60 attempts ("shutdown_check_timeout")
NOTICE: current primary has been cleanly shut down at location 0/5000028
NOTICE: promoting standby to primary
DETAIL: promoting server "pg-2.local" (ID: 2) using pg_promote()
NOTICE: waiting up to 60 seconds (parameter "promote_check_timeout") for promotion to complete
NOTICE: STANDBY PROMOTE successful
DETAIL: server "pg-2.local" (ID: 2) was successfully promoted to primary
INFO: local node 1 can attach to rejoin target node 2
DETAIL: local node's recovery point: 0/5000028; rejoin target node's fork point: 0/50000A0
NOTICE: setting node 1's upstream to node 2
WARNING: unable to ping "host=pg-1.local user=repmgr dbname=repmgr"
DETAIL: PQping() returned "PQPING_NO_RESPONSE"
NOTICE: starting server using "sudo systemctl start postgresql-16"
NOTICE: NODE REJOIN successful
DETAIL: node 1 is now attached to node 2
INFO: waiting for node "pg-1.local" (ID: 1) to connect to new primary; 1 of max 60 attempts (parameter "node_rejoin_timeout")
DETAIL: checking for record in node "pg-2.local"'s "pg_stat_replication" table where "application_name" is "pg-1.local"
NOTICE: node  "pg-2.local" (ID: 2) promoted to primary, node "pg-1.local" (ID: 1) demoted to standby
NOTICE: switchover was successful
DETAIL: node "pg-2.local" is now primary and node "pg-1.local" is attached as standby
NOTICE: STANDBY SWITCHOVER has completed successfully

E observar a inversão dos papéis:

[postgres@pg-2 ~]$ repmgr cluster show
 ID | Name       | Role    | Status    | Upstream   | Location | Priority | Timeline | Connection string
----+------------+---------+-----------+------------+----------+----------+----------+-------------------------------------------
 1  | pg-1.local | standby |   running | pg-2.local | default  | 100      | 1        | host=pg-1.local user=repmgr dbname=repmgr
 2  | pg-2.local | primary | * running |            | default  | 100      | 2        | host=pg-2.local user=repmgr dbname=repmgr
 3  | pg-a.local | witness | * running | pg-1.local | default  | 0        | n/a      | host=pg-a.local user=repmgr dbname=repmgr

Prática

Configure as máquinas pg-1, pg-2 e pg-a como um cluster de alta disponibilidade usando as configurações e comandos acima.