Master HAProxy: From Basics to High-Availability L7/L4 Load Balancing
This comprehensive guide explains what HAProxy is, its core functions and key features, then walks through installing, configuring, and running both L7 and L4 load balancers on Linux, adding logging, log rotation, monitoring, and achieving high availability with Keepalived.
What is HAProxy
HAProxy is a free load‑balancing software that runs on most mainstream Linux operating systems, offering both L4 (TCP) and L7 (HTTP) load‑balancing capabilities with a rich feature set.
The community is very active, with rapid releases (the latest stable 1.7.2 was released on 2017‑01‑13) and performance comparable to commercial load balancers, making it the de‑facto choice for many deployments.
Core Functions
Load balancing: L4 and L7 modes, supporting algorithms such as round‑robin, static‑RR, least‑connection, IP‑hash, URI‑hash, HTTP‑header‑hash, etc.
Health checks: TCP and HTTP modes.
Session persistence: Insert, rewrite, or prefix cookies combined with various hash methods.
SSL termination: HAProxy can decrypt HTTPS and forward plain HTTP to back‑ends.
HTTP request rewriting and redirection.
Monitoring and statistics: a web‑based stats page provides health status and traffic data.
Key Features
Performance
Single‑threaded, event‑driven, non‑blocking model processes hundreds of requests within 1 ms, using only a few kilobytes of memory per session.
O(1) event checking, zero‑copy forwarding and other optimizations keep CPU usage low even under moderate load.
Typical CPU usage is about 15 % for HAProxy itself, with the kernel handling the rest.
In 2009 a test showed a single HAProxy process handling over 100 k requests/second and saturating a 10 Gbps link.
Stability
Running HAProxy as a single process, the author claims no crash‑inducing bugs in 13 years; stability largely depends on the underlying Linux kernel (2.6 or 3.x recommended) and sufficient host memory.
Use a Linux 3.x kernel.
Dedicate the host to HAProxy to avoid resource contention.
Provide a standby machine for hardware failures.
Initial sysctl settings (example below) can be used as a starting point.
<code>net.ipv4.tcp_tw_reuse = 1</code>
<code>net.ipv4.ip_local_port_range = 1024 65023</code>
<code>net.ipv4.tcp_max_syn_backlog = 10240</code>
<code>net.ipv4.tcp_max_tw_buckets = 400000</code>
<code>net.ipv4.tcp_max_orphans = 60000</code>
<code>net.ipv4.tcp_synack_retries = 3</code>
<code>net.core.somaxconn = 10000</code>Installation and Running on CentOS 7
Create a dedicated user and group (e.g.,
ha), download, extract, compile, and install HAProxy:
<code>wget http://www.haproxy.org/download/1.7/src/haproxy-1.7.2.tar.gz</code>
<code>tar -xzf haproxy-1.7.2.tar.gz</code>
<code>make PREFIX=/home/ha/haproxy TARGET=linux2628</code>
<code>make install PREFIX=/home/ha/haproxy</code>Set
PREFIXto the installation path and
TARGETaccording to the kernel version (e.g.,
linux2628for Linux 3.10).
Create HAProxy Configuration File
<code>global
daemon
maxconn 256
pidfile /home/ha/haproxy/conf/haproxy.pid
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option httpchk GET /healthCheck.html
frontend http-in
bind *:8080
default_backend servers
backend servers
balance roundrobin
server server1 127.0.0.1:8000 maxconn 32 check
</code>Ensure
ulimit -nis greater than
maxconn*2+18for large connection limits.
Register HAProxy as a System Service
<code>#!/bin/sh
set -e
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/home/ha/haproxy/sbin
PROGDIR=/home/ha/haproxy
PROGNAME=haproxy
DAEMON=$PROGDIR/sbin/$PROGNAME
CONFIG=$PROGDIR/conf/$PROGNAME.cfg
PIDFILE=$PROGDIR/conf/$PROGNAME.pid
DESC="HAProxy daemon"
SCRIPTNAME=/etc/init.d/$PROGNAME
# Gracefully exit if the binary is missing.
[ -x $DAEMON ] || exit 0
start() {
echo "Starting $DESC: $PROGNAME"
$DAEMON -f $CONFIG
}
stop() {
echo "Stopping $DESC: $PROGNAME"
haproxy_pid="$(cat $PIDFILE)"
kill $haproxy_pid
}
restart() {
echo "Restarting $DESC: $PROGNAME"
$DAEMON -f $CONFIG -p $PIDFILE -sf $(cat $PIDFILE)
}
case "$1" in
start) start ;;
stop) stop ;;
restart) restart ;;
*) echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2; exit 1 ;;
esac
exit 0
</code>Running HAProxy
Start, stop, or restart with:
<code>service haproxy start</code>
<code>service haproxy stop</code>
<code>service haproxy restart</code>Logging with rsyslog
Add to
haproxy.cfg:
<code>global
...
log 127.0.0.1 local0 info
log 127.0.0.1 local1 warning
defaults
...
log global
</code>Configure
/etc/rsyslog.d/haproxy.confto write logs to
/var/log/haproxy.log(local0) and
/var/log/haproxy_warn.log(local1), then restart rsyslog and HAProxy.
Log Rotation
<code>/var/log/haproxy.log /var/log/haproxy_warn.log {
daily
rotate 7
create 0644 ha ha
compress
delaycompress
missingok
dateext
sharedscripts
postrotate
/bin/kill -HUP $(/bin/cat /var/run/syslogd.pid 2>/dev/null) >/dev/null 2>&1
endscript
}
</code>Schedule with a daily cron job.
Building an L7 Load Balancer
Architecture (illustrated below):
Deploy six backend Nginx services (three groups: ms1, ms2, def) on two hosts, each serving a simple
demo.htmlpage and a
healthCheck.htmlpage.
HAProxy Configuration for L7
<code>global
daemon
maxconn 30000
user ha
pidfile /home/ha/haproxy/conf/haproxy.pid
log 127.0.0.1 local0 info
log 127.0.0.1 local1 warning
defaults
mode http
log global
option http-keep-alive
option forwardfor
option httplog
timeout connect 5000ms
timeout client 10000ms
timeout server 50000ms
timeout http-request 20000ms
option httpchk GET /healthCheck.html
frontend http-in
bind *:9001
acl url_ms1 path_beg -i /ms1/
acl url_ms2 path_beg -i /ms2/
use_backend ms1 if url_ms1
use_backend ms2 if url_ms2
default_backend default_servers
backend ms1
balance roundrobin
cookie HA_STICKY_ms1 insert indirect nocache
server ms1.srv1 192.168.8.111:8080 cookie ms1.srv1 maxconn 300 check inter 2000ms rise 2 fall 3
server ms1.srv2 192.168.8.112:8080 cookie ms1.srv2 maxconn 300 check
backend ms2
balance roundrobin
cookie HA_STICKY_ms2 insert indirect nocache
server ms2.srv1 192.168.8.111:8081 cookie ms2.srv1 maxconn 300 check
server ms2.srv2 192.168.8.112:8081 cookie ms2.srv2 maxconn 300 check
backend default_servers
balance roundrobin
cookie HA_STICKY_def insert indirect nocache
server def.srv1 192.168.8.111:8082 cookie def.srv1 maxconn 300 check
server def.srv2 192.168.8.112:8082 cookie def.srv2 maxconn 300 check
listen stats
bind *:1080
stats refresh 30s
stats uri /stats
stats realm "HAProxy Stats"
stats auth admin:admin
</code>After starting HAProxy, the stats page (
http://<host>:1080/stats) shows health, connections, session rates, and backend status.
Building an L4 Load Balancer
In L4 mode HAProxy does not parse HTTP, so features like URI‑based routing and cookie persistence are unavailable, but performance is higher for raw TCP services.
<code>global
daemon
maxconn 30000
user ha
pidfile /home/ha/haproxy/conf/haproxy.pid
log 127.0.0.1 local0 info
log 127.0.0.1 local1 warning
defaults
mode tcp
log global
option tcplog
timeout connect 5000ms
timeout client 10000ms
timeout server 10000ms
option httpchk GET /healthCheck.html
frontend http-in
bind *:9002
default_backend default_servers
backend default_servers
balance roundrobin
server def.srv1 192.168.8.111:8082 maxconn 300 check
server def.srv2 192.168.8.112:8082 maxconn 300 check
</code>For source‑IP persistence replace
balance roundrobinwith
balance sourceor use stick‑tables.
Key Configuration Details
Global Section
daemon: run HAProxy in background.
user/
group: drop privileges.
log: send logs to rsyslog.
pidfile: store process ID.
maxconn: maximum concurrent connections.
Frontend Section
acl: define boolean conditions (e.g., URI prefixes).
bind: listen address and port.
default_backend: fallback backend.
use_backend … if: conditional routing.
option forwardfor,
option http‑keep‑alive,
option httplog, etc.
Backend Section
balance: load‑balancing algorithm (roundrobin, source, etc.).
cookie: enable cookie‑based persistence.
server: define each backend server with parameters such as
check,
maxconn,
cookie, etc.
Default Section
Common parameters that apply to all frontends and backends unless overridden.
Listen Section
Combines frontend and backend in a single block for simpler configurations.
High Availability with Keepalived
Deploy Keepalived on two HAProxy hosts to share a virtual IP. The instance with higher weight becomes MASTER; if it fails, the BACKUP takes over.
<code>global_defs {
router_id LVS_DEVEL
}
vrrp_script chk_haproxy {
script "killall -0 haproxy"
interval 2
weight 2
}
vrrp_instance VI_1 {
state MASTER
interface enp0s25
virtual_router_id 51
priority 101
advert_int 1
virtual_ipaddress {
192.168.8.201
}
track_script {
chk_haproxy
}
}
</code>Install Keepalived, register it as a service, and start it on both machines. The virtual IP will move to the backup host automatically when the master HAProxy or Keepalived instance stops, ensuring continuous service.
Efficient Ops
This public account is maintained by Xiaotianguo and friends, regularly publishing widely-read original technical articles. We focus on operations transformation and accompany you throughout your operations career, growing together happily.
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.