F5 is upgrading its customer support chat feature on My.F5.com. Chat support will be unavailable from 6am-10am PST on 1/20/26. Refer to K000159584 for details.

Forum Discussion

avinashc's avatar
avinashc
Icon for Nimbostratus rankNimbostratus
Feb 24, 2025

F5 irule for multi-pool base on http_response

I have an iRule that distributes traffic between two different pools based on weights defined in data groups. If the application in one pool is down, it receives a 503 response, allowing the traffic to be forwarded to the other pool. This functionality is working as expected. However, when this situation occurs, the browser briefly displays a "page can't be reached" error before retrying and successfully loading the page. I want the iRule to attempt both pools before displaying an error to the user.

 

 

when CLIENT_ACCEPTED {
    # Initialize variables
    set ab_class "/imc/Shared/vs_lb_svc_kube_system_f5_nginx_deployment_dg"
    set ab_rule [class match -value "/" equals $ab_class]
    set retries 0
    set request_headers ""
    set pool_list [list]
    set active_pool ""

    # Populate the pool list and determine the active pool
    if {$ab_rule != ""} then {
        set service_rules [split $ab_rule ";"]
        foreach service_rule $service_rules {
            set fields [split $service_rule ","]
            set pool_name [lindex $fields 0]
            lappend pool_list $pool_name
            if { [active_members $pool_name] >= 1 } {
                set active_pool $pool_name
            }
        }
    }

    # Select the initial pool based on weights
    if {$ab_rule != ""} then {
        set weight_selection [expr {rand()}]
        foreach service_rule $service_rules {
            set fields [split $service_rule ","]
            set pool_name [lindex $fields 0]
            set weight [expr {double([lindex $fields 1])}]
            if {$weight_selection <= $weight} then {
                # Check if active pool members are available
                if { [active_members $pool_name] >= 1 } {
                    pool $pool_name
                    return
                } else {
                    # Select other pool with active members
                    if {$active_pool != ""} then {
                        pool $active_pool
                        return
                    }
                }
            }
        }
    }

    # If no active pool members are found, return a 503 (Service Unavailable)
    if {$active_pool == ""} then {
        TCP::respond 503
        return
    }
}

when HTTP_REQUEST {
    # Save the request headers if it is a GET request and not a retried request
    if { [HTTP::method] eq "GET" && $retries == 0 } {
        set request_headers [HTTP::request]
        log local0. "Saving HTTP request headers: $request_headers"
    }
}

when HTTP_RESPONSE {
    # Check if we got a 503 response
    if { [HTTP::status] == 503 } {
        # Log the 503 response for debugging purposes
        log local0. "Received 503 response, retrying request with next pool"

        # Increment the retry counter
        incr retries

        # Get the current pool
        set current_pool [LB::server pool]

        # Find the next pool in the list
        set next_pool ""
        foreach pool $pool_list {
            if { $pool == $current_pool } {
                continue
            }
            if { [active_members $pool] >= 1 } {
                set next_pool $pool
                break
            }
        }

        # If a next pool is found, retry the request with the next pool
        if { $next_pool != "" } {
            log local0. "Retrying with next pool: $next_pool"
            pool $next_pool
            HTTP::retry $request_headers
        } else {
            log local0. "No next pool found, responding with 503"
            TCP::respond 503
        }
    }
}

1 Reply