Forum Discussion
Use iRules to query number of active connections against a node
I am currently trying to automate a lot of the "out of the box" behaviour available on the BIG-IP using iRules which is, to say the least, quite a task. The reason for doing this is that we have an environment using DNS hostnames instead of IP addresses and because of that, we cannot configure nodes as pool members since this hard codes the node IP address as the pool member. I know there are other options like using iCall and GTM, but there's a whole lot of history and I'm trying to make the background short.
In a nutshell, I am trying to program the Least Connections (Member) load balancing algorithm using iRules, and resolving each hostname to an IP address as part of the HTTP_REQUEST event. Not pretty, I know.
My question is simple, but I'm not sure if the answer will be. I need a way to code the least connections algorithm. In order for that to work, I need to programatically query the number of active connections (for a virtual server and specific port...not including connections made from other virtual servers or other ports) against specific nodes.
I know this can be done using the TM shell by looking at the connection table, but I need it to be wrapped up in code that can be put inside an iRule.
Is there any way at all to do this using iRules?
Not sure what you're looking for here.
- The client connects to the virtual server
- Instead of a pool you have a group of host names you use
- For each request the client makes you want to choose the hostname with the least connections, resolve it again, and send the request to the resolved.
Is this correct? If it is you're looking at additional latency for every query and I believe overhead in terms of new tcp connections for every request (unless you're using NAT and can re-establish only the server side connection). But I guess you're aware of that already? :)
/Patrik
- Kevin_StewartEmployee
If I may add, it doesn't sound like you need to worry about load balancing algorithms, although this can be done with the LB::mode command. If you're doing a DNS resolution on each HTTP request, then the returned value is presumably going to be a single IP address. To Patrik's point though, this can be expensive. It might make more sense to manage a local table entry and cache a response for at least as long as the TTL in the response. If the table entry exists, use it, otherwise query and insert the value into the table for later use.
I suppose it's possible, but do the returned IP addresses change wildly? If not, it may also make sense to just automate the update of the pool members using a perpetual script, and subsequently monitor these members in case an IP goes away between script calls.
- Tony_Jarvis_132Altostratus
Thanks for the replies, both very helpful!
I am aware of the overhead incurred with DNS lookups, but at least the RESOLV::lookup command caches queries. Unfortunately it is a requirement given to us and we have to play ball (it's a very customised environment that necessitates this flexibility as the servers can be passed around between locations using VMotion etc and the IP addresses can change).
Very interested in the possibility of using a perpetual script to update the pool members...how might this be done?
I don't think I can use the LB::mode option as that only applies to pools with pool members. With this setup, I cannot add pool members in, because by doing this it will save the IP addresses of those members and it will not allow the DNS lookups to be acted upon. My solution is currently doing DNS lookups via iRules and sending the requests to the approporiate node programatically with no pool members defined.
Kevin, just one final note - the resolution for each hostname will be a single IP address, but we are load balancing across multiple hostnames. So basically we have a simple setup of two hostnames, each of these need to be resolved to their own IP addresses, and it's the load balancing across each of these resolved IP addresses that I want to match up with a least connections type of algorithm. Hope that makes sense.
- Kevin_StewartEmployee
The idea of a perpetual script is to, on some regular and frequent basis, query for the DNS records of a given site, and then update a pool. That pool would have a regular load balancing algorithm applied, and a reasonable monitor to make sure requests don't fail somewhere in between the asynchronous DNS queries. It's not as real-time as using RESOLV::lookup, but it's a lot less expensive.
Have you considered using iControl to change the pool members? If you have any control over the "floating" members you could possibly write a script which was triggered when the member moves changing it's member IP as well.
/Patrik
- Kevin_StewartEmployee
Okay, so give this a shot:
Shell script:
!/bin/bash user-defined: dns_server dns_server="10.80.0.200" user-defined: host to resolve host="tester.mydomain.com" user-defined: host port host_port="80" user-defined: pool to update pool="tester-pool" lookup=($(dig @$dns_server $host +short)) pre-define host_list host_list="" for x in ${lookup[@]} do host_list="$host_list $x:$host_port" done if [ "$host_list" != "" ] then tmsh modify ltm pool $pool members replace-all-with { $host_list } fi
Create a cli script to point to the shell script:
> tmsh create sys icall script update-pool create script update-pool { app-service none definition { set update [catch {exec /config/dev/archive/update-pool.sh}] } description none events none } ** modify the above to point to your shell script
Create a periodic iCall:
create sys icall handler periodic update-pool script update-pool status active interval 300
This will create a periodic (I know I said "perpetual" but I meant periodic) script to completely update the given pool with the returned DNS values.
- Tony_Jarvis_132Altostratus
Appreciate all the help thus far, but just curious...I've searched around and honestly can't find an answer to the original question:
Is there any way to use an iRule to query how many active connections are currently on a node using the node IP and destination port as the query value (I mean, if the same node is also listening on other ports I don't want those connections to count).
Any way to do this using iRules?
- nitassEmployee
Is there any way to use an iRule to query how many active connections are currently on a node using the node IP and destination port as the query value (I mean, if the same node is also listening on other ports I don't want those connections to count).
i understand irule sits in data plane but stats you are looking for is in control/management plane. i do not think there is straight way to get that stats in irule. of course, there is a tricky way such as icall, external script, etc.
- Kevin_StewartEmployee
A few additional things to consider:
-
A "node" is simply an IP address, while a (pool) "member" is defined by an IP and port/service. If you wanted to know the number of connections to a node on a given port, then you'd be specifying a pool member.
-
There is no functionality, currently, within iRules to see the number of connections to a given node or member, so any solution would likely require diving into the management plane from the iRule.
-
There are a number of ways to do the above, from iStats, to some method of updating a session table entry. In any case, you would need some asynchronous management plane process to update that data, which means it would never be "real time", and probably not so effective given that you're looking for a number of active, transient TCP connections.
-
While this is certainly possible, I would never recommend it. Reaching into the management plane from an iRule for a piece of information, randomly and seldomly may be okay, but doing so in every HTTP request would probably decimate the memory usage of the management plane.
-
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