Skip to content

Instantly share code, notes, and snippets.

@carlosroman
Last active March 20, 2023 16:40
Show Gist options
  • Save carlosroman/f772154f26f8f553da49a08ea8e394b6 to your computer and use it in GitHub Desktop.
Save carlosroman/f772154f26f8f553da49a08ea8e394b6 to your computer and use it in GitHub Desktop.
Working HA Proxy config example with a fallback backend

Simple HA proxy with fallback backend

To run:

docker compose up # or docker-compose up if not using the docker plugin

In another terminal the run the following:

curl -v -d '{"key1":"value1", "key2":"value2"}' -H "Content-Type: application/json" -X POST  localhost:4080/test

You will then see in that the container called main-backend-1 handles the request, something like:

ha-proxy-failover-main-backend-1    | 172.27.0.4 - - [20/Mar/2023:15:11:23 +0000] "POST /test HTTP/1.1" 200 0 "-" "curl/7.81.0" "-"

To simulate the main backend going down just run:

docker compose stop main-backend

Then the next time you make a curl request it will block and might also timeout. Eventually HA proxy (after about 5 seconds or so) will register the main backend as down and route all requests to the backup backend. In the logs you will then see the request being handled by ``. You might need to make the curl request again.

ha-proxy-failover-main-backend-1 exited with code 0
ha-proxy-failover-proxy-1           | [WARNING]  (7) : Server bk_main/s1 is DOWN, reason: Layer4 timeout, check duration: 2001ms. 0 active and 0 backup servers left. 1 sessions active, 0 requeued, 0 remaining in queue.
ha-proxy-failover-proxy-1           | [ALERT]    (7) : backend 'bk_main' has no server available!
ha-proxy-failover-backup-backend-1  | 172.27.0.4 - - [20/Mar/2023:15:17:42 +0000] "POST /test HTTP/1.1" 200 0 "-" "curl/7.81.0" "-"

The HA config can be improved to not use a network check and instead an actual health check. So it could look like something like:

backend bk_main
    mode http
    option httpchk
    http-check send meth GET  uri /health
    http-request set-header X-MY-HEADER "some_value/bk_main"
    server s1 main-backend:80 check
---
version: "3.9"
services:
proxy:
image: haproxy:2.6
ports:
# curl -v -d '{"key1":"value1", "key2":"value2"}' -H "Content-Type: application/json" -X POST localhost:4080/test
- "4080:80"
volumes:
- type: bind
source: failover_ha.cfg
target: /usr/local/etc/haproxy/haproxy.cfg
main-backend:
image: nginx:stable
ports:
# curl -v -d '{"key1":"value1", "key2":"value2"}' -H "Content-Type: application/json" -X POST localhost:4081/test
- "4081:80"
volumes:
- type: bind
source: nginx_always_200.conf
target: /etc/nginx/conf.d/default.conf
read_only: true
backup-backend:
image: nginx:stable
ports:
# curl -v -d '{"key1":"value1", "key2":"value2"}' -H "Content-Type: application/json" -X POST localhost:4082/test
- "4082:80"
volumes:
- type: bind
source: nginx_always_200.conf
target: /etc/nginx/conf.d/default.conf
read_only: true
# Basic configuration
global
log 127.0.0.1 local0
maxconn 4096
stats socket /tmp/haproxy
# Some sane defaults
defaults
mode http
log global
option dontlognull
retries 3
timeout client 5s
timeout server 5s
timeout connect 5s
# This declares a view into HAProxy statistics, on port 3833
# You do not need credentials to view this page and you can
# turn it off once you are done with setup.
listen stats
bind *:3833
mode http
stats enable
stats uri /
# This section is to reload DNS Records
# Replace <DNS_SERVER_IP> and <DNS_SECONDARY_SERVER_IP> with your DNS Server IP addresses.
# For HAProxy 1.8 and newer
resolvers my-dns
nameserver dns1 1.1.1.1:53
nameserver dns2 8.8.8.8:53
resolve_retries 3
timeout resolve 2s
timeout retry 1s
accepted_payload_size 8192
hold valid 10s
hold obsolete 60s
# This the entrypoint
frontend http-in
bind *:80
# detect capacity issues in production farm
acl MAIN_not_enough_capacity nbsrv(bk_main) le 0
# failover traffic to backup farm
use_backend bk_main_backup if MAIN_not_enough_capacity
default_backend bk_main
# This is the primary backend
backend bk_main
mode http
http-request set-header X-MY-HEADER "some_value/bk_main"
server s1 main-backend:80 check
backend bk_main_backup
mode http
option httpchk
# Run a HTTP health check on the backend
http-check send meth GET uri /health
# Expect a status of 200
http-check expect status 200
http-request set-header X-MY-HEADER "some_value/bk_main_backup"
# Run the check every 10 seconds
server s1 backup-backend:80 check inter 10s
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
return 200;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment