Operations 36 min read

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.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Zero‑Downtime HAProxy Load Balancing: Full 4‑Layer & 7‑Layer Deployment Guide

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 connections

Quick 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 haproxy

Ubuntu/Debian :

sudo apt update
sudo apt install -y haproxy

Install 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 install

Verify 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 support

Step 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 3

Key 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 valid

Start HAProxy:

systemctl enable haproxy
systemctl start haproxy
systemctl status haproxy

Step 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 backup

Key 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 none

Step 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 cost

Step 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 check

Step 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 TRUE

Access 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.sock

Prometheus 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.target

Step 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.sock

Step 9: High‑Availability with Keepalived VIP

Install Keepalived on both nodes:

# RHEL/CentOS
sudo yum install -y keepalived
# Ubuntu/Debian
sudo apt install -y keepalived

Master /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.100

Monitoring & 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.05

Queue depth:

haproxy_backend_current_queue > 10

Performance & 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 100000

Security & 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 on

DDoS 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 haproxy

Best 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:password

Tested on RHEL 8.8 / Ubuntu 22.04 with HAProxy 2.8.3 (2025‑10‑31). Configuration is reviewed quarterly; SSL certificates are checked monthly.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

high availabilityOpsZero DowntimeHAProxy
MaGe Linux Operations
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.