HAProxy e Keepalived: Load Balancer com Alta Disponibilidade para PME

1. Introdução

O HAProxy (High Availability Proxy) é um dos balanceadores de carga código aberto mais rápidos e fiáveis do mercado. Combinado com o Keepalived, que implementa o protocolo VRRP para failover automático, obtém-se uma solução de alta disponibilidade robusta sem custos de licenciamento — ideal para pequenas e médias empresas (PME).

Uma PME com dois ou três servidores web precisa de distribuir o tráfego entre eles e garantir que, se o balanceador principal cair, um secundário assuma automaticamente o endereço IP virtual. É exactamente isto que HAProxy + Keepalived entrega: load balancing na camada 4 (TCP) ou 7 (HTTP) com failover transparente em segundos.

ℹ Porquê HAProxy + Keepalived para PME?

Soluções comerciais como F5 BIG-IP ou Citrix ADC custam milhares de euros. HAProxy e Keepalived são gratuitos, código aberto (GPLv2), consomem poucos recursos (correm em VMs de 1 vCPU / 512 MB RAM) e suportam centenas de milhares de ligações simultâneas.

A topologia típica para PME é active-passive: dois nós balanceadores (lb1 e lb2) partilham um IP virtual (VIP). O lb1 é o MASTER e processa todo o tráfego; o lb2 fica em BACKUP pronto para assumir. Se o lb1 cair, o Keepalived detecta a falha em 3 segundos e o lb2 assume o VIP. Em active-active, ambos os nós processam tráfego simultaneamente usando DNS round-robin ou múltiplos VIPs — mais complexo mas dobra a capacidade.

Componente Função Porta típica
HAProxy Balanceamento de carga L4/L7 80 / 443
Keepalived Failover com VRRP (IP virtual) Protocolo 112 (VRRP)
Backend web Servidores Nginx/Apache reais 8080 / 8443

2. Instalar HAProxy

O HAProxy está disponível nos repositórios oficiais das principais distribuições Linux. Em Debian/Ubuntu, a instalação é directa com apt. Em RHEL/CentOS/AlmaLinux usa-se dnf.

2.1 Debian e Ubuntu

# Actualizar repositórios e instalar
sudo apt update
sudo apt install -y haproxy keepalived

# Verificar versão instalada
haproxy -v
# HAProxy versão 2.6.x

2.2 RHEL, AlmaLinux e Rocky Linux

# Instalar via dnf
sudo dnf install -y haproxy keepalived

# Activar arranque no boot
sudo systemctl enable haproxy keepalived

⚠ Atenção

As versões nos repositórios base podem ser antigas. Para HAProxy 2.8+ (recomendado), adicionar o PPA oficial em Ubuntu: sudo add-apt-repository ppa:vbernat/haproxy-2.8 ou compilar a partir do código-fonte disponível em haproxy.org.

Após a instalação, o ficheiro de configuração principal fica em /etc/haproxy/haproxy.cfg. O Keepalived usa /etc/keepalived/keepalived.conf. Ambos devem ser configurados em ambos os nós (lb1 e lb2).

3. Configurar Load Balancing L4/L7

O HAProxy opera em duas modalidades: modo L4 (TCP), que balanceia ligações raw sem inspeccionar o conteúdo HTTP, e modo L7 (HTTP), que analisa cabeçalhos, cookies e URLs para decisões mais inteligentes. Para a maioria das PME, o modo L7 (HTTP) é o mais adequado pois permite persistência por cookie, encaminhamento por URL e compressão.

3.1 Configuração base (modos L4 e L7)

# /etc/haproxy/haproxy.cfg

global
    log /dev/log local0
    maxconn 4096
    user haproxy
    group haproxy
    daemon

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

# Frontend HTTP (modo L7)
frontend web_http
    bind *:80
    default_backend servidores_web

# Backend com 3 servidores reais
backend servidores_web
    balance roundrobin
    option httpchk GET /health
    server web1 192.168.1.101:8080 check
    server web2 192.168.1.102:8080 check
    server web3 192.168.1.103:8080 check

# Alternativa: modo L4 (TCP) para base de dados
frontend db_front
    bind *:3306
    mode tcp
    default_backend db_back

backend db_back
    mode tcp
    balance leastconn
    server db1 192.168.1.201:3306 check
    server db2 192.168.1.202:3306 check

3.2 Algoritmos de balanceamento

Algoritmo Como funciona Quando usar
roundrobin Distribui pedidos em ronda Servidores com capacidade igual
leastconn Envia para o servidor com menos ligações Ligações longas (BD, WebSocket)
source Hash do IP de origem (afinidade) Sessões sticky sem cookies
uri Hash do URL (cache locality) CDN, caching reverse proxy

3.3 Health checks e persistência por cookie

# Health check HTTP personalizado
backend servidores_web
    balance roundrobin
    option httpchk GET /health HTTP/1.1\r\nHost:\ localhost
    http-check expect status 200
    cookie SERVERID insert indirect nocache
    server web1 192.168.1.101:8080 check cookie s1
    server web2 192.168.1.102:8080 check cookie s2
    server web3 192.168.1.103:8080 check cookie s3

# Parâmetros de health check avançados
# inter   — intervalo entre checks (2s por defeito)
# rise    — checks bem-sucedidos para marcar UP (2)
# fall    — checks falhados para marcar DOWN (3)
# Check a cada 2s, considera UP após 2 sucessos, DOWN após 3 falhas
    server web1 192.168.1.101:8080 check inter 2s rise 2 fall 3

A directiva cookie SERVERID insert injecta um cookie no cliente que garante que pedidos subsequentes vão sempre para o mesmo servidor. Isto é essencial para aplicações que guardam estado de sessão localmente (PHP sessions, Django, etc.). O httpchk envia um pedido HTTP real ao backend e verifica o código de resposta — mais fiável que um simples check TCP.

4. SSL Termination

No SSL termination, o HAProxy termina a ligação HTTPS, descifra o tráfego e comunica com os backends por HTTP simples. Isto reduz a carga nos servidores web (não precisam de processar TLS) e centraliza a gestão de certificados num único ponto. A alternativa é SSL passthrough (modo TCP), onde o HAProxy repassa a ligação cifrada directamente ao backend sem descifrar.

4.1 Configuração com certificados Let’s Encrypt

# /etc/haproxy/haproxy.cfg — secção frontend HTTPS

frontend web_https
    bind *:443 ssl crt /etc/haproxy/certs/app.pt.pem alpn h2,http/1.1
    redirect scheme https code 301 if !{ ssl_fc }

    # Extrair certificado + chave combinados
    # cat /etc/letsencrypt/live/app.pt/fullchain.pem \
    #     /etc/letsencrypt/live/app.pt/privkey.pem \
    #     > /etc/haproxy/certs/app.pt.pem
    # chmod 600 /etc/haproxy/certs/app.pt.pem

    # Headers de segurança
    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
    http-response set-header X-Content-Type-Options nosniff
    http-response set-header X-Frame-Options DENY

    default_backend servidores_web

# Redireccionar HTTP para HTTPS
frontend web_http
    bind *:80
    redirect scheme https code 301 if !{ ssl_fc }

4.2 Múltiplos certificados (SNI)

# Directório com todos os certificados PEM combinados
# Um ficheiro por domínio: app.pt.pem, blog.pt.pem, loja.pt.pem

frontend web_https
    bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1

    # Routing por SNI (Server Name Indication)
    acl is_loja hdr(host) -i loja.pt
    acl is_blog hdr(host) -i blog.pt
    use_backend loja_web if is_loja
    use_backend blog_web if is_blog
    default_backend servidores_web

💡 Dica

O parâmetro alpn h2,http/1.1 activa HTTP/2 no HAProxy. Os backends continuam a receber HTTP/1.1 (o HAProxy faz a conversão). Para renovar certificados Let’s Encrypt automaticamente, criar um hook no certbot que combina os ficheiros PEM e recarrega o HAProxy: systemctl reload haproxy.

5. Keepalived — Failover com VRRP

O Keepalived implementa o protocolo VRRP (Virtual Router Redundancy Protocol, RFC 5798) para gerir um endereço IP virtual (VIP) partilhado entre dois ou mais nós. O nó MASTER detém o VIP e responde a ARP. Os nós BACKUP monitorizam o MASTER através de anúncios VRRP multicast a cada 1 segundo. Se 3 anúncios consecutivos falham (3 segundos), o BACKUP com maior prioridade assume o VIP.

5.1 Topologia active-passive

# /etc/keepalived/keepalived.conf — NÓ lb1 (MASTER)

global_defs {
    router_id LB1
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass MinhaSenhaVRRP2026
    }

    virtual_ipaddress {
        192.168.1.100/24
    }

    # Track script: verificar se HAProxy está a correr
    track_script {
        check_haproxy
    }
}

# Script de verificação do HAProxy
vrrp_script check_haproxy {
    script "/etc/keepalived/check_haproxy.sh"
    interval 2
    fall 2
    rise 2
}
# /etc/keepalived/keepalived.conf — NÓ lb2 (BACKUP)

global_defs {
    router_id LB2
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass MinhaSenhaVRRP2026
    }

    virtual_ipaddress {
        192.168.1.100/24
    }

    track_script {
        check_haproxy
    }
}

vrrp_script check_haproxy {
    script "/etc/keepalived/check_haproxy.sh"
    interval 2
    fall 2
    rise 2
}

O script de verificação check_haproxy.sh confirma que o HAProxy está activo. Se o HAProxy cair mas o nó continuar online, o track_script reduz a prioridade do nó em 50 pontos, forçando o failover para o BACKUP:

#!/bin/bash
# /etc/keepalived/check_haproxy.sh
# Verifica se o HAProxy está a processar ligações

if pidof haproxy > /dev/null; then
    exit 0
else
    exit 1
fi

# Tornar executável:
# chmod +x /etc/keepalived/check_haproxy.sh

5.2 Topologia active-active

Em active-active, cada nó é MASTER de um VIP diferente e BACKUP do outro. O tráfego é distribuído entre os dois VIPs via DNS round-robin ou um registo DNS por geolocalização. Se um nó cair, o outro assume ambos os VIPs:

# lb1: MASTER do VIP 192.168.1.100, BACKUP do VIP 192.168.1.101
vrrp_instance VI_1 {
    state MASTER
    virtual_router_id 51
    priority 150
    virtual_ipaddress { 192.168.1.100/24 }
}

vrrp_instance VI_2 {
    state BACKUP
    virtual_router_id 52
    priority 100
    virtual_ipaddress { 192.168.1.101/24 }
}

# lb2: MASTER do VIP 192.168.1.101, BACKUP do VIP 192.168.1.100
vrrp_instance VI_1 {
    state BACKUP
    virtual_router_id 51
    priority 100
    virtual_ipaddress { 192.168.1.100/24 }
}

vrrp_instance VI_2 {
    state MASTER
    virtual_router_id 52
    priority 150
    virtual_ipaddress { 192.168.1.101/24 }
}
Feature Active-Passive Active-Active
VIPs 1 2 (um por nó)
Capacidade 50% (1 nó idle) 100% (ambos activos)
Complexidade Baixa Média (DNS round-robin)
Failover Automático (<3s) Automático (ambos VIPs)
Recomendado para PME (simplicidade) Alto tráfego

6. Estatísticas e Monitorização

O HAProxy inclui um painel de estatísticas web integrado que mostra em tempo real o estado de cada backend, ligações activas, taxa de pedidos, erros e tempo de resposta. Para PME, este painel é frequentemente suficiente sem precisar de ferramentas externas.

6.1 Activar o painel de estatísticas

# Adicionar ao haproxy.cfg

listen stats
    bind *:8404
    mode http
    stats enable
    stats uri /stats
    stats realm HAProxy\ Estatisticas
    stats auth admin:SenhaForte2026
    stats admin if TRUE
    stats refresh 10

Aceder em http://192.168.1.100:8404/stats com as credenciais definidas. O stats admin if TRUE permite accionar drain/UP/DOWN nos backends directamente pelo painel.

6.2 Métricas por socket e Prometheus

# Activar socket de runtime em haproxy.cfg
global
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s

# Comandos via socket (CLI)
echo "show info" | sudo socat /run/haproxy/admin.sock -
echo "show servers state" | sudo socat /run/haproxy/admin.sock -
echo "show sess" | sudo socat /run/haproxy/admin.sock -

# Para Prometheus, usar haproxy_exporter
# Exporta métricas no endpoint /metrics
# haproxy_exporter --haproxy.scrape-uri=unix:/run/haproxy/admin.sock
# Disponível em http://localhost:9101/metrics
Métrica Descrição Valor saudável
scur (current sessions) Ligações activas por servidor Distribuído igualmente
econ (connection errors) Erros de ligação ao backend 0
eresp (response errors) Erros HTTP do backend 0
rtime (response time) Latência média (ms) < 200ms
qmax (max queue) Máximo de pedidos em fila 0 (sem gargalo)

7. Erros Comuns e Lista de verificação

A maioria dos problemas com HAProxy e Keepalived resulta de configurações incorrectas, falta de verificação de sintaxe ou problemas de rede (firewall, ARP, multicast). Abaixo os erros mais frequentes e a lista de verificação final.

7.1 Erros frequentes

⚠ VIP não responde após failover

Causa: o firewall bloqueia o protocolo VRRP (protocolo 112). Solução: permitir VRRP em ambos os nós — sudo iptables -A INPUT -p vrrp -j ACCEPT ou sudo firewall-cmd --add-protocol=vrrp --permanent no firewalld.

⚠ Erro “Cannot bind socket” no arranque

Causa: outro processo já ocupa a porta (Nginx, Apache) ou o VIP ainda não foi atribuído pelo Keepalived. Solução: parar o processo conflituoso ou adicionar bind *:80 em vez de bind 192.168.1.100:80 para que o HAProxy escute em todas as interfaces.

⚠ Split-brain (ambos os nós como MASTER)

Causa: perda de conectividade entre os nós. Ambos se consideram MASTER e respondem por ARP, causando conflito. Solução: garantir que os nós estão na mesma VLAN/L2, usar garp_master_delay e configurar preempt_delay 5 para evitar flapping.

⚠ Backends marcados como DOWN sem razão aparente

Causa: o health check httpchk envia um Host header inválido. Solução: especificar o header Host correctamente: option httpchk GET /health HTTP/1.1\r\nHost:\ app.pt e confirmar que o endpoint /health responde 200.

7.2 Comandos de diagnóstico

# Verificar sintaxe do HAProxy antes de reiniciar
sudo haproxy -c -f /etc/haproxy/haproxy.cfg

# Verificar estado do Keepalived e VRRP
sudo systemctl status keepalived
sudo journalctl -u keepalived -f

# Verificar qual nó tem o VIP
ip addr show eth0 | grep 192.168.1.100

# Verificar tabela ARP do cliente
arp -n | grep 192.168.1.100

# Capturar anúncios VRRP (protocolo 112)
sudo tcpdump -i eth0 -n vrrp

# Testar load balancing (deve ir rodando entre backends)
for i in $(seq 1 10); do curl -s -I http://192.168.1.100/ | head -1; done

# Verificar ligações activas no HAProxy
echo "show sess" | sudo socat /run/haproxy/admin.sock -

7.3 Lista de verificação de implantação

Passo Verificação Comando
1 Sintaxe HAProxy válida haproxy -c -f haproxy.cfg
2 Keepalived activo em ambos os nós systemctl status keepalived
3 VIP atribuído ao MASTER ip addr show eth0
4 Firewall permite VRRP iptables -L -n | grep vrrp
5 Health checks a funcionar Painel stats: backends UP
6 Certificado SSL válido openssl s_client -connect VIP:443
7 Teste de failover manual Parar HAProxy no MASTER e verificar VIP
8 Persistência de sessão Cookie SERVERID presente no navegador

✓ Resumo

HAProxy + Keepalived oferece alta disponibilidade profissional sem custos de licenciamento. Para uma PME com 2-3 servidores web, a topologia active-passive com um VIP e failover VRRP em 3 segundos é simples de implementar e robusta. As chaves do sucesso: health checks HTTP reais (não só TCP), track_script no Keepalived para detectar falhas do HAProxy, e firewall configurado para permitir o protocolo VRRP.