Hi,
I’m trying to setup HAProxy on Docker Swarm (the container is haproxytech/haproxy-debian:2.4 ) and the deploy mode is global (3 replicas, as I have 3 workers) with the network mode as host, so I am avoiding the docker load balancer and I’m sure which instance of the HAProxy container is forwarding the http traffic.
Behind the HAProxy there is a replicated service which requires the session persistence, so by googling up I came to the conclusion that the approach I should use is to have a stick table where I should track the cookie and redirect the connection to the right server.
As HAProxy runs on a container, I created 3 (almost identical) config files, where the only change is the line where the local peer (node#) has its listening IP to 127.0.0.1 instead of the VM IP address.
I’m providing the configuration file here:
global
log fd@2 local2 debug
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
stats socket /var/lib/haproxy/stats expose-fd listeners
master-worker
resolvers docker
nameserver dns1 127.0.0.11:53
resolve_retries 3
timeout resolve 1s
timeout retry 1s
hold other 10s
hold refused 10s
hold nx 10s
hold timeout 10s
hold valid 10s
hold obsolete 10s
defaults
timeout connect 10s
timeout client 30s
timeout server 30s
log global
mode http
option httplog
peers mypeers
peer node1 127.0.0.1:2000
peer node2 <node2 IP>:2000
peer node3 <node3 IP>:2000
frontend fe_web
bind *:80
use_backend stat if { path -i /my-stats }
default_backend configurator
backend configurator
balance roundrobin
option persist
option redispatch
server-template configurator- 6 <service name>:443 check resolvers docker init-addr libc,none
cookie SERVERID insert indirect nocache maxidle 30m maxlife 8h
stick-table type string len 32 size 100k expire 1h peers mypeers srvkey addr
stick store-response res.cook(PHPSESSID)
stick on req.cook(PHPSESSID)
tcp-request content track-sc0 req.cook(PHPSESSID)
http-request track-sc0 src
backend stat
stats enable
stats uri /my-stats
stats refresh 15s
stats show-legends
stats show-node
The service is run with the endpoint_mode: dnsrr option, so HAProxy can get all instances, like described in the guide for swarm load balancing . The first issue is that docker gives a list of IP in a random order, so the stick-table over the 3 nodes is not consistent over the server_id key.
Two possible solutions came to my mind:
- Install HAProxy on the VM and, via systemd, ensure that it gets restarted in case of any issue. The problem with this solution is that the HAProxy instance on each node is not able to resolv the containers name with the Docker DNS server, as the latter is available only inside the docker overlay network. So, I discarded this option as it seemed unfeasable to solve my problem
- Use the srv_key addr option on the stick table. With this solution, the stick-table contains correctly the Cookie as the value for the key, the server_id field and the server_key one:
# table: configurator, type: string, size:102400, used:2
0x556b582e4f20: key=10.2.0.198 use=0 exp=3533310 server_id=0 server_key=-
0x556b582f34f0: key=6qql68sgo3q33k9qfdesud9a7i use=0 exp=3582937 server_id=1 server_key=172.0.10.73:80
The first line shows up when I’m at the login page, and the second one when I’m successfully logged in.
If I use the same HAProxy, there is no problem, but if I change the HAProxy instance (giving the same PHPSESSID on the request to the other HAProxy container), the session persistence is not mantained, as data is routed to the server with id 1 for the second HAProxy instance.
The solution shown is to associate the server name with an IP, but this is not possible with docker swarm, as the IP address is changed once a container is recreated.
i.e. what described here is not doable:
[...]
server lamp1 10.0.0.1:80 check
server lamp2 10.0.0.2:80 check
So, going to the real question: is there a way to tell HAProxy to use what is stored with srvkey addr as the server address where to redirect the traffic?
Thanks in advance