🎨 Sysprovider Code
Sysprovider LogoWiki
🇪🇸Hosting español para ecommerce

Configuración avanzada de failover con PostgreSQL y repmgr

Actualizado el 27 de enero de 2026

Introducción

La alta disponibilidad (HA) en bases de datos PostgreSQL no es un lujo, es un requisito operativo en entornos de producción. Cuando el tiempo de inactividad se mide en segundos y las pérdidas económicas en miles de euros, una configuración de failover automatizada y fiable se convierte en la columna vertebral de la infraestructura. repmgr (Replication Manager) es la herramienta de referencia para gestionar clústeres de replicación lógica y failover en PostgreSQL, ofreciendo un control granular sobre la promoción de réplicas, la detección de fallos y la reconfiguración del clúster.

Este artículo profundiza en la configuración avanzada de un clúster de failover con PostgreSQL 16 y repmgr 5.4. No cubriremos la instalación básica de PostgreSQL ni los fundamentos de la replicación física; asumimos que ya tienes un par de servidores PostgreSQL sincronizados mediante streaming replication. Nos centraremos en la arquitectura, la configuración de repmgr, la automatización del failover y las estrategias de recuperación post-fallo.

Arquitectura del Clúster y Planificación

Antes de teclear un solo comando, debemos definir la topología del clúster. Para este artículo, utilizaremos una configuración de tres nodos:

  • Nodo Primario (PG1): 192.168.1.10 - El servidor de lectura/escritura inicial.
  • Nodo Standby (PG2): 192.168.1.20 - Réplica sincrónica o asíncrona.
  • Nodo Witness (PG3): 192.168.1.30 - Un nodo ligero que actúa como testigo para el quórum de failover y prevención de split-brain.

¿Por qué un nodo Witness?

En un clúster de dos nodos (primario + standby), si el primario falla, el standby puede promocionarse sin problemas. El problema surge si la red falla, no el servidor. En ese escenario, ambos nodos pueden creer que el otro ha muerto e intentar promocionarse, creando dos primarios (split-brain). El nodo witness actúa como un juez imparcial: solo se concede la promoción si el witness puede confirmar que el primario original está realmente inaccesible. Esto requiere un mínimo de tres nodos para formar quórum.

Requisitos de Red y Sistema

  • Resolución de nombres: Todos los nodos deben poder resolverse por nombre. Usaremos /etc/hosts para simplicidad.
  • Conectividad SSH sin contraseña: repmgr utiliza SSH para ejecutar comandos remotos durante el failover. La clave SSH del usuario postgres en cada nodo debe estar en los authorized_keys de los demás.
  • Puertos abiertos: PostgreSQL (5432), repmgr (por defecto usa SSH, pero puede configurarse un puerto dedicado).
  • Sincronización de tiempo (NTP): Esencial para la consistencia de los logs y la detección de fallos.

Instalación y Configuración de repmgr

repmgr está disponible en los repositorios oficiales de PostgreSQL (PGDG). Asumimos que tienes PostgreSQL 16 instalado desde PGDG.

Instalación en Todos los Nodos

# En PG1, PG2 y PG3
sudo apt-get install -y postgresql-16-repmgr

Configuración de repmgr.conf

El archivo de configuración principal de repmgr es /etc/repmgr/16/repmgr.conf. Debe ser idéntico en todos los nodos, excepto por el parámetro node_id y node_name.

Configuración Base (PG1 - Primario)

# /etc/repmgr/16/repmgr.conf
node_id=1
node_name='pg1'
conninfo='host=192.168.1.10 port=5432 user=repmgr dbname=repmgr'
data_directory='/var/lib/postgresql/16/main'

# Configuración de failover
failover=automatic
promote_command='/usr/bin/repmgr standby promote -f /etc/repmgr/16/repmgr.conf --log-to-file'
follow_command='/usr/bin/repmgr standby follow -f /etc/repmgr/16/repmgr.conf --log-to-file --upstream-node-id=%n'

# Monitoring
monitoring_history=yes
monitor_interval_secs=2
connection_check_type=ping
reconnect_attempts=6
reconnect_interval=10

# Logging
log_level=INFO
log_file='/var/log/postgresql/repmgr.log'

Explicación de parámetros clave:

  • conninfo: Cadena de conexión a la base de datos repmgr. Esta base de datos se crea en el primario y se replica a los standbys. repmgr almacena aquí el estado del clúster.
  • promote_command: Script que se ejecuta en el nodo que se va a promocionar. repmgr standby promote es el comando estándar.
  • follow_command: Script que se ejecuta en los standbys restantes para que sigan al nuevo primario. El token %n se reemplaza con el node_id del nuevo upstream.
  • monitor_interval_secs: Cada 2 segundos, repmgrd (el daemon de monitoreo) verifica la salud del primario.
  • connection_check_type=ping: Usa pg_isready para comprobar la conexión. Otras opciones: query (ejecuta una consulta) o connect (solo intenta conectar).
  • reconnect_attempts e interval: Número de reintentos y tiempo entre ellos antes de declarar un nodo como caído.

Configuración en PG2 (Standby)

# /etc/repmgr/16/repmgr.conf
node_id=2
node_name='pg2'
conninfo='host=192.168.1.20 port=5432 user=repmgr dbname=repmgr'
data_directory='/var/lib/postgresql/16/main'
failover=automatic
promote_command='/usr/bin/repmgr standby promote -f /etc/repmgr/16/repmgr.conf --log-to-file'
follow_command='/usr/bin/repmgr standby follow -f /etc/repmgr/16/repmgr.conf --log-to-file --upstream-node-id=%n'
monitoring_history=yes
monitor_interval_secs=2
connection_check_type=ping
reconnect_attempts=6
reconnect_interval=10
log_level=INFO
log_file='/var/log/postgresql/repmgr.log'

Configuración en PG3 (Witness)

# /etc/repmgr/16/repmgr.conf
node_id=3
node_name='pg3'
conninfo='host=192.168.1.30 port=5432 user=repmgr dbname=repmgr'
data_directory='/var/lib/postgresql/16/main'
failover=automatic
promote_command='/usr/bin/repmgr standby promote -f /etc/repmgr/16/repmgr.conf --log-to-file'
follow_command='/usr/bin/repmgr standby follow -f /etc/repmgr/16/repmgr.conf --log-to-file --upstream-node-id=%n'
monitoring_history=yes
monitor_interval_secs=2
connection_check_type=ping
reconnect_attempts=6
reconnect_interval=10
log_level=INFO
log_file='/var/log/postgresql/repmgr.log'

Nota importante: El nodo witness no necesita una instancia de PostgreSQL completa. repmgr puede funcionar con un directorio de datos vacío. Sin embargo, para simplificar, asumiremos que PostgreSQL está instalado y la base de datos repmgr es accesible desde todos los nodos.

Creación de la Base de Datos y el Usuario repmgr

En el nodo primario (PG1), ejecuta:

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

Edita pg_hba.conf para permitir conexiones desde todos los nodos:

# /etc/postgresql/16/main/pg_hba.conf
host    repmgr          repmgr          192.168.1.0/24          md5
host    replication     repmgr          192.168.1.0/24          md5

Recarga la configuración de PostgreSQL:

sudo -u postgres psql -c "SELECT pg_reload_conf();"

Registro del Primario y Clonación del Standby

En el primario (PG1), registra el nodo:

sudo -u postgres repmgr -f /etc/repmgr/16/repmgr.conf primary register

Ahora, en el standby (PG2), clona los datos del primario:

sudo -u postgres repmgr -h 192.168.1.10 -U repmgr -d repmgr -f /etc/repmgr/16/repmgr.conf standby clone --dry-run
# Si el dry-run es exitoso, ejecuta sin --dry-run
sudo -u postgres repmgr -h 192.168.1.10 -U repmgr -d repmgr -f /etc/repmgr/16/repmgr.conf standby clone

Inicia PostgreSQL en PG2 y registra el standby:

sudo systemctl start postgresql@16-main
sudo -u postgres repmgr -f /etc/repmgr/16/repmgr.conf standby register

Registro del Nodo Witness

En PG3, registra el witness:

sudo -u postgres repmgr -f /etc/repmgr/16/repmgr.conf witness register -h 192.168.1.10 -U repmgr -d repmgr

Verificación del Estado del Clúster

En cualquier nodo, ejecuta:

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

La salida debería ser similar a:

 ID | Name | Role    | Status    | Upstream | Location | Priority | Timeline | Connection string
----+------+---------+-----------+----------+----------+----------+----------+------------------------------------------
 1  | pg1  | primary | * running |          | default  | 100      | 1        | host=192.168.1.10 port=5432 user=repmgr dbname=repmgr
 2  | pg2  | standby |   running | pg1      | default  | 100      | 1        | host=192.168.1.20 port=5432 user=repmgr dbname=repmgr
 3  | pg3  | witness | * running | pg1      | default  | 0        |          | host=192.168.1.30 port=5432 user=repmgr dbname=repmgr

Automatización del Failover con repmgrd

repmgrd es el daemon de monitoreo que detecta fallos y ejecuta el failover automático. Debe ejecutarse en todos los nodos del clúster (incluyendo el witness).

Inicio del Daemon en Todos los Nodos

sudo systemctl enable repmgrd
sudo systemctl start repmgrd

Mecanismo de Detección de Fallos

repmgrd utiliza un sistema de votación. Cada nodo monitorea al primario. Si un standby detecta que el primario no responde, intenta contactar al witness y a otros standbys. Si la mayoría (quórum) está de acuerdo en que el primario está caído, se inicia el proceso de failover.

Parámetros de failover en repmgr.conf:

  • failover=automatic: Habilita la promoción automática.
  • priority: (Se define por nodo) Controla el orden de promoción. El standby con mayor prioridad (número más bajo) será promovido primero. Si falla, se prueba el siguiente.
  • replication_type=synchronous: (Opcional) Si se configura replicación síncrona, el failover es más seguro, pero impacta en la latencia de escritura.

Configuración de Prioridades

En repmgr.conf de PG2, podemos añadir:

priority=50

En un hipotético PG4 (otro standby), podríamos poner priority=100. En un failover, repmgr intentará promocionar el nodo con la prioridad más baja (50 en este caso). Si ese nodo no está disponible, promocionará el siguiente (100).

El Proceso de Failover Paso a Paso

  1. Detección: repmgrd en PG2 y PG3 detectan que PG1 no responde después de reconnect_attempts (6) intentos cada reconnect_interval (10 segundos).
  2. Votación: PG2 contacta a PG3 (witness). PG3 confirma que tampoco puede contactar a PG1. Se forma quórum (2 de 3 nodos).
  3. Promoción: repmgrd en PG2 ejecuta promote_command (repmgr standby promote). PG2 se convierte en el nuevo primario.
  4. Notificación: repmgr actualiza el estado del clúster en la base de datos repmgr.
  5. Seguimiento: PG3 (witness) ejecuta follow_command para apuntar al nuevo primario (PG2).
  6. Reconfiguración de aplicaciones: Este paso NO lo maneja repmgr. Debes tener un mecanismo externo (HAProxy, pgpool-II, o un script personalizado) para redirigir las conexiones de las aplicaciones al nuevo primario.

Estrategias Avanzadas de Failover y Recuperación

Failover Manual (Planificado)

Para mantenimiento, puedes forzar un failover manual sin tiempo de inactividad:

# En el nodo a promocionar (PG2)
sudo -u postgres repmgr standby switchover -f /etc/repmgr/16/repmgr.conf

switchover realiza una conmutación controlada: detiene la replicación, promociona PG2 y reconfigura PG1 para que sea standby de PG2. Es una operación segura y sin pérdida de datos.

Recuperación Post-Failover (Reincorporación del Antiguo Primario)

Una vez que el antiguo primario (PG1) se recupera (hardware reparado, red restablecida), no puede simplemente unirse al clúster como standby porque su timeline (historial de cambios) es diferente al del nuevo primario (PG2). Debe ser "re-clonado".

Procedimiento:

  1. Detén PostgreSQL en PG1:

    sudo systemctl stop postgresql@16-main
    
  2. Limpia los datos antiguos (¡CUIDADO!):

    sudo rm -rf /var/lib/postgresql/16/main/*
    
  3. Clona desde el nuevo primario (PG2):

    sudo -u postgres repmgr -h 192.168.1.20 -U repmgr -d repmgr -f /etc/repmgr/16/repmgr.conf standby clone
    
  4. Inicia PostgreSQL y registra el nodo:

    sudo systemctl start postgresql@16-main
    sudo -u postgres repmgr -f /etc/repmgr/16/repmgr.conf standby register --force
    

    La opción --force es necesaria porque repmgr detectará que el nodo ya existía en el clúster con un ID diferente.

Gestión de Split-Brain (Caso Extremo)

Un split-brain ocurre cuando la comunicación de red se pierde, pero ambos nodos permanecen activos. Si se promociona un standby mientras el primario original sigue vivo, tendremos dos primarios. repmgr intenta prevenirlo con el witness, pero no es infalible.

Detección: Ejecuta repmgr cluster show en ambos nodos. Si ambos se muestran como primary, hay split-brain.

Resolución:

  1. Identifica el primario "real": El que tiene los datos más recientes (timeline más alto) o el que las aplicaciones están usando.
  2. Degrada el otro primario: En el nodo que debe ser standby, ejecuta:
    sudo -u postgres repmgr standby follow -f /etc/repmgr/16/repmgr.conf --upstream-node-id=<ID_del_primario_real> --force
    
    Esto forzará a ese

¿Necesitas ayuda?Son dos de nuestros técnicos, Agustín y Mikel, y están disponibles para resolver cualquier problema.

Hablar con ellos ahora
Agustín y Mikel