The issue
I'm using haproxy to load balance web servers. I use session persistence with additional cookies as some applications use session files and these are not synchronized between servers.
I want to disable a server for maintenance, but without breaking sessions. So I would like to allow existing clients to continue their application session, but not accept new clients.
haproxy behavior
- I set a server to "going to maintenance"
- if a client has the cookie set, use the server even if marked as "going into maintenance"
- if a new client (without cookie) come, it is directed to another server
- after all clients end their application sessions, no more client would have the cookie set to this particular server, and I'd be good to shut it down without user disruption.
Do you think this is achievable with some haproxy configuration? Or is there a clever way to do it?
Other ways
Non exhaustive list of other ways to achieve this need:
- synchronize session files between servers (needs a way to synchronize files between several servers, or a common single mountpoint)
- use database to store session information (needs to change application behavior)
More details
I use this kind of configuration:
frontend https-in
bind xxx.xxx.xxx.xxx:443 ssl crt /etc/haproxy/ssl/_default.pem crt /etc/haproxy/ssl
reqadd X-Forwarded-Proto:\ https
acl APP1 hdr(host) -i APP1.atac.local
use_backend APP1 if APP1
default_backend _default
backend APP1
redirect scheme https if !{ ssl_fc }
mode http
balance roundrobin
cookie HAPROXY_SESSION insert indirect
option httpchk HEAD /haproxy_test_page.php HTTP/1.0\nUser-Agent:\ HAProxy
server SRV1 SRV1_IP:PORT cookie SRV1 check
server SRV2 SRV2_IP:PORT cookie SRV2 check
If I just disable SRV1 (with haproxy cli command), I think all application sessions opened on SRV1 will break after the end of the current HTTP "session". Is that right?
If you use socat for communicate with your haproxy configurations, you can put a server in drain state of following way:
echo "set server backend/serv state drain" | sudo socat stdio /etc/haproxy/haproxysock
More commands here! For install socat in Ubuntu go to this answer
I test that with haproxy 1.6.3 version :)
Put the server in drain mode using the web management interface. That provides the exact functionality you're looking for.
For details on the web management interface - https://github.com/Aidaho12/haproxy-wi
For the future reader that wants to drain a backend from a HAProxy container...
Note:
The
/haproxy.sock
path is the one you have set in thehaproxy.cfg
file [egstats socket /haproxy.sock mode 660 level admin
]If your backend servers use PHP for the application(s) you can use Memcache to sync the sessions between them.
Also Couchbase-Server can do memcache replication out of the box.
Of course it's kind of overkill to use couchbase-server just for sessions replication :)