Forum Discussion
Query on GTM irule based on Pool Availability
Hello,
I am very beginner to iRule creation. In GTM I tried to create irule as below. But getting error.
Our intention is we need to reroute the DNS query to different pool based on client IP and pool availability.
Condition:
If the client IP match and the pool is available then need to go normal pool
If the client IP match and the pool is not available then need to go failback pool
Pool EUR_LDS0_ITHUBPR_POOL with TTL 300
pool GLOBAL_LDS0_POOL with TTL 300
pool GLOBAL_FAILBACK_LDS0_POOL with TTL 60
when DNS_REQUEST {
if [{ [IP::addr [IP::client_addr] equals 10.235.24.64/27] and ([active_members EUR_LDS0_ITHUBPR_POOL] > 0) } {
pool EUR_LDS0_ITHUBPR_POOL
} else {
pool GLOBAL_FAILBACK_LDS0_POOL }
}
else {
pool GLOBAL_LDS0_POOL
}
}
Appreciate any help on this.
Data groups are available in BIG-IP DNS systems. Per the support article SanjayP identified, in versions prior to 12.1, you can only configure them using TMSH as a workaround. In v12.1 and later, you can also define them using the Configuration utility at DNS > GSLB > Delivery > iRules > Data Group List.
In the datagroup, you could define the IP network address ranges as the key and the associated pool name to use as the value. For example:
(In case the screen shot is too small...)
(tmos)# list /ltm data-group internal special_pool_ips ltm data-group internal special_pool_ips { records { 10.221.152.0/24 { data AOA_LDS0_WIPRO_POOL } 10.222.152.0/24 { data EUR_LDS0_WIPRO_POOL } 10.223.152.0/24 { data AMS_LDS0_WIPRO_POOL } 10.234.24.64/27 { data AMS_LDS0_ITHUBPR_POOL } 10.235.24.64/27 { data EUR_LDS0_ITHUBPR_POOL } 10.236.24.64/27 { data AOA_LDS0_ITHUBPR_POOL } } type ip }
Then your iRule could be reduced to something like below. I included log commands to write to /var/log/gtm when testing. These should be commented out for production. I checked for a match with the data group first, before checking to see if there are active members. That way you don't have to do two comparisons on every DNS query, only on those from the special client IPs:
when DNS_REQUEST { # set default pool for load balancing pool GLOBAL_LDS0_POOL # if DNS request is from a client # with a special IP address, select # a different load balancing pool but # only if it has an available pool member. # If no available pool members, # use GLOBAL_FAILBACK_LDS0_POOL if { [class match [IP::client_addr] equals special_pool_ips] } { log local2. "Match with special_pool_ips datagroup for [IP::client_addr]" if { [active_members [class lookup [IP::client_addr] special_pool_ips]] > 0 } { log local2. "Pool [class lookup [IP::client_addr] special_pool_ips] has active members" pool [class lookup [IP::client_addr] special_pool_ips] } else { log local2. "Pool [class lookup [IP::client_addr] special_pool_ips] has no active members; using failback pool" pool GLOBAL_FAILBACK_LDS0_POOL } } }
- crodriguezRet. Employee
Data groups are available in BIG-IP DNS systems. Per the support article SanjayP identified, in versions prior to 12.1, you can only configure them using TMSH as a workaround. In v12.1 and later, you can also define them using the Configuration utility at DNS > GSLB > Delivery > iRules > Data Group List.
In the datagroup, you could define the IP network address ranges as the key and the associated pool name to use as the value. For example:
(In case the screen shot is too small...)
(tmos)# list /ltm data-group internal special_pool_ips ltm data-group internal special_pool_ips { records { 10.221.152.0/24 { data AOA_LDS0_WIPRO_POOL } 10.222.152.0/24 { data EUR_LDS0_WIPRO_POOL } 10.223.152.0/24 { data AMS_LDS0_WIPRO_POOL } 10.234.24.64/27 { data AMS_LDS0_ITHUBPR_POOL } 10.235.24.64/27 { data EUR_LDS0_ITHUBPR_POOL } 10.236.24.64/27 { data AOA_LDS0_ITHUBPR_POOL } } type ip }
Then your iRule could be reduced to something like below. I included log commands to write to /var/log/gtm when testing. These should be commented out for production. I checked for a match with the data group first, before checking to see if there are active members. That way you don't have to do two comparisons on every DNS query, only on those from the special client IPs:
when DNS_REQUEST { # set default pool for load balancing pool GLOBAL_LDS0_POOL # if DNS request is from a client # with a special IP address, select # a different load balancing pool but # only if it has an available pool member. # If no available pool members, # use GLOBAL_FAILBACK_LDS0_POOL if { [class match [IP::client_addr] equals special_pool_ips] } { log local2. "Match with special_pool_ips datagroup for [IP::client_addr]" if { [active_members [class lookup [IP::client_addr] special_pool_ips]] > 0 } { log local2. "Pool [class lookup [IP::client_addr] special_pool_ips] has active members" pool [class lookup [IP::client_addr] special_pool_ips] } else { log local2. "Pool [class lookup [IP::client_addr] special_pool_ips] has no active members; using failback pool" pool GLOBAL_FAILBACK_LDS0_POOL } } }
- spalandeNacreous
Nice example and looks better optimized one.
Hello Sanjay,
Thanks for your advice on this.
Regards,
Kannan.
- crodriguezRet. Employee
Can you share the error that you are getting, please? It will help us to pinpoint the trouble.
Hello Crodriguez,
Thanks.. if I modify the irule with two statement then it is accepting..
when DNS_REQUEST {
if {[IP::addr [IP::client_addr] equals 10.235.24.64/27] and ([active_members EUR_LDS0_ITHUBPR_POOL] < 1 ) } {
pool EUR_LDS0_ITHUBPR_POOL
}
elseif { [IP::addr [IP::client_addr] equals 10.235.24.64/27] and ([active_members EUR_LDS0_ITHUBPR_POOL] > 0) } {
pool GLOBAL_FAILBACK_LDS0_POOL
}
else {
pool GLOBAL_LDS0_POOL
}
}
But our intention is, have a simplified one..
Condition:
If the client IP match
if the pool is available then need to go normal pool (EUR_LDS0_ITHUBPR_POOL)
if the pool is not available then need to go failback pool (GLOBAL_FAILBACK_LDS0_POOL)
If the client IP don't match
go to default pool (GLOBAL_LDS0_POOL)
Hello Crodriguez,
Thanks.. if I modify the irule with two statement then it is accepting..
when DNS_REQUEST {
if {[IP::addr [IP::client_addr] equals 10.235.24.64/27] and ([active_members EUR_LDS0_ITHUBPR_POOL] < 1 ) } {
pool EUR_LDS0_ITHUBPR_POOL
}
elseif { [IP::addr [IP::client_addr] equals 10.235.24.64/27] and ([active_members EUR_LDS0_ITHUBPR_POOL] > 0) } {
pool GLOBAL_FAILBACK_LDS0_POOL
}
else {
pool GLOBAL_LDS0_POOL
}
}
But our intention is, have a simplified one..
Condition:
1.If the client IP match
- if the pool is available then need to go normal pool (EUR_LDS0_ITHUBPR_POOL)
- if the pool is not available then need to go failback pool (GLOBAL_FAILBACK_LDS0_POOL)
2. If the client IP don't match
- go to default pool (GLOBAL_LDS0_POOL)
- spalandeNacreous
something like below. modify as needed
when DNS_REQUEST { switch [IP::addr [IP::client_addr] mask 255.255.255.224] { "10.235.24.64" { if {[active_members EUR_LDS0_ITHUBPR_POOL] > 0}{ pool EUR_LDS0_ITHUBPR_POOL } else { pool GLOBAL_FAILBACK_LDS0_POOL } } default { pool GLOBAL_LDS0_POOL } } }
- spalandeNacreous
switch engine in iRule doesn't support for different subnet masks. so iRule needs to be modified. If BIGIP is licensed with only DNS module, iRule data group is not present. Following iRule can be used in that scenerio. on WIP please use default pool as "GLOBAL_LDS0_POOL"
when DNS_REQUEST { if {([IP::addr [IP::client_addr]/27 equals 10.235.24.64] or [IP::addr [IP::client_addr]/24 equals 10.222.152.0]) and ([active_members EUR_LDS0_ITHUBPR_POOL] > 0)}{ pool EUR_LDS0_ITHUBPR_POOL } elseif {([IP::addr [IP::client_addr]/27 equals 10.235.24.64] or [IP::addr [IP::client_addr]/24 equals 10.222.152.0]) and ([active_members EUR_LDS0_ITHUBPR_POOL] == 0)}{ pool GLOBAL_FAILBACK_LDS0_POOL } else { pool GLOBAL_LDS0_POOL } }
If your BIGIP has iRule datagroup available, create datagroup with address for DNS servers and use below iRule
when DNS_REQUEST { if { ([class match [IP::client_addr] equals src-dns_datagroup]) and ([active_members EUR_LDS0_ITHUBPR_POOL] > 0) } { pool EUR_LDS0_ITHUBPR_POOL } elseif { ([class match [IP::client_addr] equals src-dns_datagroup]) and ([active_members EUR_LDS0_ITHUBPR_POOL] == 0) } { pool GLOBAL_FAILBACK_LDS0_POOL } else { pool GLOBAL_LDS0_POOL } }
Let us know how testing goes.
Hello Crodriguez,
Thank you very much for your on this.
I applied the change and waiting for application team's test result.
Regards,
Kannan.
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