Guía práctica: configurar failover activo‑pasivo entre dos VPS con Keepalived, HAProxy y lsyncd para uploads sincronizados

Por · Publicado el · 10 min de lectura

Cable de red rojo en primer plano con equipos de rack de servidores desenfocados al fondo
Infraestructura de red y servidores — ideal para ilustrar alta disponibilidad y failover Foto: blickpixel / Pixabay

Cómo configurar failover activo‑pasivo entre dos VPS con Keepalived, HAProxy y lsyncd para sincronizar uploads. Este guía muestra la topología, prerequisitos y la configuración paso a paso para tener un VIP flotante con VRRP, HAProxy como entrada y lsyncd replicando uploads casi en tiempo real vía SSH. Enfocado en simplicidad y conmutación automática de nodo.

¿Qué es el failover activo‑pasivo con Keepalived, HAProxy y lsyncd?

El failover activo‑pasivo emplea dos VPS: una atiende (MASTER) y la otra queda en espera (BACKUP). Keepalived mueve una IP virtual (VIP) entre los nodos usando VRRP. HAProxy escucha en el VIP y enruta al servicio local. lsyncd replica los uploads del MASTER hacia el BACKUP por SSH.

Esta arquitectura reduce la indisponibilidad y mantiene los uploads coherentes. Es sencilla y no requiere un orquestador. A continuación se explica el papel de cada componente y los puntos de atención.

Componente Función Puntos a atención
Keepalived (VRRP) Mueve el VIP entre las VPS Unicast en la nube; prioridad; healthchecks; ARP/GARP
HAProxy Punto de entrada HTTP/HTTPS en el VIP Health check de la app; ip_nonlocal_bind
lsyncd (rsync/SSH) Replica uploads del MASTER → BACKUP Claves SSH; exclusiones; evitar split‑brain
Aplicación Atiende localmente en el nodo activo Uploads en directorio dedicado; permisos
Firewall/Kernel Permite VRRP/anuncio del VIP arp_announce/ignore; rutas; journald/logrotate

¿Qué prerequisitos y limitaciones en la VPS debo comprobar?

Verifica que ambas VPS compartan la misma subred o soporten VIP/floating IP. Algunos proveedores bloquean multicast o anuncios ARP. Si no hay L2 común, usa VRRP en unicast y prueba el anuncio del VIP.

Si el proveedor bloquea ARP/VRRP, el failover de VIP no funcionará. Alternativa: automatizar DNS con TTL bajo, asumiendo los trade‑offs de propagación. Asegura claves SSH entre nodos, NTP y un directorio exclusivo para uploads.

Para preparar el sistema y evitar cuellos de botella en kernel y logs, consulta este checklist para VPS Debian en producción: checklist técnico VPS Debian. Para políticas de retención y compresión del journald, consulta: Journald: retención y compresión en Ubuntu.

  • Dos VPS en la misma subred o soporte a VIP/floating IP
  • Acceso root por SSH para instalar y configurar paquetes
  • Reloj sincronizado (chrony o systemd‑timesyncd)
  • Directorio de uploads separado (p. ej.: /var/www/app/uploads)
  • Puertos: HTTP/HTTPS para HAProxy; VRRP unicast entre los nodos
  • Rotación de logs para no llenar disco

Preparar usuarios, directorios y claves SSH para lsyncd

Crea un usuario de sincronización con acceso restringido, ajusta permisos del directorio de uploads y cambia las claves SSH. Haz un respaldo del directorio de uploads antes de automatizar la sincronización.

En el ejemplo, nodo A = 10.0.0.10 (MASTER preferente) y nodo B = 10.0.0.11 (BACKUP). Ajusta IPs, rutas y usuarios a tu entorno.

# Em AMBAS as VPS (A e B):
sudo adduser --system --group --home /var/sync sync
sudo usermod -aG www-data sync

# Diretório de uploads da aplicação (se já existir, apenas ajuste permissões):
sudo mkdir -p /var/www/app/uploads
sudo chown -R www-data:www-data /var/www/app/uploads
sudo chmod 2755 /var/www/app/uploads  # setgid para manter o grupo

# Gerar chave no nó A e autorizar no nó B (para rsync via SSH):
sudo -u sync mkdir -p /var/sync/.ssh && sudo chown -R sync:sync /var/sync/.ssh && sudo chmod 700 /var/sync/.ssh
sudo -u sync ssh-keygen -t ed25519 -C sync@vpsA -f /var/sync/.ssh/id_ed25519 -N ""
ssh-copy-id -i /var/sync/.ssh/id_ed25519.pub [email protected]

# Segurança no nó B (opcional avançado): restringir comandos no authorized_keys
# command="rrsync /var/www/app/uploads",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-ed25519 AAAA... sync@vpsA

Cómo configurar Keepalived (VRRP) en unicast con VIP flotante

Instala Keepalived, habilita los sysctl necesarios para ARP e ip_nonlocal_bind y crea una instancia VRRP por nodo. Usa prioridad mayor en el primario. Un vrrp_script debe bajar la prioridad si HAProxy para.

Usa scripts de notify para controlar lsyncd: en el MASTER realiza un rsync de calentamiento e inicia lsyncd; en BACKUP/FAULT detén lsyncd. Ajusta IPs, interfaz y VIP según tu entorno.

# Em AMBAS as VPS (ajuste interface e IPs):
# /etc/sysctl.d/99-vrrp.conf
net.ipv4.ip_nonlocal_bind=1
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.default.arp_ignore=1
net.ipv4.conf.default.arp_announce=2

# Aplicar sysctl
# sysctl --system

# Instalar serviços essenciais
# apt-get update && apt-get install -y keepalived haproxy lsyncd

# /etc/keepalived/keepalived.conf (exemplo para o nó A - MASTER preferencial)
vrrp_script chk_haproxy {
    script "/usr/bin/pgrep -x haproxy"
    interval 2
    fall 2
    rise 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150                 # nó A mais prioritário
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass 7c0m53gr3t
    }

    unicast_src_ip 10.0.0.10
    unicast_peer {
        10.0.0.11
    }

    track_script {
        chk_haproxy
    }

    virtual_ipaddress {
        10.0.0.50/24 dev eth0 label eth0:vip
    }

    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault  "/etc/keepalived/notify.sh fault"
}

# No nó B, mude:
# state BACKUP
# priority 100
# unicast_src_ip 10.0.0.11
# unicast_peer { 10.0.0.10 }

# notify.sh para iniciar/parar o lsyncd conforme o papel do nó
# /etc/keepalived/notify.sh
#-----------------------------------
#!/usr/bin/env bash
set -euo pipefail
ROLE="$1"  # master|backup|fault
PEER_IP="10.0.0.11"   # do ponto de vista do nó A; ajuste no B
SRC_DIR="/var/www/app/uploads"
DST="sync@${PEER_IP}:${SRC_DIR}"
LOGTAG="keepalived-notify"

case "$ROLE" in
  master)
    logger -t "$LOGTAG" "MASTER: warm-up rsync -> $DST"
    rsync -az --inplace --partial "$SRC_DIR/" "$DST/" || true
    systemctl restart lsyncd
    ;;
  backup|fault)
    logger -t "$LOGTAG" "${ROLE^^}: stopping lsyncd"
    systemctl stop lsyncd || true
    ;;
  *)
    logger -t "$LOGTAG" "unknown role: $ROLE" ;;
esac
#-----------------------------------
# chmod 750 /etc/keepalived/notify.sh && chown root:root /etc/keepalived/notify.sh
# systemctl enable --now keepalived

Configurar HAProxy para atender en el VIP

HAProxy debe escuchar en 0.0.0.0; cuando el VIP esté en el nodo, los clientes llegarán por él. El health check del backend soporta el vrrp_script de Keepalived. Sustituye el puerto 8080 por el de tu aplicación.

Para TLS y ACME puedes ampliar la configuración más adelante. Más ideas y configuraciones en: HAProxy con Let's Encrypt y healthchecks.

# /etc/haproxy/haproxy.cfg (mínimo funcional)

global
    log /dev/log local0
    maxconn 2000
    daemon

defaults
    mode http
    log global
    option httplog
    timeout connect 5s
    timeout client  30s
    timeout server  30s

frontend fe_http
    bind 0.0.0.0:80
    http-request set-header X-Forwarded-Proto http
    default_backend be_app

backend be_app
    option httpchk GET /health
    server app1 127.0.0.1:8080 check

# Valide e habilite
# haproxy -c -f /etc/haproxy/haproxy.cfg && systemctl enable --now haproxy

Cómo sincronizar uploads solo en el nodo MASTER con lsyncd

lsyncd vigila cambios y lanza rsync vía SSH del MASTER al BACKUP. Para evitar split‑brain, debe ejecutarse únicamente en el nodo que tiene el VIP. notify.sh de Keepalived se encarga de esto.

Usa exclusiones para archivos temporales y activa --inplace para reducir escrituras duplicadas. Atención con --delete: úsalo solo después de validar la dirección de la sincronización.

-- /etc/lsyncd/lsyncd.lua
settings {
    logfile    = "/var/log/lsyncd.log",
    statusFile = "/var/run/lsyncd.status",
    nodaemon   = false,
    maxDelays  = 5,
}

default.rsyncssh {
    source    = "/var/www/app/uploads",
    host      = "[email protected]",   -- destino (nó B)
    targetdir = "/var/www/app/uploads",
    rsync = {
        archive  = true,
        compress = true,
        verbose  = true,
        _extra   = { "--inplace", "--partial" }
        -- Para espelhamento completo, adicione: "--delete" (use com cautela)
    },
    delay = 2,
    excludeFrom = "/etc/lsyncd.exclude"
}

-- /etc/lsyncd.exclude (exemplo)
-- *.tmp
-- .*swp
-- .DS_Store

-- Habilite o serviço (start/stop será controlado pelo Keepalived):
-- systemctl enable lsyncd

Cómo probar el failover y confirmar que funcionó

Verifica qué nodo tiene el VIP, realiza un upload de prueba y simula la caída del servicio. HAProxy debe exponer una ruta /health simple. El VIP debe migrar en segundos si el health check falla.

Tras estabilizar, valida que el archivo de prueba llegó al BACKUP. Revisa logs para analizar tiempos de conmutación y la sincronización.

# 1) Quem é o MASTER (deve mostrar 10.0.0.50 no nó ativo)
ip -br a | grep 10.0.0.50 || echo "VIP não está neste nó"

# 2) Teste HTTP pelo VIP
curl -sS http://10.0.0.50/health || echo "sem resposta"

# 3) Upload/arquivo de teste no MASTER e checar no BACKUP
TS=$(date +%s)
echo "ok-$TS" | sudo -u www-data tee /var/www/app/uploads/test-$TS.txt >/dev/null
ssh [email protected] "ls -l /var/www/app/uploads/test-$TS.txt"

# 4) Simule falha do HAProxy no MASTER e observe failover
sudo systemctl stop haproxy
sleep 3
curl -sS http://10.0.0.50/health || echo "sem resposta"

# 5) Logs úteis
journalctl -u keepalived -n 50 --no-pager
journalctl -u lsyncd -n 50 --no-pager

Buenas prácticas, observabilidad y problemas comunes

Monitorea logs, uso de disco y latencia de sincronización. Rota logs para que no afecten VRRP ni lsyncd. Mantén healthchecks simples y confiables. Evita que la aplicación acepte escrituras en el BACKUP.

Si algo falla, revisa red, ARP/VRRP y permisos del directorio de uploads. Para riesgos de split‑brain en escenarios de datos, consulta también cómo evitar split‑brain en failover de PostgreSQL: evitar split‑brain en failover de PostgreSQL.

  • Usa healthchecks rápidos (/health) en HAProxy y un track_script sencillo
  • Prioridad del MASTER mayor; no cambies virtual_router_id
  • Permite tráfico de VRRP unicast entre las IPs de las VPS
  • Revisa permisos del directorio (setgid y grupo de la app)
  • Rota logs de systemd‑journald para evitar disco lleno
  • Documenta runbooks y prueba el failover periódicamente

Preguntas frecuentes

¿Necesitan estar las dos VPS en la misma red para que el VIP funcione?

Sí. En la mayoría de los casos ambas VPS deben compartir la misma subred o usar el floating IP del proveedor. Sin L2 común o soporte a ARP/VRRP, el VIP no se propagará entre nodos. Alternativa: automatizar DNS con TTL bajo, aceptando la latencia de propagación.

¿Cómo evitar split‑brain en los uploads con lsyncd?

Ejecuta lsyncd únicamente en el nodo MASTER, controlado por el notify de Keepalived. Haz un rsync de calentamiento al asumir MASTER y, si usas --delete, valida la dirección de la sincronización. Evita que la app escriba en ambos nodos simultáneamente.

¿Cuál es la latencia típica de sincronización con lsyncd?

Es casi en tiempo real, pero depende de I/O, CPU, red y número de archivos. Los cambios se agrupan con pequeños retrasos (p. ej. 2 a 5 segundos) para eficiencia. En picos con muchos ficheros, la sincronización inicial puede tardar más antes de estabilizarse.

¿Funciona con IPv6 para el VIP?

Funciona si el proveedor admite anuncios de VIP IPv6 y la red permite Neighbor Advertisements (análogos a ARP en IPv4). En muchas nubes es más sencillo usar el floating IP del proveedor. Ajusta Keepalived y HAProxy para direcciones IPv6 si es necesario.

¿Puedo usar NFS o un almacenamiento compartido en lugar de lsyncd?

Sí, pero añade complejidad y posible punto único de fallo. NFS requiere tuning, reglas de firewall y pruebas de bloqueo. lsyncd es simple para uploads ocasionales y directorios pequeños‑medios. Para volúmenes grandes o escritura concurrente, evalúa un storage distribuido.

¿Quieres revisar tu topología de failover antes de producción?

Envía un esquema de tu red (IPs, subred, VIP deseado) y los requisitos de uploads. Una revisión externa ayuda a detectar puntos frágiles y definir pruebas de failover realistas.

Hablar sobre mi escenario

Ver también