Forum Discussion

Gregory_Gerard_'s avatar
Gregory_Gerard_
Icon for Nimbostratus rankNimbostratus
Jun 18, 2005

How do I detect if a pool is down in an iRule?

Use Case:

 

pool is down

 

 

Current behavior:

 

I have an http profile setup that sends back an impersonal redirect to the client.

 

 

Desired behavior:

 

I'd like to have the URI passed to the host that got the redirection.

 

 

Why?

 

I have an SSL VS https://blah.example.com

 

 

An iRule looks at the first portion of the URI and decides which pool to send to in a big switch statement:

 

 

iRule fragment:

 

elseif {[HTTP::uri] starts_with "/customer1" } {

 

pool pool-customer1

 

}

 

 

https://blah.example.com/customer1/rest/of/uri?and=stuff

 

 

gets routed to a different pool than

 

 

https://blah.example.com/customer2/rest/of/uri?and=stuff

 

 

If the pool is down, I'd like to be able to redirect to a system down page and send the original URI so I can log it in our application and periodically retry their original request with a JavaScript timer.

 

 

Right now, the redirect is fixed because the profile is shared amongst all customers. Must I create a profile per customer to get this behavior or can I gauge the health of a pool and do a better redirect myself?

8 Replies

  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    The way to do this is to write a handler for the LB_FAILED event.

    You can then query the pool and take action according to which pool was selected.

    Eg:

     
     when LB_FAILED { 
        switch [LB::server pool] { 
           pool-customer1 { HTTP::redirect http:://foo/customer1 } 
           pool-customer2 { HTTP::redirect http:://bar/notavail } 
           default { HTTP::redirect http:://sitedown/ } 
        } 
     } 
     

    You can also use "HTTP::respond" instead of "HTTP::redirect" and then you can completely customize the response.

  • I am trying the follwowing rule

    rule sorry_test {
       when LB_FAILED {
           log local0.err "ERR: Load Balancing failed for [virtual name]  Pool: [LB::server]  Client: [IP::remote_addr] 
           HTTP::redirect "http://sorry.domain.com/sorry.html"
       }
    }

    Now when I make a request to the virtual immediately after shutting down the webserver I get an empty reply from the server and I get the following entry in /var/log/ltm:

    Mar  5 16:47:02 tmm tmm[1028]: Rule sorry_test : ERR: Load Balancing failed for testvip  Pool: test_pool  Client: 10.1.1.1 
    Mar  5 16:47:02 tmm tmm[1028]: 011f0007:3: http_process_state_header_xfer - Invalid action EV_SINK_HEADER during ST_HTTP_XFER_HEADERS

    So it appears to have triggered the LB_FAILED event but the HTTP:redirect did not get executed.

    Then a few seconds later when the monitor marks the pool member down, I get the correct redirect the response to my HTTP request and I get the following in /var/log/ltm

    
    Mar  5 16:47:03 testbip mcpd[1119]: 01070638:3: Pool member 10.2.2.2:80 monitor status down.
    Mar  5 16:47:04 tmm tmm[1028]: Rule sorry_test : ERR: Load Balancing failed for testvip  Pool: test_pool  Client: 10.1.1.1
    Mar  5 16:47:04 tmm tmm[1028]: 011f0007:3: http_process_state_header_xfer - Invalid action EV_SINK_HEADER during ST_HTTP_XFER_HEADERS

    In this case, the LB_FAILED event was triggered and the HTTP::redirect was executed.

    So my questions are:

    1. Why does the HTTP::redirect not get executed in the first instance?

    2. What does the EV_SINK_HEADER error message mean?

    -Al

    • Walter_Kacynski's avatar
      Walter_Kacynski
      Icon for Cirrostratus rankCirrostratus
      I think you want to use LB::down and then perform the redirect. I haven't tested this.
  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    Not that you don't have valid questions, because they're good ones, but wouldn't it be easier to just check to see if the pool is down prior to sending the request to it? If all you're looking to do is redirect when no members in the pool are available, something like this would work:

    
    when HTTP_REQUEST {
      if { [active_members your_pool] < 1 } {
        HTTP::redirect "http://somedomain.com/somepage.html"
      } else {
        pool your_pool
      }
    }

    I know it doesn't answer your questions (which I'd love to do, when I get a minute to look into them), but I would think it would give you the desired behavior, no?

    Colin
  • Thanks for the suggestion.

    Actually I do have that in my production iRule. I just was looking for a way to handle the period where a server crashes or is otherwise unresponsive between the time a request is dispatched to it and before the health check marks a server as down.

    There are still other active pool members in this scenario so if it would be possible to have the request redirected to another server, that would be even better. I already tried something like..

    
    when HTTP_REQUEST {
       set request [HTTP::request]
    }
    when LB_FAILED {
       HTTP::retry $request
    }

    But I haven't gotten it to work yet.

    -Al

  • Have you looked at inspecting the return response from the server?

     

     

    Something as follows may help out:

     

     

    
    when HTTP_RESPONSE {
    if { [HTTP::status] ends_with "404" } {
       LB::reselect pool  
    }

     

     

    Course you could also setup a datagroup with the HTTP codes that you want to base your reselect decision on, what I mean is, anything other than 200 or a select few, you could also do something similar to:

     

     

    
    when HTTP_RESPONSE {
       if { [HTTP::status] > "300" } {
          LB::reselect pool  
    }

     

     

    I haven't tested any of this stuff, but with a little trial and error I don't see why it wouldn't work. Best of all you are inspecting the response code from the server and not relying on the interval ECV to mark the node unavailable if it fails (which you should still do, but this comes into place in between those health checks and wait times before the LB marks the node down).

     

     

    Let me know how it goes.

     

     

    -wn

     

     

     

    }

     

  • This issue is you want to determine if the server is down before the LTM does, that is a bit tricky. I'm wondering if you combined the LB failed logic with the pool reselect, instead of redirect, I think the redirect has to be executed based on a positive return value for whatever condition you are checking for, then again they both might and we'll be back in square one.

     

  • Also kind of wondering if those errors you mentioned before are related to the fact that the HTTP profile inspects the HTTP packet header information, since there isn't one it flips out. Not sure if that makes sense or not.