You would want to use a local variable ($failure) not a global variable ($::failure) as a global variable would get updated across all TCP connections. Also, you would need to initialise the variable in all paths through the iRule or check to see if it's set before trying to use it. You can check to see if a variable is defined using [info exists var_name]. Keep in mind that LB_SELECTED will occur before HTTP_RESPONSE on the first request on a new TCP connection.
Even after fixing those issues, your current iRule wouldn't do much to fix the current request that received a 503 as you're not forcing a retry of the request from HTTP_RESPONSE.
With that said, what are you actually trying to accomplish? Are you concerned that the application will return a 503 and more requests will be sent to it before the monitor marks it down? Do you want to mark the pool member down if a 503 is seen in the response? Do you want to have the current request reload balanced to a new pool member if a 503 is seen in the response? Is the application stateful with the sessions only existing on one server?
If you mark the server down after a single 503, and your application is stateful with the sessions existing only on that server, the client could be reload balanced, but they'd have to re-establish their application session on the new server.
If you do want to retry the request after a 503 response, you could use HTTP::retry (
Click here) in HTTP_RESPONSE. LB::reselect isn't available in HTTP_RESPONSE--just LB_FAILED and LB_SELECTED. And an HTTP 50x response (or any acceptance of the TCP connection) will not trigger LB_FAILED. The downside to HTTP::retry is that you need to save the request headers (and data) for every request in order to retry the request.
Aaron