Zero‑Downtime HAProxy Load Balancing: Full 4‑Layer & 7‑Layer Deployment Guide
This guide walks through installing HAProxy, configuring both layer‑4 TCP and layer‑7 HTTP/HTTPS load balancing with health checks, session persistence, advanced algorithms, high‑availability via Keepalived, monitoring with HAProxy stats and Prometheus, performance tuning, security hardening, and step‑by‑step rollback procedures for zero‑downtime deployments.
Applicable Scenarios & Prerequisites
Applicable Services : Web cluster entry, micro‑service gateway, MySQL/Redis read load balancing, SSL termination proxy.
Prerequisites :
HAProxy ≥ 2.0 (recommended 2.4+ with HTTP/2 and dynamic backend updates)
OS: RHEL 7/8, Ubuntu 18.04/20.04/22.04
Network: at least 2 NICs (recommended front‑end/back‑end separation) or single NIC with multiple IPs
Root or sudo privileges, ability to bind ports 80/443
Backend services: at least 2 healthy instances
Environment & Version Matrix
Component Version Requirement OS Support Key Features
---------- ------------------- --------------------------- ------------------------------------------
HAProxy 2.0+ (recommended 2.4‑2.8) RHEL 7/8, Ubuntu 18.04/20.04/22.04 HTTP/2, dynamic backend, Runtime API
OpenSSL 1.1.1+ (TLS 1.3) Same as above ALPN, SNI, OCSP Stapling
Keepalived 2.0+ Same as above VIP drift (high‑availability)
System 2C/4G/20G (minimum) - Handles 10,000 concurrent connectionsQuick Checklist
Install HAProxy and verify version
Configure layer‑4 TCP load balancing (MySQL/Redis)
Configure layer‑7 HTTP/HTTPS load balancing (Web services)
Configure backend health checks (TCP/HTTP/SSL)
Configure load‑balancing algorithms (round‑robin, least‑conn, consistent hash)
Configure session persistence (Cookie/Source IP)
Configure SSL/TLS termination and SNI
Enable stats page and monitoring
Test failover and service drain
Configure high‑availability with Keepalived VIP
Implementation Steps
Step 1: Install HAProxy and Verify Version
RHEL/CentOS :
# RHEL 8
sudo dnf install -y haproxy
# RHEL 7 (EPEL required)
sudo yum install -y epel-release
sudo yum install -y haproxyUbuntu/Debian :
sudo apt update
sudo apt install -y haproxyInstall latest version from official PPA (optional):
# Ubuntu
sudo add-apt-repository ppa:vbernat/haproxy-2.8 -y
sudo apt update
sudo apt install -y haproxy=2.8.*
# Or compile from source
wget https://www.haproxy.org/download/2.8/src/haproxy-2.8.3.tar.gz
tar xzf haproxy-2.8.3.tar.gz
cd haproxy-2.8.3
make TARGET=linux-glibc USE_OPENSSL=1 USE_PCRE=1 USE_SYSTEMD=1
sudo make installVerify installation:
haproxy -v
# Expected output: HAProxy version 2.8.3 2023/11/23
haproxy -vv | grep -E "OpenSSL|PCRE|epoll"
# Expected output shows OpenSSL 1.1.1, PCRE2, epoll supportStep 2: Configure Layer‑4 TCP Load Balancing (MySQL Read)
Create /etc/haproxy/haproxy.cfg with the following snippet (only the relevant part shown):
global
log /dev/log local0 info
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 40000
nbthread 4
cpu-map auto:1/1-4 0-3
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
tune.ssl.default-dh-param 2048
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 5s
timeout client 50s
timeout server 50s
timeout check 5s
retries 3
maxconn 30000
# ---------- MySQL Read Load Balancing (layer‑4 TCP) ----------
listen mysql-read
bind 0.0.0.0:3307
mode tcp
balance leastconn
option tcp-check
tcp-check connect port 3306
tcp-check send-binary 0a
tcp-check expect binary 0a
server mysql-slave-01 10.0.1.101:3306 check inter 3s rise 2 fall 3 maxconn 1000
server mysql-slave-02 10.0.1.102:3306 check inter 3s rise 2 fall 3 maxconn 1000
server mysql-slave-03 10.0.1.103:3306 check inter 3s rise 2 fall 3 maxconn 1000 backup
# ---------- Redis Load Balancing (layer‑4 TCP) ----------
listen redis-cluster
bind 0.0.0.0:6380
mode tcp
balance roundrobin
option tcp-check
tcp-check send PING
tcp-check expect string +PONG
server redis-01 10.0.1.201:6379 check inter 2s rise 2 fall 3
server redis-02 10.0.1.202:6379 check inter 2s rise 2 fall 3
server redis-03 10.0.1.203:6379 check inter 2s rise 2 fall 3Key parameter explanations: balance leastconn: selects backend with fewest active connections (ideal for long‑lived MySQL connections) check inter 3s: health check interval rise 2 fall 3: 2 consecutive successes mark UP, 3 failures mark DOWN maxconn 1000: per‑backend connection limit backup: standby server used only when all primary backends are down
Validate configuration syntax:
haproxy -c -f /etc/haproxy/haproxy.cfg
# Expected output: Configuration file is validStart HAProxy:
systemctl enable haproxy
systemctl start haproxy
systemctl status haproxyStep 3: Configure Layer‑7 HTTP/HTTPS Load Balancing (Web Services)
Append the following sections to /etc/haproxy/haproxy.cfg:
# ---------- HTTP Frontend (layer‑7) ----------
frontend http-in
bind *:80
mode http
option httplog
option forwardfor
option http-server-close
acl is_api hdr(host) -i api.example.com
acl is_web hdr(host) -i www.example.com
acl is_admin hdr(host) -i admin.example.com
acl is_static path_beg /static /images /css /js
use_backend api-backend if is_api
use_backend web-backend if is_web
use_backend admin-backend if is_admin
use_backend static-backend if is_static
default_backend web-backend
# redirect http to https (optional)
# redirect scheme https code 301 if !{ ssl_fc }
# ---------- HTTPS Frontend (SSL termination) ----------
frontend https-in
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem alpn h2,http/1.1
mode http
option httplog
option forwardfor
http-request set-header X-Forwarded-Proto https
http-request set-header X-Forwarded-Port 443
use_backend api-backend if is_api
default_backend web-backend
# ---------- Web Backend (round‑robin + Cookie persistence) ----------
backend web-backend
mode http
balance roundrobin
cookie SERVERID insert indirect nocache httponly secure
option httpchk GET /health
http-check expect status 200
server web-01 10.0.2.11:8080 check cookie web01 maxconn 500
server web-02 10.0.2.12:8080 check cookie web02 maxconn 500
server web-03 10.0.2.13:8080 check cookie web03 maxconn 500
# ---------- API Backend (leastconn + Source IP stickiness) ----------
backend api-backend
mode http
balance leastconn
stick-table type ip size 100k expire 30m
stick on src
option httpchk POST /api/health
http-check expect status 200
server api-01 10.0.2.21:8080 check maxconn 1000
server api-02 10.0.2.22:8080 check maxconn 1000
server api-03 10.0.2.23:8080 check maxconn 1000
# ---------- Static Backend (URI hash / consistent hash) ----------
backend static-backend
mode http
balance uri
hash-type consistent
option httpchk HEAD /favicon.ico
http-check expect status 200
server static-01 10.0.2.31:8080 check
server static-02 10.0.2.32:8080 check
# ---------- Admin Backend (single point with backup) ----------
backend admin-backend
mode http
balance roundrobin
option httpchk GET /admin/health
http-check expect status 200
server admin-01 10.0.2.41:8080 check
server admin-02 10.0.2.42:8080 check backupKey parameter explanations: option forwardfor: adds X‑Forwarded‑For header with client IP cookie SERVERID insert: inserts a cookie for session persistence stick-table … stick on src: source‑IP stickiness for API backend balance uri + hash-type consistent: consistent hashing for static assets (improves cache hit rate) alpn h2,http/1.1: enables HTTP/2 negotiation on HTTPS frontend
Step 4: Advanced Health Checks
# HTTP health check with custom headers
backend advanced-health-check
mode http
balance roundrobin
option httpchk GET /health HTTP/1.1
Host:\ health.example.com
User-Agent:\ HAProxy-Health-Check
http-check expect status 200
http-check expect string "healthy"
server app-01 10.0.3.11:8080 check port 8080 inter 5s rise 2 fall 3
server app-02 10.0.3.12:8080 check port 8080 inter 5s rise 2 fall 3
# SSL health check (TLS handshake)
backend ssl-backend
mode tcp
balance roundrobin
option ssl-hello-chk
server secure-01 10.0.3.21:443 check check-ssl verify none
server secure-02 10.0.3.22:443 check check-ssl verify noneStep 5: Load‑Balancing Algorithm Comparison
Algorithm Configuration Suitable Scenarios Pros / Cons
---------- ------------- ----------------- ----------
roundrobin balance roundrobin General web services Simple, even distribution, ignores load
leastconn balance leastconn Long‑lived connections (DB, WS) Adapts to load, extra CPU overhead
source balance source Stateless services needing stickiness Fixed client‑to‑backend mapping, may imbalance
uri balance uri CDN / cache‑heavy static content Improves cache hit, uneven URL distribution
consistent balance uri + hash-type consistent Dynamic scaling environments Minimal remapping when backends change
leasttime resp balance leasttime response (HAProxy 2.4+) Heterogeneous backend performance Picks fastest backend, adds monitoring costStep 6: Session Persistence Options
# Cookie insertion (recommended)
backend cookie-persistence
mode http
balance roundrobin
cookie SERVERID insert indirect nocache httponly secure
server web-01 10.0.5.11:8080 check cookie srv01
server web-02 10.0.5.12:8080 check cookie srv02
# Source IP stickiness (simple, NAT‑sensitive)
backend source-ip-persistence
mode http
balance roundrobin
stick-table type ip size 100k expire 30m
stick on src
server web-01 10.0.5.11:8080 check
server web-02 10.0.5.12:8080 check
# URL‑parameter stickiness (API token scenario)
backend url-param-persistence
mode http
balance roundrobin
stick-table type string len 32 size 100k expire 1h
stick on url_param(session_id)
server api-01 10.0.5.21:8080 check
server api-02 10.0.5.22:8080 checkStep 7: Statistics Page & Monitoring
listen stats
bind *:8404
mode http
stats enable
stats uri /haproxy-stats
stats refresh 30s
stats realm "HAProxy Statistics"
stats auth admin:StrongPassword123
stats admin if TRUEAccess via http://<em>haproxy‑ip</em>:8404/haproxy-stats (basic auth required).
Runtime API examples (using socat):
echo "show servers state" | socat stdio /run/haproxy/admin.sock
echo "set server web-backend/web-01 state maint" | socat stdio /run/haproxy/admin.sockPrometheus exporter setup (haproxy_exporter):
wget https://github.com/prometheus/haproxy_exporter/releases/download/v0.15.0/haproxy_exporter-0.15.0.linux-amd64.tar.gz
tar xzf haproxy_exporter-0.15.0.linux-amd64.tar.gz
sudo cp haproxy_exporter-0.15.0.linux-amd64/haproxy_exporter /usr/local/bin/
# systemd service (simplified)
[Unit]
Description=HAProxy Exporter
After=network.target
[Service]
Type=simple
User=haproxy
ExecStart=/usr/local/bin/haproxy_exporter --haproxy.scrape-uri="unix:/run/haproxy/admin.sock"
Restart=on-failure
[Install]
WantedBy=multi-user.targetStep 8: Failover & Service Drain Testing
# Simulate backend failure
ssh web-01 "systemctl stop nginx"
# Or block traffic
ssh web-01 "iptables -A INPUT -p tcp --dport 8080 -j DROP"
# Observe HAProxy logs
journalctl -u haproxy -f | grep web-01
# Expected log: Server web-backend/web-01 is DOWN, reason: Layer4 connection problem
# Graceful drain
echo "set server web-backend/web-01 state drain" | socat stdio /run/haproxy/admin.sock
# Wait for connections to finish, then maintenance
echo "set server web-backend/web-01 state maint" | socat stdio /run/haproxy/admin.sockStep 9: High‑Availability with Keepalived VIP
Install Keepalived on both nodes:
# RHEL/CentOS
sudo yum install -y keepalived
# Ubuntu/Debian
sudo apt install -y keepalivedMaster /etc/keepalived/keepalived.conf (simplified):
global_defs {
router_id HAProxy-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 100
advert_int 1
authentication {
auth_type PASS
auth_pass SecurePassword123
}
virtual_ipaddress {
10.0.0.100/24
}
track_script { chk_haproxy }
notify_master "/usr/local/bin/haproxy_master.sh"
}Backup node uses the same file with state BACKUP and lower priority (e.g., 90).
Start Keepalived on both nodes and verify VIP migration.
systemctl enable keepalived
systemctl start keepalived
ip addr show eth0 | grep 10.0.0.100Monitoring & Alerting
Key HAProxy metrics (via HAProxy stats socket or Prometheus): haproxy_backend_up == 0 – backend down alert haproxy_backend_response_time_average_seconds > 1 – high latency
5xx error rate:
rate(haproxy_backend_http_responses_total{code="5xx"}[5m]) / rate(haproxy_backend_http_responses_total[5m]) > 0.05Queue depth:
haproxy_backend_current_queue > 10Performance & Capacity
Benchmark expectations on a 2 CPU / 4 GB server:
Layer‑4 TCP: 50 k QPS, < 5 ms P99 latency, 40 % CPU
Layer‑7 HTTP: 30 k QPS, < 10 ms P99 latency, 60 % CPU
Layer‑7 HTTPS: 15 k QPS, < 20 ms P99 latency, 80 % CPU
Performance tuning parameters (add to global):
maxconn 100000
nbthread 8
tune.bufsize 32768
tune.maxrewrite 8192
tune.ssl.cachesize 100000Security & Compliance
SSL/TLS hardening (global section):
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
# OCSP stapling
tune.ssl.ocsp-update.mode onDDoS protection (rate limiting):
frontend http-in
stick-table type ip size 1m expire 30s store conn_rate(10s)
tcp-request connection track-sc0 src
tcp-request connection reject if { sc_conn_rate(0) gt 100 }
http-request track-sc1 src
http-request deny if { sc_http_req_rate(1) gt 200 }Detailed logging (syslog integration):
global
log /dev/log local0 info
log /dev/log local1 notice
frontend https-in
option httplog
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"Troubleshooting Quick Reference
Symptom
Diagnostic Command
Possible Cause
Quick Fix
Permanent Fix
Backend marked DOWN
echo "show stat" | socat stdio /run/haproxy/admin.sock
Health check failure
Check backend service/network
Adjust health‑check parameters
503 Service Unavailable
journalctl -u haproxy -f
All backends down
Restore at least one backend
Add more backends or configure backup
SSL handshake failure
openssl s_client -connect localhost:443
Expired or mis‑configured certificate
Update certificate
Automate cert renewal monitoring
Connection timeout
echo "show info" | socat stdio /run/haproxy/admin.sock
Slow backend or maxconn reached
Increase timeout / maxconn
Scale backend resources
VIP unreachable
ip addr | grep VIP
Keepalived not running or VRRP blocked
Restart Keepalived
Check firewall / VRRP configuration
Session persistence broken
curl -v … (inspect Cookie)
Cookie not set or overwritten
Verify backend config
Debug application side
Change & Rollback Playbook
Backup current config: cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.backup Validate new config: haproxy -c -f /etc/haproxy/haproxy.cfg.new Hot reload: systemctl reload haproxy Monitor for 5 minutes:
watch -n 1 'echo "show stat" | socat stdio /run/haproxy/admin.sock | grep DOWN'If critical alerts (all backends down, 5xx > 10 %, client failures > 5 %) occur, rollback:
cp /etc/haproxy/haproxy.cfg.backup /etc/haproxy/haproxy.cfg
systemctl reload haproxyBest Practices
Health checks must target real service endpoints (e.g., /health) rather than static files.
Deploy at least two HAProxy nodes with Keepalived VIP to avoid single‑point failure.
Prefer cookie‑based session persistence over source‑IP stickiness.
Set conservative timeout values greater than the slowest backend response.
Enable detailed HTTP logging ( option httplog) for troubleshooting.
Limit per‑backend connections ( maxconn) to ~80 % of backend capacity.
Automate SSL certificate renewal (e.g., Let’s Encrypt + certbot).
Monitor backend response latency (P95/P99) and alert on thresholds.
Periodically test failover by manually draining backends.
Version‑control HAProxy configuration (Git) and enforce PR review.
Appendix: Production Configuration Template
global
log /dev/log local0 info
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
maxconn 50000
nbthread 4
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5s
timeout client 50s
timeout server 50s
retries 3
maxconn 40000
frontend http-in
bind *:80
redirect scheme https code 301
frontend https-in
bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
option forwardfor
http-request set-header X-Forwarded-Proto https
use_backend web-backend
backend web-backend
balance roundrobin
cookie SERVERID insert indirect nocache httponly secure
option httpchk GET /health
http-check expect status 200
server web-01 10.0.1.11:8080 check cookie web01
server web-02 10.0.1.12:8080 check cookie web02
listen stats
bind *:8404
mode http
stats enable
stats uri /
stats refresh 30s
stats auth admin:passwordTested on RHEL 8.8 / Ubuntu 22.04 with HAProxy 2.8.3 (2025‑10‑31). Configuration is reviewed quarterly; SSL certificates are checked monthly.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
