Forum Discussion

Neo_Ph's avatar
Neo_Ph
Icon for Altocumulus rankAltocumulus
May 22, 2022

iRule cookie persistence and pool redirect

Hi all, base on the on below setup...

  • When Pool A/NodeA1 goes down, we expect URI /beta/ requests to be sent to Pool B, as nodeA2 can't accept URI /beta/ requests.
  • However, when Pool A/NodeA1 goes down, we see the LTM sending URI /beta/ requests to Pool A/nodeA2.
  • F5 support said cookies have precedence over iRule and the cookie will try to honor it's persistence, hence why traffic is still being sent to Pool A / nodeA2(A1 is down at that point).

Strangely in lab I have a different behavior from the LTM.  Whether it's an new or a subsequent request, the source_addr persistence record will show the connection for 3mins(default timeout value).  During that time pressing F5 and CTRL-F5 will force the client's browser to reinitiate the communication.   When I reinitiate, despite having received a cookie, previously, for Pool A / nodeA1 -- I also get a new cookie for Pool B / node B1 and connect to node B1 successfully.  That behavior is what I'm expecting in production, but that's not the case.

Should I be adding more to the iRule, in order to maninpulate the cookies, or any suggestions of what can be at cause?

SETUP
LTM contains:
- cookie persistence with fallback source_addr
- Pool A with member nodeA1(priority 15 ) & nodeA2(priority 5); with min-active 1
- Pool B with member NodeB1 only


nodeA1 = 10.10.10.1
nodeA2 = 10.10.10.2
nodeB1 = 10.20.20.21

And an iRule that should mainly redirect like this:
if { PoolA/nodeA1 is down + URI equal "/beta/"} {
         then send it to Pool B
          }
else { send it to Pool A }

 

Here is the iRule:

when HTTP_REQUEST {
set sslex 0

if { ([string tolower [HTTP::uri]] starts_with "/beta/") && ([LB::status pool Alpha-Pool member 10.10.10.1 443] eq "down") } {
set sslex 1
set sni_value "betaServer.lab.com"
HTTP::header replace Host "betaServer.lab.com"
set uri [string map -nocase {"/beta /" "/"} [HTTP::uri]]
HTTP::uri $uri
pool Beta-Pool
} else {
set sslex 0
set sni_value "lab.com"
pool Alpha-Pool
} }


when SERVERSSL_CLIENTHELLO_SEND {
# SNI extension record as defined in RFC 3546/3.1
# https://support.f5.com/csp/article/K41600007
if { $sslex > 0 } {
SSL::extensions insert [binary format SSScSa* 0 [expr { [set sni_length [string length $sni_value]] + 5 }] [expr { $sni_length + 3 }] 0 $sni_length $sni_value]
}
}

  • Tests were done in the production LTM instead, by creating a temporary VIP with same pool members.  A few users were able to test via the temporary VIP, and everything was working as expected.  Yet, it wasn't working on the production VIP. 
    I end-up creating a PoolC containing nodeA1 ONLY for /beta/ URI ONLY.  That way /beta/ URI would never reach nodeA2 when nodeA1 is down.   
    If PoolC/nodeA1 is UP, then PoolC will be used. Otherwise, it will hit the 2nd condition, redirecting /beta/ to PoolB.  Problem solved.

  • Hi Neo_Ph, 

    Seen that you get different behaviour in the lab as in live, that's interesting indeed! Have you gone through the virtual server configuration to ensure that they are exactly the same? Especially the profiles? 

    Also, can you check that the iRules in the live and lab systems are attached in the same order? (order very much matters when it comes to attaching iRules under the Resource tab) 

    And are there any other differences either in software or configuration between the live and lab systems? 

    • Neo_Ph's avatar
      Neo_Ph
      Icon for Altocumulus rankAltocumulus

      There are a few differences such as the use of F5-TCP-WAN & F5-TCP-LAN in the lab, instead of just using tcp profile.  There is only 1 iRule. But the major difference would be the lab version at 13.x vs Prod at 15.x.

      I will have to upgrade to version 15.x and redo my tests. And also use the same profiles, just in case it would impact the way cookie persistence is operating; which would surprise me. I'll add an update afterwards.  Thanks AlexBCT

  • Tests were done in the production LTM instead, by creating a temporary VIP with same pool members.  A few users were able to test via the temporary VIP, and everything was working as expected.  Yet, it wasn't working on the production VIP. 
    I end-up creating a PoolC containing nodeA1 ONLY for /beta/ URI ONLY.  That way /beta/ URI would never reach nodeA2 when nodeA1 is down.   
    If PoolC/nodeA1 is UP, then PoolC will be used. Otherwise, it will hit the 2nd condition, redirecting /beta/ to PoolB.  Problem solved.