Deploy HAProxy Load Balancer for Service Exposure
| Module | NODE |
|---|---|
| Docs | https://pigsty.io/docs/node/haproxy |
| Related Roles | node, pgsql |
The haproxy role deploys HAProxy for load balancing and service exposure:
- Install HAProxy package
- Create configuration directory
- Render default and service configs
- Configure SELinux policies (if applicable)
- Launch HAProxy service
- Support config reload without restart
HAProxy is used by PostgreSQL clusters for connection pooling and load balancing across replicas.
| Playbook | Description |
|---|---|
node.yml |
Node provisioning (includes HAProxy) |
roles/haproxy/
├── defaults/
│ └── main.yml # Default variables
├── files/
│ └── haproxy.svc # Systemd service file
├── meta/
│ └── main.yml # Role dependencies
├── tasks/
│ └── main.yml # Main task list
└── templates/
├── haproxy.cfg.j2 # Default HAProxy config
└── service.j2 # Service definition template
haproxy (full role)
│
├── haproxy_install # Install HAProxy
│
├── haproxy_config # Configure HAProxy
│ └── haproxy_firewall # SELinux configuration
│
├── haproxy_launch # Start HAProxy service
│
└── haproxy_reload # Reload configuration
| Variable | Default | Description |
|---|---|---|
haproxy_enabled |
true |
Enable HAProxy on this node |
haproxy_clean |
false |
Wipe existing config on deploy |
haproxy_reload |
true |
Reload after config changes |
| Variable | Default | Description |
|---|---|---|
haproxy_auth_enabled |
true |
Enable admin authentication |
haproxy_admin_username |
admin |
Admin page username |
haproxy_admin_password |
pigsty |
Admin page password |
haproxy_exporter_port |
9101 |
Admin/metrics port |
⚠️ Security Warning: The default passwordpigstyis publicly known. Changehaproxy_admin_passwordin production environments!
| Variable | Default | Description |
|---|---|---|
haproxy_client_timeout |
24h |
Client connection timeout |
haproxy_server_timeout |
24h |
Server connection timeout |
| Variable | Default | Description |
|---|---|---|
haproxy_services |
[] |
List of services to expose |
/etc/haproxy/
├── haproxy.cfg # Global defaults
├── pg-test-primary.cfg # Service: port 5433
├── pg-test-replica.cfg # Service: port 5434
├── pg-test-default.cfg # Service: port 5435
├── pg-test-offline.cfg # Service: port 5436
└── ...
Define custom HAProxy services:
haproxy_services:
# PostgreSQL read-only replicas
- name: pg-test-ro
port: 5440
ip: "*"
protocol: tcp
balance: leastconn
maxconn: 20000
default: 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'
options:
- option httpchk
- option http-keep-alive
- http-check send meth OPTIONS uri /read-only
- http-check expect status 200
servers:
- { name: pg-test-1, ip: 10.10.10.11, port: 5432, options: 'check port 8008', backup: true }
- { name: pg-test-2, ip: 10.10.10.12, port: 5432, options: 'check port 8008' }
- { name: pg-test-3, ip: 10.10.10.13, port: 5432, options: 'check port 8008' }
# Redis cluster
- name: redis-test
port: 5441
servers:
- { name: redis-test-1-6379, ip: 10.10.10.11, port: 6379, options: check }
- { name: redis-test-1-6380, ip: 10.10.10.11, port: 6380, options: check }| Parameter | Required | Default | Description |
|---|---|---|---|
name |
Yes | - | Unique service name |
port |
Yes | - | Listen port |
ip |
No | * |
Listen address |
protocol |
No | tcp |
Protocol (tcp/http) |
balance |
No | roundrobin |
Load balance algorithm |
maxconn |
No | 10000 |
Max frontend connections |
options |
No | [] |
Additional HAProxy options |
servers |
Yes | - | Backend server list |
| Algorithm | Description |
|---|---|
roundrobin |
Round-robin selection (default, good for homogeneous servers) |
leastconn |
Prefer server with fewest connections (good for OLTP) |
source |
Hash client IP for session affinity |
first |
Use first available server (for active-standby) |
For PostgreSQL clusters, HAProxy uses HTTP health checks against Patroni REST API:
options:
- option httpchk
- option http-keep-alive
- http-check send meth OPTIONS uri /read-only # or /primary, /replica, /health
- http-check expect status 200
servers:
- { name: pg-test-1, ip: 10.10.10.11, port: 5432, options: 'check port 8008' }Patroni Health Check Endpoints (port 8008):
| Endpoint | Returns 200 When | Use Case |
|---|---|---|
/primary |
Instance is primary | Read-write service |
/replica |
Instance is replica | Read-only service |
/read-only |
Instance accepts read queries (any role) | Read-only + backup |
/health |
Instance is healthy (any role) | General health |
Update services without restarting:
./node.yml -t haproxy_config,haproxy_reload
bin/pgsql-svc <cls>This validates config before reload and only applies changes if valid.
On RHEL/Rocky systems with SELinux enabled, the role automatically:
- Sets
haproxy_connect_anyboolean to allow HAProxy to connect to any port - Installs a custom SELinux policy module (
haproxy_proc) to allow HAProxy to read/procfilesystem for health monitoring
This is handled silently - if SELinux tools are not available, these steps are skipped.
This role supports RHEL/Rocky 8-10, Ubuntu 22-24, and Debian 12-13.
The systemd service file is installed to {{ systemd_dir }}/haproxy.service,
where systemd_dir is determined by the node_id role based on OS detection.
node: Node provisioningpgsql: PostgreSQL cluster- HAProxy Guide: Configuration documentation