Configuración de repmgr en PostgreSQL para replicación con conmutación por error automática

PostgreSQL no incluye conmutación por error automática de fábrica.
Cuando el primario falla, alguien tiene que promover el secundario manualmente, lo que significa tiempo de inactividad.
repmgr añade un demonio de conmutación por error automática (repmgrd) que supervisa el clúster y promueve el standby en cuestión de segundos cuando el primario falla.
Esta guía explica cómo configurar un clúster PostgreSQL 18 de dos nodos con réplica por streaming y conmutación por error automática en Ubuntu 24.04, utilizando repmgr 5.x.
Cada paso se ha ejecutado en tiempo real en un clúster real y la salida ha sido verificada.


Una copia en espera de transmisión continua que requiere una promoción manual no es una configuración de alta disponibilidad, es una configuración de recuperación ante desastres.

La diferencia importa durante un incidente a las 3 AM.

PostgreSQL incluye los componentes básicos para la replicación, pero la lógica de failover automático reside en una herramienta separada.

repmgr es la herramienta a la que la mayoría de los administradores de bases de datos de PostgreSQL recurren primero: es ligera, está bien documentada y se integra limpiamente con systemd.

Esta guía construye la pila completa: replicación en streaming desde cero, repmgrd ejecutándose como un demonio y una falla automática probada que recupera el clúster sin intervención humana.


Índice


El medioambiente

Esta guía utiliza dos servidores Ubuntu 24.04 en la misma subred.

AnfitriónPIRol inicial
servidor1192.168.0.181Primario
servidor2192.168.0.182En espera

PostgreSQL 18 y repmgr 5.5.0 están instalados desde el repositorio PGDG en ambos servidores.


Paso 1 — Instalar PostgreSQL 18 y repmgr

PostgreSQL 18 no se encuentra en el repositorio predeterminado de Ubuntu 24.04.
En postgresql-common El paquete incluye un script oficial que agrega automáticamente el repositorio APT de PGDG y la clave de firma.

En ambos servidores:

sudo apt install -y postgresql-common
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh

sudo apt update
sudo apt install -y postgresql-18 postgresql-18-repmgr

Verifique la instalación:

psql --version
# Expected: psql (PostgreSQL) 18.x

repmgr --version
# Expected: repmgr 5.x

En server2, detenga PostgreSQL y elimine el directorio de datos predeterminado.
repmgr clonará el directorio de datos del primario a server2 en un paso posterior; si ya existe un directorio de datos, clonar réplica de repmgr se negará a proceder.

# On server2
sudo systemctl stop postgresql
sudo rm -rf /var/lib/postgresql/18/main

Paso 2 — Configurar PostgreSQL para la replicación por streaming

Estos parámetros deben configurarse en /etc/postgresql/18/main/postgresql.conf en ambos servidores antes de configurar la replicación.
repmgr requiere wal_log_hints y shared_preload_libraries — sin ellos, el proceso de reincorporación del nodo (pg_rewind) y el demonio repmgrd no funcionarán.

En ambos servidores, edita /etc/postgresql/18/main/postgresql.conf:

listen_addresses = ‘*' wal_level = replica max_wal_senders = 10 max_replication_slots = 10 hot_standby = on wal_log_hints = on shared_preload_libraries = ‘repmgr'

Estos parámetros requieren un reinicio de PostgreSQL para que surtan efecto.
No reinicies todavía — añade la pg_hba.conf entrar primero para que no reinicie dos veces.


Paso 3 — Permitir conexiones de replicación en pg_hba.conf

En ambos servidores, adjunta estas líneas a /etc/postgresql/18/main/pg_hba.conf.
Estos permiten la repmgr para conectarse tanto a consultas de gestión como a streaming de WAL desde cualquier nodo.

sudo tee -a /etc/postgresql/18/main/pg_hba.conf > /dev/null << 'EOF'

host    repmgr          repmgr          192.168.0.181/32        scram-sha-256
host    repmgr          repmgr          192.168.0.182/32        scram-sha-256
host    replication     repmgr          192.168.0.181/32        scram-sha-256
host    replication     repmgr          192.168.0.182/32        scram-sha-256
EOF

Ahora reinicia PostgreSQL en server1 (server2 aún no tiene directorio de datos):

# On server1
sudo systemctl restart postgresql

Paso 4: Cree el usuario y la base de datos repmgr

Ejecuta estos comandos en server1 (el principal) solamente.
El standby recibirá el esquema repmgr a través de la replicación en un paso posterior.

sudo -u postgres psql -c "CREATE USER repmgr WITH SUPERUSER REPLICATION LOGIN PASSWORD 'repmgr';"
sudo -u postgres psql -c "CREATE DATABASE repmgr OWNER repmgr;"

Añadir un .pgpass archivo para el usuario del sistema operativo postgres en ambos servidores para que repmgr pueda conectarse sin solicitud de contraseña.

En server1:

sudo -u postgres bash -c 'cat > /var/lib/postgresql/.pgpass <<EOF
192.168.0.181:5432:repmgr:repmgr:repmgr
192.168.0.182:5432:repmgr:repmgr:repmgr
192.168.0.181:5432:replication:repmgr:repmgr
192.168.0.182:5432:replication:repmgr:repmgr
EOF'
sudo chmod 600 /var/lib/postgresql/.pgpass

En server2:

sudo -u postgres bash -c 'cat > /var/lib/postgresql/.pgpass <<EOF
192.168.0.181:5432:repmgr:repmgr:repmgr
192.168.0.182:5432:repmgr:repmgr:repmgr
192.168.0.181:5432:replication:repmgr:repmgr
192.168.0.182:5432:replication:repmgr:repmgr
EOF'
sudo chmod 600 /var/lib/postgresql/.pgpass

Paso 5: Configurar repmgr en ambos nodos

Crear /etc/repmgr.conf en cada servidor.
En pg_bindir parámetro es requerido en Ubuntu — el pg_rewind binario no está en el PATH predeterminado para el usuario del sistema operativo postgres, y repmgr lo necesita durante la reintegración de nodos después de una conmutación por error.
En comando_inicio_servicio y comando_detener_servicio parámetros son requeridos: sin comando_detener_servicio, los cambios de sistema planeados fallan con el mensaje “no se pudo confirmar el apagado primario”; sin comando_inicio_servicio, un nodo no puede volver a unirse automáticamente al clúster después de ser rebobinado.

En server1:

sudo tee /etc/repmgr.conf > /dev/null << 'EOF'
node_id=1
node_name='server1'
conninfo='host=192.168.0.181 user=repmgr dbname=repmgr connect_timeout=2'
data_directory='/var/lib/postgresql/18/main'

failover=automatic
promote_command='repmgr standby promote -f /etc/repmgr.conf --log-to-file'
follow_command='repmgr standby follow -f /etc/repmgr.conf --upstream-node-id=%n --log-to-file'

use_replication_slots=yes
monitoring_history=yes
log_file='/var/log/repmgr/repmgr.log'

pg_bindir='/usr/lib/postgresql/18/bin'
service_start_command='sudo systemctl start postgresql'
service_stop_command='sudo systemctl stop postgresql'

node_rejoin_timeout=120
standby_reconnect_timeout=120
EOF

sudo chown postgres:postgres /etc/repmgr.conf
sudo chmod 640 /etc/repmgr.conf

En server2, solo node_id y nombre_nodo diferir

sudo tee /etc/repmgr.conf > /dev/null << 'EOF'
node_id=2
node_name='server2'
conninfo='host=192.168.0.182 user=repmgr dbname=repmgr connect_timeout=2'
data_directory='/var/lib/postgresql/18/main'

failover=automatic
promote_command='repmgr standby promote -f /etc/repmgr.conf --log-to-file'
follow_command='repmgr standby follow -f /etc/repmgr.conf --upstream-node-id=%n --log-to-file'

use_replication_slots=yes
monitoring_history=yes
log_file='/var/log/repmgr/repmgr.log'

pg_bindir='/usr/lib/postgresql/18/bin'
service_start_command='sudo systemctl start postgresql'
service_stop_command='sudo systemctl stop postgresql'

node_rejoin_timeout=120
standby_reconnect_timeout=120
EOF

sudo chown postgres:postgres /etc/repmgr.conf
sudo chmod 640 /etc/repmgr.conf

Crea el directorio de registros en ambos servidores:

sudo mkdir -p /var/log/repmgr
sudo chown postgres:postgres /var/log/repmgr

Paso 6 — Configurar claves SSH y sudo sin contraseña

Los cambios de configuración planificados requieren que repmgr se conecte por SSH desde un nodo al otro como el usuario del sistema operativo postgres y ejecute systemctl stop postgresql.
Este paso es obligatorio; sin él, los conmutadores fallan en el punto donde repmgr intenta detener el primario actual de forma remota.

Configuración de claves SSH:

En server1 — generar una clave y mostrar la clave pública:

# On server1
sudo -u postgres ssh-keygen -t ed25519 -N '' -f /var/lib/postgresql/.ssh/id_ed25519
sudo -u postgres cat /var/lib/postgresql/.ssh/id_ed25519.pub

En server2 — autoriza la clave pública de server1:

# On server2
sudo -u postgres mkdir -p /var/lib/postgresql/.ssh
# Paste the public key from server1 in place of <server1-public-key>
sudo -u postgres bash -c 'echo "<server1-public-key>" >> /var/lib/postgresql/.ssh/authorized_keys'
sudo chmod 700 /var/lib/postgresql/.ssh
sudo chmod 600 /var/lib/postgresql/.ssh/authorized_keys
sudo chown -R postgres:postgres /var/lib/postgresql/.ssh

Repite en la otra dirección: genera una clave en server2 y luego autorízala en server1:

# On server2
sudo -u postgres ssh-keygen -t ed25519 -N '' -f /var/lib/postgresql/.ssh/id_ed25519
sudo -u postgres cat /var/lib/postgresql/.ssh/id_ed25519.pub
# On server1
sudo -u postgres mkdir -p /var/lib/postgresql/.ssh
sudo -u postgres bash -c 'echo "<server2-public-key>" >> /var/lib/postgresql/.ssh/authorized_keys'
sudo chmod 700 /var/lib/postgresql/.ssh
sudo chmod 600 /var/lib/postgresql/.ssh/authorized_keys
sudo chown -R postgres:postgres /var/lib/postgresql/.ssh

Verificar desde cada nodo (tipo si se le pide que acepte la clave del host —solo la primera vez):

# On server1
sudo -u postgres ssh postgres@192.168.0.182 "echo OK"
# Expected: OK
# On server2
sudo -u postgres ssh postgres@192.168.0.181 "echo OK"
# Expected: OK

Sudo sin contraseña — en ambos servidores:

Crear /etc/sudoers.d/postgres-repmgr para permitir que el usuario postgres inicie y detenga PostgreSQL sin contraseña.
El camino debe ser /usr/bin/systemctl — en Ubuntu 24.04 aquí es donde vive systemctl, y sudo valida la ruta exacta.
El archivo debe tener permisos 440 — sudo ignora silenciosamente los archivos con permisos legibles por el mundo.

sudo tee /etc/sudoers.d/postgres-repmgr > /dev/null << 'EOF'
postgres ALL=(ALL) NOPASSWD: /usr/bin/systemctl start postgresql, /usr/bin/systemctl stop postgresql, /usr/bin/systemctl restart postgresql
EOF
sudo chmod 440 /etc/sudoers.d/postgres-repmgr

Verificar — no se espera solicitud de contraseña:

sudo -u postgres sudo systemctl status postgresql@18-main

Paso 7 — Registrar el Primario y Clonar el Secundario

En server1, registre la instancia de PostgreSQL en ejecución como nodo primario:

# On server1
sudo -u postgres repmgr -f /etc/repmgr.conf primary register

En server2, ejecuta primero una simulación para confirmar la conectividad:

# On server2
sudo -u postgres repmgr -h 192.168.0.181 -U repmgr -d repmgr \
  -f /etc/repmgr.conf standby clone --dry-run
# Expected: "STANDBY CLONE (target node \"server2\") would complete successfully"

Luego, ejecuta el clon real:

# On server2
sudo -u postgres repmgr -h 192.168.0.181 -U repmgr -d repmgr \
  -f /etc/repmgr.conf standby clone

En Ubuntu, postgresql.conf y pg_hba.conf vivir en /etc/postgresql/18/main/ — fuera del directorio de datos.
pg_basebackup solo clona el directorio de datos, por lo que estos archivos de configuración no se copian automáticamente.
Cópialos del servidor1 al servidor2:

# On server1 — stage the files for transfer
sudo cp /etc/postgresql/18/main/postgresql.conf /tmp/postgresql.conf
sudo cp /etc/postgresql/18/main/pg_hba.conf /tmp/pg_hba.conf
sudo chmod 644 /tmp/postgresql.conf /tmp/pg_hba.conf
# On server2 — copy and install
scp fernando@192.168.0.181:/tmp/postgresql.conf /tmp/postgresql.conf
scp fernando@192.168.0.181:/tmp/pg_hba.conf /tmp/pg_hba.conf
sudo cp /tmp/postgresql.conf /etc/postgresql/18/main/postgresql.conf
sudo cp /tmp/pg_hba.conf /etc/postgresql/18/main/pg_hba.conf

Inicie PostgreSQL en el servidor2 y regístrelo como un respaldo:

# On server2
sudo systemctl start postgresql
sudo -u postgres repmgr -f /etc/repmgr.conf standby register

Verifica el clúster desde cualquiera de los nodos:

sudo -u postgres repmgr -f /etc/repmgr.conf cluster show

Salida esperada:

 ID | Name    | Role    | Status    | Upstream | Location | Priority | Timeline | Connection string
----+---------+---------+-----------+----------+----------+----------+----------+----------------------------------------------------------
 1  | server1 | primary | * running |          | default  | 100      | 1        | host=192.168.0.181 user=repmgr dbname=repmgr connect_timeout=2
 2  | server2 | standby |   running | server1  | default  | 100      | 1        | host=192.168.0.182 user=repmgr dbname=repmgr connect_timeout=2

Paso 8. Inicie repmgrd para la conmutación por error automática

repmgrd es el demonio de monitoreo que activa la conmutación automática por error.
En Ubuntu 24.04, repmgr no incluye un archivo de unidad de systemd para repmgrd — inícielo manualmente utilizando --demonio.

En ambos servidores:

sudo -u postgres repmgrd -f /etc/repmgr.conf --daemonize

Verifica que el demonio esté en ejecución y no en pausa:

sudo -u postgres repmgr daemon status

Salida esperada:

 ID | Name    | Role    | Status    | repmgrd Active | PID  | Paused? | Upstream
----+---------+---------+-----------+----------------+------+---------+---------
 1  | server1 | primary | * running | yes            | XXXX | no      | n/a
 2  | server2 | standby |   running | yes            | XXXX | no      | server1

En ¿Pausado? no la columna es crítica — repmgrd se pausa a sí mismo después de un intento fallido de failover y no intentará otro failover mientras esté pausado.
Antes de cualquier prueba de conmutación por error, verifique que ambos nodos muestren ¿Pausado? no.
Si un nodo muestra ¿Pausado? sí, ejecutar:

sudo -u postgres repmgr daemon unpause

Paso 9 — Probar la conmutación por error automática

Detener PostgreSQL en server1 para simular un fallo primario:

# On server1
sudo systemctl stop postgresql

En server2, observa la reacción de repmgrd:

# On server2
sudo tail -f -n 50 /var/log/repmgr/repmgr.log

repmgrd espera un número configurable de intentos de reconexión (predeterminado: 6 intentos × 10 segundos = ~60 segundos) antes de promover el standby.
Cuando la promoción se completa, el registro muestra:

NOTICE: promoting standby to primary
NOTICE: STANDBY PROMOTE successful

Verificar la nueva topología:

# On server2
sudo -u postgres repmgr -f /etc/repmgr.conf cluster show

server2 es ahora el principal, server1 aparece como no disponible.


Paso 10: Reincorporar el nodo fallido como en espera

Después de la conmutación por error, server1 necesita ser reintegrado.
PostgreSQL puede haber avanzado en server2 mientras server1 estaba caído; los directorios de datos ahora divergieron.
repmgr usa pg_rewind para sincronizar server1 con la línea de tiempo del nuevo primario antes de iniciar la replicación.

En server1, verifica que PostgreSQL esté detenido, luego ejecuta:

# On server1
sudo systemctl status postgresql@18-main
# Expected: inactive (dead) — if active, stop it first: sudo systemctl stop postgresql

sudo -u postgres repmgr node rejoin \
  -d 'host=192.168.0.182 user=repmgr dbname=repmgr' \
  -f /etc/repmgr.conf \
  --force-rewind \
  --verbose

--forzar-rebobinado indicar a repmgr que se ejecute pg_rewind independientemente de la verificación de divergencia temporal.
En Ubuntu 24.04, la reconexión a veces falla por tiempo de espera antes de que PostgreSQL termine de iniciarse como respaldo.
Si el comando sale con un mensaje de tiempo de espera agotado pero el registro muestra que pg_rewind se completó con éxito, inicia PostgreSQL manualmente:

sudo systemctl start postgresql

Registrar el servidor server1 en los metadatos de repmgr e iniciar el demonio repmgrd.
En --forzar se requiere el indicador porque server1 se registró previamente como el principal:

sudo -u postgres repmgr -f /etc/repmgr.conf standby register --force
sudo -u postgres repmgrd -f /etc/repmgr.conf --daemonize

Verifica que ambos nodos estén ejecutándose:

sudo -u postgres repmgr -f /etc/repmgr.conf cluster show

Esperado: server1 listado como en espera, server2 como principal.


Preguntas frecuentes

¿repmgr funciona con PostgreSQL 18?

Sí.
repmgr 5.5.0 es compatible con PostgreSQL 18.
Instale desde el repositorio PGDG usando el paquete postgresql-18-repmgr.

¿Por qué falla mi cambio planeado con “no se pudo confirmar el apagado principal”?

El parámetro service_stop_command no está configurado en /etc/repmgr.conf.
repmgr necesita detener el primario actual a través de SSH durante un cambio y requiere un comando explícito para hacerlo.
Añada service_stop_command='sudo systemctl stop postgresql' a /etc/repmgr.conf en ambos nodos.

¿Por qué repmgrd no activa la conmutación por error a pesar de que el primario está caído?

repmgrd está en pausa.
El demonio se detiene a sí mismo después de un intento fallido de conmutación por error para prevenir la promoción en cascada en escenarios de split-brain.
Ejecute el estado del demonio repmgr para verificar la columna Paused? y el demonio repmgr unpause para reanudar la supervisión.

¿El nodo degradado se reinicia automáticamente después de un cambio de rol?

No.
repmgr detiene el primario antiguo durante el cambio pero no lo reinicia.
La documentación oficial de repmgr afirma: El primario original se detendrá en cualquier caso y deberá reintegrarse manualmente en el clúster de replicación.
Una vez que se complete el cambio de rol, ejecuta sudo systemctl start postgresql en el nodo degradado para que vuelva a ser un nodo en espera.

pg_rewind es una utilidad que se utiliza para acercar una base de datos PostgreSQL a un estado sincronizado con otra base de datos PostgreSQL. Es particularmente útil en escenarios de alta disponibilidad donde puede ser necesario reconectar un nodo de base de datos a un clúster después de que se haya separado.**¿Por qué es necesario para la reconexión de nodos?**Cuando un nodo de base de datos se separa de un clúster (por ejemplo, debido a un problema de red o una falla del servidor), el contenido de su base de datos puede volverse diferente al del nodo principal o de otros nodos del clúster. Si este nodo se intenta reconectar sin más intervención, podría existir el riesgo de conflictos de datos o de que el nodo reconectado se presente como el "estado más reciente" cuando en realidad no lo es, lo que podría llevar a la pérdida de datos o a una inconsistencia general del clúster.Aquí es donde interviene `pg_rewind`:1. **Identifica las diferencias:** `pg_rewind` compara los datos de la base de datos separada con una base de datos de origen (generalmente el nodo principal actual). Identifica qué bloques de datos han sido modificados en la base de datos separada y cuáles están desactualizados en comparación con la base de datos de origen.2. **Rebobina y reescribe:** En lugar de realizar una copia de seguridad y restauración completa (que puede ser lenta y costosa en términos de tiempo y recursos), `pg_rewind` "rebobina" la base de datos separada a un punto seguro en el tiempo (el último punto en el que estaba sincronizada con la fuente). Luego, reescribe selectivamente solo los bloques de datos que difieren y que son anteriores a ese punto de sincronización. Básicamente, copia los bloques de datos necesarios del origen a la base de datos separada.**En resumen:**`pg_rewind` es una herramienta de recuperación eficiente que permite que un nodo de base de datos previamente separado y con datos potencialmente divergentes se vuelva compatible y se sincronice rápidamente con un clúster existente. Evita la necesidad de operaciones de restauración completas, lo que minimiza el tiempo de inactividad y contribuye a la resiliencia del sistema de bases de datos.

pg_rewind resincroniza un directorio de datos de PostgreSQL que se ha desviado de la línea de tiempo primaria.
Esto sucede después de una conmutación por error: la antigua principal puede haber confirmado transacciones que no se replicaron antes de que fallara.
pg_rewind reemplaza esos bloques divergidos con los datos correctos del nuevo primario, permitiendo que el nodo reanude la replicación sin una copia de seguridad base completa.
wal_log_hints = on debe estar configurado en postgresql.conf para que pg_rewind funcione.


En resumen

La replicación en streaming de PostgreSQL está integrada; el failover automático requiere repmgr.
La configuración involucra seis partes móviles que deben estar correctas: configuración de PostgreSQL, configuración de repmgr, claves SSH entre los usuarios de postgres, sudo sin contraseña para la gestión de servicios, ranuras de replicación y repmgrd en ejecución y sin pausa.
Los puntos de fallo más comunes son los permisos del archivo sudoers (deben ser 440, no 644) y la ausencia de comando_detener_servicio para cambios.

Una vez que el clúster esté en funcionamiento, el siguiente paso es agregar una IP virtual flotante con Keepalived para que las aplicaciones siempre se conecten automáticamente a la principal actual. Consulte PostgreSQL repmgr con Keepalived Agregando un VIP Flotante.

Si estás construyendo un clúster de alta disponibilidad de PostgreSQL para un entorno de producción y buscas una segunda opinión sobre la arquitectura antes de comprometerte, ponerse en contacto

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *