TL;DR — Resumen Rápido

Guía completa de HAProxy para balanceo de carga TCP y HTTP con alta disponibilidad. ACLs, health checks, SSL, stick tables y failover con keepalived VRRP.

HAProxy es la implementación de referencia para balanceo de carga de código abierto. Mientras Nginx sirve también como servidor web y Caddy prioriza la facilidad de uso, HAProxy está diseñado específicamente para proxy y balanceo de carga, y eso se nota en cada benchmark. Esta guía cubre el stack completo de HAProxy: arquitectura, instalación en Ubuntu y RHEL, ajuste de global y defaults, configuración de frontend/backend con ACLs, todos los algoritmos de balanceo, health checks TCP y HTTP, terminación SSL/TLS, la página de estadísticas, stick tables, rate limiting, integración con rsyslog y una configuración completa de keepalived VRRP para alta disponibilidad en dos nodos.

Requisitos Previos

Antes de comenzar, asegúrate de tener:

  • Ubuntu 22.04/24.04 o RHEL 9/AlmaLinux 9 con acceso sudo
  • Al menos dos servidores de aplicación backend
  • Dos nodos HAProxy (para la sección de alta disponibilidad con keepalived)
  • Conocimientos básicos de TCP/IP y HTTP
  • HAProxy 2.6 o posterior (se recomienda la versión LTS)

Arquitectura de HAProxy

HAProxy se ejecuta como un proceso único basado en eventos (o un número configurable de procesos/hilos). Toda la E/S es no bloqueante y multiplexada, lo que permite a HAProxy gestionar decenas de miles de conexiones concurrentes con RAM mínima.

Un archivo de configuración tiene cuatro tipos de sección principales:

  • global — configuración global del proceso (maxconn, log, chroot, user/group, nbthread)
  • defaults — valores predeterminados heredados por todos los frontends y backends
  • frontend — escucha conexiones entrantes; aplica ACLs y enruta tráfico a backends
  • backend — define el grupo de servidores, algoritmo de balanceo y parámetros de health check
  • listen — combinación de frontend+backend, útil para la página de estadísticas o proxies TCP simples

El flujo del tráfico es: cliente → frontend → evaluación de ACLs → regla use_backend → backend → servidor.

Instalación

Ubuntu / Debian

sudo apt update
sudo apt install haproxy -y
haproxy -v

Para una versión LTS más reciente, añade el PPA oficial:

sudo add-apt-repository ppa:vbernat/haproxy-2.8 -y
sudo apt install haproxy=2.8.\* -y

RHEL / AlmaLinux / Rocky Linux

sudo dnf install haproxy -y
haproxy -v
sudo systemctl enable --now haproxy

Configuración Global y Defaults

Abre /etc/haproxy/haproxy.cfg y reemplaza el contenido estándar con una base lista para producción:

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
    maxconn 50000
    nbthread 4
    tune.ssl.default-dh-param 2048
    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    option  forwardfor
    option  http-server-close
    retries 3
    timeout connect  5s
    timeout client   30s
    timeout server   30s
    timeout http-keep-alive 10s
    timeout check    5s
    maxconn 3000

Parámetros clave explicados:

  • maxconn 50000 — límite global de conexiones; ajusta según la RAM disponible (~1 MB por 1000 conexiones)
  • nbthread 4 — ejecuta cuatro hilos en un sistema de cuatro núcleos; HAProxy 2.x es multihilo
  • option dontlognull — suprime logs de health checks sin payload
  • option forwardfor — inyecta la cabecera X-Forwarded-For en las peticiones proxy
  • retries 3 — reintentos de conexión fallida antes de marcar un servidor como caído
  • timeout connect 5s — tiempo máximo para establecer una conexión TCP con un backend

Configuración de Frontend

Un frontend define en qué escucha HAProxy y a dónde enruta el tráfico:

frontend http_front
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
    http-request redirect scheme https unless { ssl_fc }
    http-request set-header X-Forwarded-Proto https if { ssl_fc }

    # Definición de ACLs
    acl is_api  path_beg /api/
    acl is_static path_beg /static/ /assets/ /images/
    acl host_admin hdr(host) -i admin.example.com

    # Reglas de enrutamiento
    use_backend api_backend    if is_api
    use_backend static_backend if is_static
    use_backend admin_backend  if host_admin
    default_backend app_backend

Coincidencias de ACL más utilizadas:

CoincidenciaEjemploQué comprueba
path_begpath_beg /api/URI comienza con /api/
path_endpath_end .phpURI termina en .php
hdr(host)hdr(host) -i api.example.comCabecera Host (sin distinción de mayúsculas)
srcsrc 10.0.0.0/8Rango de IP del cliente
methodmethod POSTMétodo HTTP

Configuración de Backend

Un backend define el grupo de servidores y cómo se distribuye el tráfico:

backend app_backend
    balance roundrobin
    option httpchk GET /health HTTP/1.1\r\nHost:\ app.example.com

    server app1 10.0.0.10:8080 weight 3 maxconn 500 check inter 2s fall 3 rise 2
    server app2 10.0.0.11:8080 weight 3 maxconn 500 check inter 2s fall 3 rise 2
    server app3 10.0.0.12:8080 weight 1 maxconn 200 check inter 2s fall 3 rise 2
    server app_backup 10.0.0.20:8080 backup check inter 5s fall 2 rise 1

Algoritmos de Balanceo

AlgoritmoDirectivaMejor para
Round-robinbalance roundrobinPeticiones cortas y uniformes
RR ponderadobalance roundrobin + weight NServidores de capacidad mixta
Menos conexionesbalance leastconnTiempos de respuesta variables
Hash de IP origenbalance sourceAfinidad de sesión por IP del cliente
Hash de URIbalance uriServidores de caché
Hash de cabecerabalance hdr(User-Agent)Enrutamiento por cabecera HTTP

Health Checks

Health Check TCP (predeterminado)

HAProxy abre una conexión TCP para verificar que el puerto está escuchando:

backend tcp_backend
    balance leastconn
    server db1 10.0.0.30:5432 check inter 3s fall 2 rise 1
    server db2 10.0.0.31:5432 check inter 3s fall 2 rise 1

Health Check HTTP

Para backends HTTP, verifica que la aplicación devuelve un código de estado saludable:

backend app_backend
    option httpchk GET /health HTTP/1.1\r\nHost:\ app.example.com
    http-check expect status 200
    server app1 10.0.0.10:8080 check inter 2s fall 3 rise 2
    server app2 10.0.0.11:8080 check inter 2s fall 3 rise 2

Terminación SSL/TLS

HAProxy termina SSL en el frontend y reenvía TCP o HTTP sin cifrar a los backends. Combina certificado y clave privada en un PEM:

cat fullchain.pem privkey.pem > /etc/haproxy/certs/example.com.pem
chmod 600 /etc/haproxy/certs/example.com.pem

SNI multi-certificado (un directorio, HAProxy elige el certificado correcto automáticamente):

frontend https_front
    bind *:443 ssl crt /etc/haproxy/certs/
    http-request set-header X-Forwarded-Proto https
    http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    default_backend app_backend

Página de Estadísticas

La página de estadísticas integrada de HAProxy proporciona métricas de conexión en tiempo real:

listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s
    stats auth admin:changeme
    stats show-legends
    stats show-node
    stats hide-version

Accede en http://tu-servidor:8404/stats. Protege este puerto con una regla de firewall:

sudo ufw allow from 10.0.0.0/8 to any port 8404
sudo ufw deny 8404

Stick Tables para Persistencia de Sesión

Las stick tables rastrean asignaciones cliente→servidor en memoria compartida:

backend app_backend
    balance roundrobin
    stick-table type ip size 100k expire 30m
    stick on src
    server app1 10.0.0.10:8080 check
    server app2 10.0.0.11:8080 check

Para persistencia basada en cookies:

backend app_backend
    balance roundrobin
    cookie SERVERID insert indirect nocache
    server app1 10.0.0.10:8080 cookie app1 check
    server app2 10.0.0.11:8080 cookie app2 check

Rate Limiting con Stick Tables

Las stick tables de HAProxy también gestionan el rate limiting sin dependencias externas:

frontend http_front
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/
    stick-table type ip size 200k expire 10s store http_req_rate(10s)
    http-request track-sc0 src
    http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 }
    default_backend app_backend

Para límites más estrictos en rutas específicas (por ejemplo, el endpoint de login):

frontend http_front
    stick-table type ip size 50k expire 60s store http_req_rate(60s)
    http-request track-sc0 src if { path_beg /api/auth/ }
    http-request deny deny_status 429 if { path_beg /api/auth/ } { sc_http_req_rate(0) gt 10 }

Logging con rsyslog

HAProxy registra en un socket syslog. Configura rsyslog para escribir los logs de HAProxy en un archivo dedicado.

Crea /etc/rsyslog.d/49-haproxy.conf:

$AddUnixListenSocket /dev/log

:programname, startswith, "haproxy" {
  /var/log/haproxy.log
  stop
}

Reinicia rsyslog y HAProxy:

sudo systemctl restart rsyslog
sudo systemctl restart haproxy

HAProxy con Keepalived para Failover VRRP

keepalived ejecuta VRRP para asignar una IP virtual compartida entre dos nodos HAProxy. Si el nodo primario falla, el nodo de respaldo toma la IP virtual en uno o dos segundos.

Instalar keepalived

sudo apt install keepalived -y           # Ubuntu
sudo dnf install keepalived -y           # RHEL

Nodo primario — /etc/keepalived/keepalived.conf

vrrp_script chk_haproxy {
    script "killall -0 haproxy"
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 110
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass s3cur3p4ss
    }
    virtual_ipaddress {
        192.168.1.100/24
    }
    track_script {
        chk_haproxy
    }
}

Nodo de respaldo — /etc/keepalived/keepalived.conf

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass s3cur3p4ss
    }
    virtual_ipaddress {
        192.168.1.100/24
    }
}
sudo systemctl enable --now keepalived
ip addr show eth0 | grep 192.168.1.100

Tabla Comparativa de Balanceadores

CaracterísticaHAProxyNginxTraefikEnvoyAWS ALB
Balanceo TCPSí (nativo)
Health checks activosSí (integrado)Solo Plus
IU de estadísticasIntegradastub_statusDashboardAdmin APICloudWatch
Rate limitingStick tableslimit_reqMiddlewareFiltersWAF
Terminación SSL
HA/VRRPVia keepalivedVia keepalivedNo integradoNo integradoGestionado
Huella de recursosMuy bajaBajaMediaAltaGestionado
Mejor paraTCP+HTTP HAWeb + cachéContenedoresService meshAWS nativo

Resumen

HAProxy es el estándar de referencia para balanceo de carga TCP y HTTP en entornos Linux. Puntos clave:

  • Ajusta maxconn, nbthread y los timeouts en las secciones global y defaults antes que nada
  • Construye ACLs en el frontend con path_beg, hdr() y src; enruta a backends con use_backend
  • Elige leastconn para APIs HTTP, roundrobin para tráfico uniforme, y source o stick tables para persistencia de sesión
  • Añade siempre check inter 2s fall 3 rise 2 a cada línea de servidor y option httpchk a los backends HTTP
  • Termina SSL en el frontend con un archivo PEM combinado; varios certs en un directorio para SNI automático
  • Usa stick tables para persistencia de sesión y rate limiting sin dependencias externas
  • Combina HAProxy con keepalived VRRP para failover en menos de un segundo entre dos nodos

Artículos Relacionados