--- title: "Keepalived y VRRP: IP virtual con failover en Ubuntu 24.04" description: "Configura Keepalived con VRRP en dos servidores Ubuntu 24.04 para compartir una IP virtual que pasa al nodo de respaldo si HAProxy o el servidor fallan." category: "Temas Avanzados" language: es source: https://cubepath.com/es/docs/temas-avanzados/keepalived-para-alta-disponibilidad-vrrp updated: 2026-09-25 --- # Keepalived y VRRP: IP virtual con failover en Ubuntu 24.04 Keepalived implementa el protocolo VRRP (*Virtual Router Redundancy Protocol*) en Linux: dos o más servidores comparten una IP virtual, uno de ellos la tiene asignada (MASTER) y, si deja de anunciarse o su servicio falla, otro (BACKUP) la asume en uno o dos segundos. Es la forma más sencilla de eliminar el punto único de fallo de un balanceador de carga. En esta guía configurarás Keepalived en dos servidores Ubuntu 24.04 que ejecutan HAProxy, con comprobación de salud del servicio, VRRP en modo unicast y un script de notificación, y probarás el failover. ## Cómo funciona VRRP - Cada nodo tiene una **prioridad** entre 1 y 254. El de mayor prioridad se convierte en MASTER, se asigna la IP virtual y envía anuncios VRRP (protocolo IP 112) cada segundo. - Los nodos BACKUP escuchan esos anuncios. Si dejan de recibirlos durante unas tres veces el intervalo de anuncio, el de mayor prioridad pasa a MASTER, se asigna la IP y envía un **ARP gratuito** para que los equipos de la red actualicen la MAC asociada a la IP. - Un **`vrrp_script`** comprueba periódicamente un servicio local (aquí, HAProxy). Si falla, el nodo pasa al estado FAULT y libera la IP aunque el servidor siga encendido. - Todos los nodos de una misma instancia comparten el mismo **`virtual_router_id`** (1-255), que debe ser único en ese segmento de red. ## Requisitos previos Necesitas: - Dos servidores con Ubuntu 24.04 LTS, por ejemplo VPS o servidores dedicados de CubePath, con un usuario no root con privilegios `sudo`. - Una red privada común entre ellos. En esta guía: | Nodo | IP privada | Papel inicial | |---|---|---| | `lb1` | `10.0.0.21` | MASTER | | `lb2` | `10.0.0.22` | BACKUP | - Una IP libre en la misma subred para la IP virtual: `10.0.0.100`. - HAProxy (o el servicio que quieras proteger) instalado y configurado igual en ambos nodos. Si aún no lo tienes, sigue primero la guía de balanceo de carga con HAProxy. > Importante: la IP virtual cambia de servidor anunciándose con ARP gratuito. Esto funciona en una red de capa 2 normal, pero muchas redes de nube filtran el tráfico de las IP que no están asignadas a una interfaz concreta. Confirma que tu red permite mover una IP entre los dos servidores antes de usar esta arquitectura. ## Paso 1: Instalar Keepalived En ambos nodos, instala el paquete: ```bash sudo apt update sudo apt install keepalived ``` Comprueba la versión: ```bash keepalived --version 2>&1 | head -n 1 ``` ```output Keepalived v2.2.8 ``` El servicio no arrancará todavía, porque Ubuntu no incluye un archivo de configuración por defecto. Averigua el nombre de la interfaz conectada a la red privada, lo necesitarás más adelante: ```bash ip -brief address ``` ```output lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 UP 203.0.113.21/24 eth1 UP 10.0.0.21/24 ``` En este ejemplo la red privada está en `eth1`. Sustitúyelo por el nombre que veas en tus servidores. ## Paso 2: Permitir VRRP en el cortafuegos VRRP no usa TCP ni UDP, sino su propio protocolo IP (112), que UFW no permite abrir con `ufw allow`. Añade una regla en `/etc/ufw/before.rules` en ambos nodos: ```bash sudo nano /etc/ufw/before.rules ``` Justo antes de la línea `COMMIT` final de la sección `*filter`, añade esta regla, que acepta VRRP solo desde la red privada: ```text # Allow VRRP from the private network (Keepalived) -A ufw-before-input -p 112 -s 10.0.0.0/24 -j ACCEPT ``` Recarga UFW: ```bash sudo ufw reload ``` Verifica que la regla está cargada: ```bash sudo iptables -S ufw-before-input | grep 112 ``` ```output -A ufw-before-input -s 10.0.0.0/24 -p vrrp -j ACCEPT ``` ## Paso 3: Permitir que HAProxy escuche en la IP virtual En el nodo BACKUP la IP virtual no está asignada, así que HAProxy fallaría al arrancar si su configuración usa `bind 10.0.0.100:80`. El parámetro del kernel `ip_nonlocal_bind` permite enlazar a una IP que todavía no existe en el sistema. Créalo en ambos nodos: ```bash echo "net.ipv4.ip_nonlocal_bind = 1" | sudo tee /etc/sysctl.d/60-keepalived.conf sudo sysctl --system ``` Comprueba el valor: ```bash sysctl net.ipv4.ip_nonlocal_bind ``` ```output net.ipv4.ip_nonlocal_bind = 1 ``` Si tu HAProxy escucha en todas las direcciones (`bind :80`), este paso no es estrictamente necesario, pero no hace daño. ## Paso 4: Crear un usuario para los scripts Keepalived ejecuta los scripts de comprobación con el usuario indicado en `script_user`. Con `enable_script_security` activado se niega a ejecutar scripts que puedan ser modificados por usuarios sin privilegios. Crea en ambos nodos un usuario de sistema dedicado: ```bash sudo useradd --system --no-create-home --shell /usr/sbin/nologin keepalived_script ``` ## Paso 5: Escribir el script de notificación Keepalived puede ejecutar un script cada vez que el nodo cambia de estado. Aquí lo usarás para dejar constancia en el registro del sistema; puedes ampliarlo para avisar a tu sistema de monitorización. Créalo en ambos nodos: ```bash sudo nano /usr/local/bin/keepalived-notify.sh ``` ```bash #!/usr/bin/env bash set -euo pipefail # Keepalived passes: $1 = INSTANCE or GROUP, $2 = name, $3 = new state type="$1" name="$2" state="$3" logger -t keepalived-notify "${type} ${name} changed to ${state} on $(hostname)" ``` Hazlo ejecutable y propiedad de root: ```bash sudo chown root:root /usr/local/bin/keepalived-notify.sh sudo chmod 755 /usr/local/bin/keepalived-notify.sh ``` ## Paso 6: Configurar Keepalived en el nodo MASTER En `lb1`, crea el archivo de configuración: ```bash sudo nano /etc/keepalived/keepalived.conf ``` ```text global_defs { router_id lb1 enable_script_security script_user keepalived_script } vrrp_script chk_haproxy { script "/usr/bin/systemctl is-active --quiet haproxy" interval 2 fall 2 rise 2 } vrrp_instance VI_1 { state MASTER interface eth1 virtual_router_id 51 priority 150 advert_int 1 unicast_src_ip 10.0.0.21 unicast_peer { 10.0.0.22 } virtual_ipaddress { 10.0.0.100/24 dev eth1 } track_script { chk_haproxy } notify /usr/local/bin/keepalived-notify.sh } ``` Puntos clave de esta configuración: - `chk_haproxy` comprueba cada 2 segundos que el servicio HAProxy está activo. Tras 2 fallos seguidos (`fall 2`), el nodo pasa a FAULT y libera la IP; tras 2 éxitos (`rise 2`) vuelve a participar. - `unicast_src_ip` y `unicast_peer` hacen que los anuncios VRRP se envíen directamente al otro nodo en lugar de a la dirección multicast `224.0.0.18`. Es la opción recomendada en redes de nube y en redes donde el multicast está filtrado, y evita interferir con otros grupos VRRP del mismo segmento. - `virtual_router_id 51` debe ser idéntico en ambos nodos y distinto de cualquier otro grupo VRRP de la red. - Cambia `eth1` por el nombre de tu interfaz privada. Valida la sintaxis: ```bash sudo keepalived -t -f /etc/keepalived/keepalived.conf && echo "OK" ``` ## Paso 7: Configurar Keepalived en el nodo BACKUP En `lb2`, crea el mismo archivo con cuatro diferencias: el `router_id`, el estado inicial, una prioridad menor y las IP de origen y del par intercambiadas: ```bash sudo nano /etc/keepalived/keepalived.conf ``` ```text global_defs { router_id lb2 enable_script_security script_user keepalived_script } vrrp_script chk_haproxy { script "/usr/bin/systemctl is-active --quiet haproxy" interval 2 fall 2 rise 2 } vrrp_instance VI_1 { state BACKUP interface eth1 virtual_router_id 51 priority 100 advert_int 1 unicast_src_ip 10.0.0.22 unicast_peer { 10.0.0.21 } virtual_ipaddress { 10.0.0.100/24 dev eth1 } track_script { chk_haproxy } notify /usr/local/bin/keepalived-notify.sh } ``` Valida también este archivo con `sudo keepalived -t -f /etc/keepalived/keepalived.conf`. ## Paso 8: Arrancar Keepalived y comprobar el estado Arranca el servicio y habilítalo en el arranque, primero en `lb1` y después en `lb2`: ```bash sudo systemctl enable --now keepalived ``` En `lb1`, comprueba que tiene asignada la IP virtual: ```bash ip -brief address show eth1 ``` ```output eth1 UP 10.0.0.21/24 10.0.0.100/24 ``` En `lb2` la interfaz solo debe mostrar `10.0.0.22/24`. Consulta el registro de cada nodo para ver su estado: ```bash sudo journalctl -u keepalived -n 20 --no-pager ``` En `lb1` verás una línea como: ```output Keepalived_vrrp[1234]: (VI_1) Entering MASTER STATE ``` Y en `lb2`, `(VI_1) Entering BACKUP STATE`. Desde otro equipo de la red privada, haz una petición a la IP virtual: ```bash curl -s http://10.0.0.100 ``` ## Paso 9: Probar el failover Deja en un equipo cliente un bucle que haga una petición por segundo a la IP virtual, para ver cuánto dura el corte: ```bash while sleep 1; do curl -s -o /dev/null -w "%{http_code}\n" --max-time 1 http://10.0.0.100; done ``` **Fallo del servicio.** En `lb1`, detén HAProxy: ```bash sudo systemctl stop haproxy ``` En unos 4 segundos (dos comprobaciones fallidas), `lb1` pasa a FAULT, libera la IP y `lb2` la asume. En `lb2`, `ip -brief address show eth1` mostrará ahora `10.0.0.100/24`, y el script de notificación habrá dejado constancia: ```bash sudo journalctl -t keepalived-notify --no-pager ``` ```output keepalived-notify[2345]: INSTANCE VI_1 changed to MASTER on lb2 ``` Vuelve a arrancar HAProxy en `lb1`. Como tiene mayor prioridad, recuperará la IP virtual: ```bash sudo systemctl start haproxy ``` **Fallo del servidor.** Apaga `lb1` o desconecta su interfaz privada. `lb2` dejará de recibir anuncios y asumirá la IP en unos 3 segundos. En el bucle del cliente verás como mucho unas pocas peticiones fallidas durante cada cambio. > Consejo: si prefieres que la IP no vuelva automáticamente a `lb1` cuando se recupera (evitando un segundo corte), pon `state BACKUP` en ambos nodos y añade `nopreempt` dentro de `vrrp_instance`. El nodo que tenga la IP la conservará hasta que falle. ## Solución de problemas **Ambos nodos están en MASTER (split-brain).** Los nodos no reciben los anuncios del otro. Comprueba que la regla de VRRP está cargada en UFW en los dos nodos, que `unicast_peer` apunta a la IP correcta y que `virtual_router_id` coincide. Puedes ver si llegan los anuncios con `tcpdump`: ```bash sudo tcpdump -ni eth1 vrrp ``` Deberías ver un paquete por segundo desde el nodo MASTER con su prioridad (`prio 150`). **El nodo entra en FAULT aunque HAProxy funciona.** Ejecuta el script como lo hace Keepalived para ver si falla: ```bash sudo -u keepalived_script /usr/bin/systemctl is-active haproxy ``` Revisa también `journalctl -u keepalived` por mensajes de `script security`, que indican permisos incorrectos en el script o su directorio. **La IP virtual no aparece en ningún nodo.** Suele ser un nombre de interfaz incorrecto en `interface` o `virtual_ipaddress`. El registro de Keepalived lo indica al arrancar. **La IP cambia de nodo pero los clientes no llegan.** Los equipos de la red siguen usando la MAC antigua o la red filtra la IP virtual. Comprueba desde un cliente con `ip neigh show 10.0.0.100` qué MAC tiene asociada y confirma con tu proveedor que la red permite IP adicionales no asignadas. **El estado cambia continuamente (flapping).** La comprobación de salud es demasiado sensible o la red pierde paquetes. Sube `fall` y `rise` en `vrrp_script` y revisa la pérdida de paquetes entre los nodos con `ping -c 100`. ## Conclusión Tienes dos balanceadores compartiendo una IP virtual con Keepalived: si HAProxy o el servidor activo fallan, el otro nodo asume la IP en segundos y los clientes siguen llegando a la misma dirección. Como siguientes pasos puedes añadir una segunda instancia VRRP con otra IP virtual y prioridades invertidas para repartir carga entre ambos nodos (activo-activo), ampliar el script de notificación para avisar a tu sistema de alertas, o pasar a Pacemaker y Corosync si necesitas gestionar más recursos que una IP y un servicio.