Failover automatico con HAProxy e Keepalived: guida pratica
Come eliminare il single point of failure davanti a un servizio web: due bilanciatori, un IP virtuale e un failover che avviene in pochi secondi.

Capita spesso: due, tre server applicativi dietro un load balancer, e ci si sente coperti. Ma se il load balancer è uno solo, l'alta affidabilità è un'illusione. È lui il punto di guasto unico: quando si ferma, i server dietro, per quanto ridondati, diventano irraggiungibili. Questa guida mostra come chiudere quel buco con due strumenti collaudati, HAProxy e Keepalived, e con le configurazioni che si usano davvero.
Il problema: il bilanciatore come single point of failure
Un load balancer fa due cose: presenta un punto di ingresso unico e distribuisce il traffico sui backend. Finché è uno solo, però, eredita il difetto che doveva risolvere. La soluzione non è un bilanciatore più robusto: è un secondo bilanciatore, e un meccanismo che faccia passare il traffico da uno all'altro senza che il client se ne accorga.
L'architettura: due nodi, un IP virtuale
L'idea portante è l'IP virtuale (VIP). I client non si connettono all'indirizzo di un nodo specifico: si connettono al VIP. Il VIP, in ogni istante, è "posseduto" da uno solo dei due nodi, quello in stato MASTER. Se il MASTER cade, il nodo BACKUP rileva l'assenza e si prende il VIP. Da fuori, il servizio non si è mai spostato.
- Nodo A e nodo B: ognuno con HAProxy (bilancia) e Keepalived (gestisce il VIP).
- VIP (es.
192.0.2.10): l'indirizzo pubblico del servizio, su cui punta il DNS. - Backend: i server applicativi reali (
10.0.0.11,10.0.0.12...).
HAProxy si occupa della distribuzione, Keepalived del failover dell'indirizzo. Due ruoli, due strumenti.
HAProxy: il bilanciatore
La configurazione di HAProxy è identica sui due nodi. In /etc/haproxy/haproxy.cfg:
global
log /dev/log local0
maxconn 4096
defaults
mode http
log global
option httplog
timeout connect 5s
timeout client 30s
timeout server 30s
frontend web_in
bind 192.0.2.10:443 ssl crt /etc/haproxy/certs/site.pem
default_backend web_servers
backend web_servers
balance roundrobin
option httpchk GET /health
http-check expect status 200
server web1 10.0.0.11:80 check inter 2s fall 3 rise 2
server web2 10.0.0.12:80 check inter 2s fall 3 rise 2
I punti che contano:
- Il
bindè sul VIP, non sull'indirizzo del nodo. Per permettere a HAProxy di mettersi in ascolto su un IP che il nodo non possiede ancora, servenet.ipv4.ip_nonlocal_bind=1in/etc/sysctl.conf. option httpchk GET /healthconhttp-check expect status 200: HAProxy interroga attivamente un endpoint di salute su ogni backend.check inter 2s fall 3 rise 2: controlla ogni 2 secondi; dopo 3 fallimenti toglie il backend dal giro, dopo 2 successi lo riammette. Questo è il primo livello di affidabilità, quello sui server applicativi.
Verifica sempre la sintassi prima di ricaricare: haproxy -c -f /etc/haproxy/haproxy.cfg.
Keepalived: il failover dell'IP
Keepalived implementa il protocollo VRRP: i due nodi si scambiano annunci, e quando il BACKUP smette di sentire il MASTER si promuove. In /etc/keepalived/keepalived.conf, sul nodo A (MASTER):
vrrp_script chk_haproxy {
script "/usr/bin/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 <password-condivisa>
}
virtual_ipaddress {
192.0.2.10
}
track_script {
chk_haproxy
}
}
Sul nodo B (BACKUP) la configurazione è identica, con due differenze: state BACKUP e priority 100.
Il dettaglio che molti tralasciano è il vrrp_script. Senza, Keepalived sposta il VIP solo se l'intero nodo cade. Ma può succedere che il nodo sia vivo e sia HAProxy a essere morto: in quel caso il VIP resterebbe su un nodo che non bilancia più nulla. Lo script chk_haproxy controlla che il processo esista; se non c'è, applica weight -20 alla priorità. Il MASTER scende da 110 a 90, sotto il BACKUP a 100, e il VIP migra. Il failover segue la salute del servizio, non solo quella della macchina.
Testare il failover
Una configurazione di HA non verificata non è alta affidabilità: è una speranza ben documentata. Il test va fatto, e va fatto vedere.
Da un terzo host, tieni una richiesta in loop sul VIP:
while true; do curl -so /dev/null -w "%{http_code} %{time_total}s\n" \
https://192.0.2.10/health; sleep 1; done
Poi, sul nodo MASTER, simula i due scenari:
- HAProxy muore:
systemctl stop haproxy. Lo scriptchk_haproxyfallisce, la priorità scende, il VIP passa al nodo B. Sul loop di curl vedrai una manciata di richieste perse, poi la ripresa. - Il nodo cade: stacca la rete del nodo A, o spegnilo. Il BACKUP smette di ricevere gli annunci VRRP e si promuove.
Controlla dove sta il VIP con ip addr show eth0: l'indirizzo 192.0.2.10 deve comparire sul nodo attivo e sparire dall'altro. Quando il nodo A torna su, con priorità più alta si riprende il VIP (comportamento preemptive): valuta se è ciò che vuoi o se preferisci nopreempt per evitare un secondo spostamento.
I limiti da conoscere
Questa architettura risolve l'alta affidabilità del livello di bilanciamento, ed è solida. Ma due punti vanno tenuti a mente.
Il primo: HAProxy e Keepalived non rendono affidabile ciò che sta dietro. Se i tuoi backend condividono un solo database, quel database resta il vero punto di guasto unico: l'alta affidabilità del dato è un problema a parte, che ho trattato per i database nell'articolo su MySQL senza downtime.
Il secondo: lo stato. Il round robin presuppone backend senza stato locale. Se l'applicazione tiene le sessioni in memoria sul singolo server, un failover le perde. La soluzione corretta non è la session persistence sul bilanciatore, ma spostare lo stato fuori dai backend, su uno store condiviso.
Chiuso questo, il risultato è concreto: un servizio web che sopravvive alla perdita di un intero nodo di bilanciamento con qualche secondo di disservizio, non con un'interruzione. E un failover che hai visto funzionare con i tuoi occhi, non che speri funzioni.
Altri insights
Hardening di pfSense: la configurazione che metto in produzione
Una guida operativa al firewall perimetrale per una PMI: segmentazione, regole, accesso amministrativo blindato, IDS/IPS e filtraggio GeoIP. Configurazioni reali, non teoria.
LeggiAutomatizzare alerting e remediation con i workflow
Una pipeline pratica che trasforma un alert grezzo in una notifica utile e, dove ha senso, in una correzione automatica. Architettura e limiti.
LeggiNIS2 oltre il firewall: la checklist di adeguamento per una PMI
La direttiva NIS2, recepita in Italia con il D.Lgs. 138/2024, chiede misure tecniche e organizzative, governance e notifica degli incidenti. Una guida operativa per leggere obblighi, tempi ACN e checklist.
Leggi