15

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?

  • Is your server running in HTTP mode or TCP mode? – austinian Jul 15 '15 at 16:46
  • 1
    @austinian; Likely http mode seeing as how he's talking about balancing and persistance based on cookies (TCP mode doesn't offer such features). – GregL Jul 15 '15 at 16:54
  • @Christophe, have you actually tried the configuration described in your 'haproxy behaviour' section, because it should work. – GregL Jul 15 '15 at 16:54
  • @GregL, right, that's what I'm thinking too. If he's using HTTP mode and just sets the server to maintenance mode, then it'll stop accepting new sessions but keep the valid sessions alive until they expire. You can still have cookies, etc. in TCP mode, but then it won't mean anything to HAProxy. – austinian Jul 15 '15 at 17:03
  • @Christophe, are you trying to use "a more clever way" to make your maintenance time shorter, or just looking for a way to have sessions end gracefully while you wait to do maintenance? – austinian Jul 15 '15 at 17:07
6

Put the server in drain mode using the web management interface. That provides the exact functionality you're looking for.

| improve this answer | |
  • 3
    If you set it to Maint, it's going to stop sending any traffic to it, as outlined here. Rather, he'd want to put it in to Drain mode, and use a stick-table with expiration to provide persistance. – GregL Jul 16 '15 at 14:39
  • @GregL, oops, fixing now – austinian Jul 16 '15 at 14:43
  • Thanks for your answer, austinian and @GredL. I'll try that. The hard part will be with the stick-table, I think. I'll have to find a way to store every client with the cookie set to the drain mode server in this stick-table. – Christophe Drevet-Droguet Jul 17 '15 at 7:55
  • Well, it seems that the drain mode is sufficient in my case, the sessions that already have the cookie set still uses the drained server, and new sessions are directed to other servers. – Christophe Drevet-Droguet Jul 17 '15 at 9:22
  • 1
    How do you change modes in the web interface? It looks to be just informational. – kagronick Jun 18 '18 at 17:08
13

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 :)

| improve this answer | |
1

Other ways

synchronize session files between servers (needs a way to synchronize files between several servers, or a common single mountpoint)

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 :)

| improve this answer | |
  • While it would be a better way, it needs code changes, I think. So I'll use austinian, and GregL, answer for our current applications that don't sync sessions. – Christophe Drevet-Droguet Jul 17 '15 at 7:39
  • If your code does not set a custom session handler, then you don't need to change any code for PHP to use memcache for sessions. It's all configured in php.ini, not in code. – Cha0s Jul 17 '15 at 9:54
  • OK, Cha0s, I'll look at that. – Christophe Drevet-Droguet Jul 17 '15 at 11:45
1

For the future reader that wants to drain a backend from a HAProxy container...

docker exec $(docker ps | grep haproxy | awk '{print $1}') bash -c 'echo "set server backend_name/svc_name state drain" | nc -U /haproxy.sock'

Note:
The /haproxy.sock path is the one you have set in the haproxy.cfg file [eg stats socket /haproxy.sock mode 660 level admin]

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.