Forum Discussion
URi based redirection only if pool members are available.
Hello everyone. I am a newbie to iRules thus I apologize for any dumb questions in advance for foreseeable future. I have this iRule which does simple redirection based on URI:
when HTTP_REQUEST {
if { [HTTP::host] equals "example.com" and ( [HTTP::uri] equals "/" or [HTTP::uri] equals "/example-client" or [HTTP::uri] equals "/example-client//" ) } {
HTTP::redirect "https://example.com/example-client/login"
}
This works fine as it should. However, developers now want to integrated a failover scenario where if two out of three server in the pool are not available, all requests will be forwarded to a third pool member which will only display simple error page. To solve this, I turned to priority groups. I put two 'production servers' in one PG and the error server to another PG. However, then I was informed that the 'error_page_server' cannot be modified to answer a request with any URI in it. How's that possible I do not know. Therefore, I would like to come up with modification to above iRule in following fashion: If productino servers are down, then strip any URI from incoming request before forwarding to 'error_page_request'. Otherwise, perform URI manipulation as usual.
So far, I found out that LB::status will be used. However, I cannot work out how to introduce that condition in the iRule.
I will be gratefull for any suggestions. Thank you very much. Best regards, JH.
12 Replies
Hi!
If I understood your scenario correctly, you can use active_members for this. Try this one (not checked for syntax):
when HTTP_REQUEST { if { [active_members http_pool] >= 2 } { if { [HTTP::host] equals "example.com" and ( [HTTP::uri] equals "/" or [HTTP::uri] equals "/example-client" or [HTTP::uri] equals "/example-client//" ) } { HTTP::redirect "https://example.com/example-client/login" } } else { HTTP::uri "/errorpage" pool your_error_pool } }/Patrik
- Jakub_Hornik_16
Nimbostratus
Hi Patrik! Thank you very much for your help. It's a kick in right direction. At least now I know how to start tackling this problem. However, from what I understood of your reply, it seems that I would need to introduce another pool. Which is, of course, an option, however I would like to stick with one pool solution. Current setup is as follows:
pool www.example.com - member1:8083priority group 5 - member1:8003priority group 10 - member2:8003priority group 10
The production servers are those with PRG 10. The error page server is the one with PG 5 and different port. And using this setup I would like to achieve what I described in the first post. Thank you. Take care. Best regards, JH.
- Jakub_Hornik_16
Nimbostratus
Supplemental: Priority group activation condition is se to 'Less than 1 Available member(s)'.
Hi!
Sorry mate, I understood it as you had another pool for the error pages.
If you have the same pool I'd disable the priority group activation and use an iRule like this one instead (omit the pool command if the default pool is the one you intend to use):
when HTTP_REQUEST { if { [active_members http_pool] >= 2 } { if { [HTTP::host] equals "example.com" and ( [HTTP::uri] equals "/" or [HTTP::uri] equals "/example-client" or [HTTP::uri] equals "/example-client//" ) } { HTTP::redirect "https://example.com/example-client/login" } } else { HTTP::uri "/errorpage" } }Does that make sense?
/Patrik
- Jakub_Hornik_16
Nimbostratus
Hi Patrik! It does make sense, however this '{ [active_members http_pool] >= 2 }' combined with removal of priority group would results into the scenario where all three members of the pool getting requests (based on load-balancing method), would it not? If yes, then I am afraid it is an undesirable result.
Because member1 on port 8083 must NOT receive ANY traffic until member1:8003 and member2:8003 are down. That is why I resorted to priority groups.
Thank you. Best regards, JH.
So you have 3 members:
member1:8083 - Error page member1:8003 - Normal page member2:8003 - Normal page
Then you should be able to keep your priority group activation, or try the node command?
when HTTP_REQUEST { if { [active_members http_pool] >= 2 } { if { [HTTP::host] equals "example.com" and ( [HTTP::uri] equals "/" or [HTTP::uri] equals "/example-client" or [HTTP::uri] equals "/example-client//" ) } { HTTP::redirect "https://example.com/example-client/login" } } else { HTTP::uri "/errorpage" node member1 8083 } }Please note that this would require you to remove member1:8083 from the pool and disabling priority activation.
/Patrik
- Jakub_Hornik_16
Nimbostratus
Hi Patrik! Thank you very much again. It seems that the node command is my last resort.
Just to clarify: if I keep the priority group and use '{ [active_members http_pool] >= 2 }', will the priority group still be in effect? I am just asking because so far I gained an impression that when iRule will be combing through the pool using this '{ [active_members http_pool] >= 2 }' it will disregard the priority group settings and will take the state of whole pool into account rather than state of twoo pool members in higher PG. Thank you. Best regards, JH.
Hi
Yeah, you're right. If you don't want to use the node command and want to keep the priority groups you'd be better off checking the individual members. Try this:
when HTTP_REQUEST { if { [LB::status pool http_pool member 10.0.0.1 8003] eq "up" or [LB::status pool http_pool member 10.0.0.2 8003] eq "up" } { if { [HTTP::host] equals "example.com" and ( [HTTP::uri] equals "/" or [HTTP::uri] equals "/example-client" or [HTTP::uri] equals "/example-client//" ) } { HTTP::redirect "https://example.com/example-client/login" } } else { HTTP::uri "/errorpage" } }/Patrik
- Jakub_Hornik_16
Nimbostratus
Hi Patrik!
Thank you very much again, your last post is exactly what I had in mind in the first place. Just two last questions:
If I want to remove the URI completely, would this be enough?
} else { HTTP::uri "/" }
Also, if I want to log output of this iRule, I would add this log local0. My question is, will this log locally into /var/log/ltm only or is it possible for me to redirect the log output somewhere else? Thank you. Best regards, JH.
Hi!
My pleasure. :)
Yes, HTTP::uri "/" would suffice.
log local0. "Test" would log Test to the ltm log, just like you said.
To log to another file you'd have to fiddle with the syslog-ng config or, which is my favorite, use HSL (you need a syslog server for this):
https://devcentral.f5.com/wiki/irules.HSL.ashx
Here's an old post about configuring custom log files:
/Patrik
- Jakub_Hornik_16
Nimbostratus
Hi Patrik!
Thank you very much for knowledge you shared. I applaud to your skills, sir. You have saved me a lot of headscratching. That remote logging sounds nice too, will have to investigate that also. Enjoy your weekend and have a nice rest of the day. Best regards, JH.
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com