Cómo implementar balanceo de carga con HAProxy y keepalived en alta disponibilidad
Introducción
En entornos de producción modernos, la disponibilidad y el rendimiento de las aplicaciones web son requisitos no negociables. Un único servidor representa un punto único de fallo (SPOF) que puede provocar interrupciones del servicio, pérdida de ingresos y degradación de la experiencia del usuario. Para mitigar estos riesgos, se implementan arquitecturas de alta disponibilidad (HA) y balanceo de carga.
Este artículo técnico detalla la implementación de un sistema de alta disponibilidad y balanceo de carga utilizando dos herramientas estándar de la industria: HAProxy como balanceador de carga de capa 4 y 7, y Keepalived para proporcionar una IP virtual (VIP) compartida mediante el protocolo VRRP (Virtual Router Redundancy Protocol). El resultado es un clúster activo-pasivo de balanceadores que distribuye el tráfico de forma inteligente entre un conjunto de servidores backend, garantizando que, si un balanceador falla, el otro asume automáticamente sin intervención manual.
Arquitectura de la Solución
Antes de profundizar en la configuración, es crucial comprender el flujo de tráfico y los componentes involucrados.
Componentes Clave
- HAProxy: Software de balanceo de carga y proxy TCP/HTTP. Ofrece alta eficiencia, bajos requisitos de recursos y un rico conjunto de características como persistencia de sesión, terminación SSL, y estadísticas en tiempo real.
- Keepalived: Demonio que implementa el protocolo VRRP. Permite que dos o más servidores compartan una misma dirección IP virtual (VIP). Los servidores se organizan en un grupo (VRRP Instance), donde uno es el MASTER (activo) y los otros son BACKUP (pasivos). El MASTER responde por la VIP. Si falla, un BACKUP asume el rol y reivindica la VIP.
- Servidores Backend: Los servidores web o de aplicaciones reales (Apache, Nginx, Tomcat, etc.) que atienden las peticiones.
Flujo de Tráfico
- El tráfico de los clientes (usuarios) llega a la IP Virtual (VIP).
- Keepalived, ejecutándose en ambos balanceadores, se asegura de que la VIP esté siempre activa en el nodo MASTER actual.
- El nodo MASTER (por ejemplo,
lb-01) recibe el tráfico en la VIP y lo reenvía a HAProxy. - HAProxy, según su configuración, aplica el algoritmo de balanceo (roundrobin, leastconn, etc.) y distribuye la petición a uno de los servidores backend (
web-01,web-02,web-03). - La respuesta del servidor backend viaja de vuelta a través del balanceador (o directamente al cliente, si se configura modo DSR - Direct Server Return, aunque no es el estándar).
+--------+ VIP (192.168.1.100)
| Cliente |---------->
+--------+ |
|
v
+----------------------------------------------+
| Red Pública / Privada |
+----------------------------------------------+
|
v
+---------------------------+----------------------------+
| lb-01 (MASTER) | lb-02 (BACKUP) |
| HAProxy + Keepalived | HAProxy + Keepalived |
| IP Real: 192.168.1.10 | IP Real: 192.168.1.11 |
+---------------------------+----------------------------+
| ^
| (Solo MASTER responde) | (VRRP Heartbeat)
v |
+------------------------------------+
| Red de Backend (192.168.2.0/24) |
+------------------------------------+
| | |
v v v
+----------+ +----------+ +----------+
| web-01 | | web-02 | | web-03 |
| 192.168.2.10| 192.168.2.11| 192.168.2.12|
+----------+ +----------+ +----------+
Prerrequisitos y Consideraciones Iniciales
Requisitos de Hardware y Software
- 2 Servidores para los balanceadores (pueden ser físicos o VPS). Se recomiendan al menos 2 vCPU y 4 GB de RAM para HAProxy en entornos con tráfico medio-alto.
- 2 o más Servidores Backend para servir el contenido.
- Sistema Operativo: Debian 12 / Ubuntu 22.04 LTS (las configuraciones se basan en estos). CentOS/RHEL 9 también es válido con ligeras variaciones en los comandos.
- Red: Ambos balanceadores deben estar en la misma subred y tener conectividad con los servidores backend. Una red privada separada para el tráfico de backend es altamente recomendable por seguridad y rendimiento.
Topología de Red
| Componente | Interfaz | IP Real | VIP (Virtual) | Rol |
|---|---|---|---|---|
lb-01 | eth0 | 192.168.1.10/24 | 192.168.1.100/24 | MASTER (por defecto) |
lb-02 | eth0 | 192.168.1.11/24 | 192.168.1.100/24 | BACKUP |
web-01 | eth0 | 192.168.2.10/24 | N/A | Backend Web |
web-02 | eth0 | 192.168.2.11/24 | N/A | Backend Web |
web-03 | eth0 | 192.168.2.12/24 | N/A | Backend Web |
Nota Importante: La IP Virtual (VIP) debe ser una IP no utilizada en la misma subred que las IPs reales de los balanceadores. Keepalived se encargará de añadirla a la interfaz de red del nodo MASTER.
Instalación de Paquetes
El primer paso es instalar HAProxy y Keepalived en ambos balanceadores (lb-01 y lb-02).
# En ambos balanceadores (lb-01 y lb-02)
sudo apt update
sudo apt install -y haproxy keepalived
¿Por qué estos paquetes? haproxy proporciona el binario haproxy y los scripts de systemd. keepalived instala el demonio keepalived y su herramienta de configuración.
Configuración de Keepalived (VRRP)
Keepalived gestiona la IP Virtual. La configuración se encuentra en /etc/keepalived/keepalived.conf. Es crucial que la configuración sea ligeramente diferente en cada nodo para definir el rol (MASTER vs BACKUP).
Configuración en el Nodo MASTER (lb-01)
sudo nano /etc/keepalived/keepalived.conf
global_defs {
notification_email {
admin@example.com
}
notification_email_from keepalived@example.com
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_haproxy {
script "/usr/bin/killall -0 haproxy" # Verifica si el proceso haproxy existe
interval 2
weight 2
fall 2
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 101 # Prioridad más alta que el BACKUP
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip
}
track_script {
chk_haproxy
}
}
Configuración en el Nodo BACKUP (lb-02)
sudo nano /etc/keepalived/keepalived.conf
global_defs {
notification_email {
admin@example.com
}
notification_email_from keepalived@example.com
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_haproxy {
script "/usr/bin/killall -0 haproxy"
interval 2
weight 2
fall 2
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100 # Prioridad más baja que el MASTER
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip
}
track_script {
chk_haproxy
}
}
Explicación de la configuración de Keepalived:
vrrp_script chk_haproxy: Define un script de seguimiento.killall -0 haproxyno mata el proceso, sino que verifica su existencia (retorna 0 si existe, 1 si no). Si el script falla (HAProxy caído), Keepalived reduce el peso (weight -2) de la instancia VRRP, provocando que el otro nodo (con prioridad efectiva ahora más alta) asuma como MASTER.state: Define el rol inicial.MASTERintentará ser el activo;BACKUPesperará.interface: La interfaz de red física donde se gestionará la VIP.virtual_router_id: Un número único (1-255) que identifica el grupo VRRP. Debe ser el mismo en ambos nodos.priority: Define la prioridad del nodo. El nodo con la prioridad más alta se convierte en MASTER. El scriptchk_haproxypuede modificar esta prioridad dinámicamente.advert_int: Intervalo de anuncios VRRP en segundos.authentication: Autenticación simple entre los nodos VRRP para evitar intrusiones.virtual_ipaddress: La(s) IP(s) virtual(es) que se asignarán al nodo MASTER.track_script: Vincula el script de seguimiento a la instancia VRRP.
Alerta: El valor
vrrp_strictpuede causar comportamientos inesperados en algunas configuraciones de red. Si experimentas problemas con la VIP (no se asigna o se asigna a ambos nodos), comenta esta línea.
Configuración de HAProxy
La configuración principal de HAProxy se encuentra en /etc/haproxy/haproxy.cfg. Esta configuración es idéntica en ambos balanceadores.
sudo nano /etc/haproxy/haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# Opciones de rendimiento
maxconn 4096
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
# Frontend: Escucha en la VIP y puerto 80
frontend http-in
bind *:80
# bind *:443 ssl crt /etc/ssl/certs/example.com.pem # Para HTTPS
# Definir ACLs (Access Control Lists) para enrutamiento avanzado
acl is_static path_beg /static /images /css /js
acl is_api path_beg /api
# Usar backend específico según la ACL
use_backend static-servers if is_static
use_backend api-servers if is_api
# Backend por defecto
default_backend web-servers
# Estadísticas de HAProxy (protegidas por contraseña)
stats enable
stats uri /haproxy?stats
stats realm Haproxy\ Statistics
stats auth admin:StrongPassword123
stats refresh 5s
# Backend para servidores web generales
backend web-servers
balance roundrobin
# Persistencia de sesión basada en cookies
cookie SRVNAME insert indirect nocache
option httpchk GET /health HTTP/1.1\r\nHost:\ www.example.com
http-check expect status 200
server web-01 192.168.2.10:80 check cookie w01 inter 2000 fall 3 rise 2
server web-02 192.168.2.11:80 check cookie w02 inter 2000 fall 3 rise 2
server web-03 192.168.2.12:80 check cookie w03 inter 2000 fall 3 rise 2 backup
# Backend para contenido estático
backend static-servers
balance source
option httpchk GET /health
server static-01 192.168.2.10:8080 check
server static-02 192.168.2.11:8080 check
# Backend para API
backend api-servers
balance leastconn
option httpchk GET /api/health
server api-01 192.168.2.10:3000 check
server api-02 192.168.2.11:3000 check
server api-03 192.168.2.12:3000 check
Explicación de la configuración de HAProxy:
- global: Configura el demonio.
chrootmejora la seguridad.stats socketpermite la administración dinámica. - defaults: Valores por defecto para todos los frontends y backends.
option forwardforañade la cabeceraX-Forwarded-Forpara que los backend conozcan la IP real del cliente.option http-server-closemejora el rendimiento al cerrar las conexiones del lado del servidor pero mantenerlas del lado del cliente. - frontend http-in: Define el punto de entrada.
bind *:80escucha en todas las interfaces (incluyendo la VIP) en el puerto 80. - ACLs: Permiten enrutar el tráfico basado en reglas (path, header, etc.). En este ejemplo, las peticiones a
/staticvan a un backend específico. - backend web-servers: Define el grupo de servidores backend.
balance roundrobin: Distribuye las peticiones de forma equitativa entre los servidores disponibles.cookie SRVNAME insert indirect nocache: Inserta una cookie para mantener la persistencia de sesión (sticky session). Una vez que un cliente es asignado a un servidor, las siguientes peticiones van al mismo servidor.option httpchk: Define un chequeo de salud HTTP. HAProxy hará una peticiónGET /healtha cada servidor. Si el servidor responde con un código de estado diferente a 2xx o 3xx, se marca como DOWN.server: Define cada servidor backend.checkhabilita los chequeos de salud.inter 2000(intervalo de 2s).fall 3(marcar como DOWN tras 3 fallos).rise 2(marcar como UP tras 2 éxitos).backupconvierte al servidor en un respaldo que solo recibe tráfico si los demás están caídos.
Nota sobre la Persistencia: El uso de
cookiepara persistencia es más fiable que basarse en IP (balance source), ya que las IPs de los clientes pueden cambiar (NAT, proxies móviles).
Verificación de la Configuración
Antes de iniciar los servicios, es obligatorio verificar la sintaxis de los archivos de configuración.
# Verificar configuración de HAProxy
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
# Verificar configuración de Keepalived (no tiene una herramienta de verificación directa, pero se puede probar la
