Using F5 DNS in the Public Cloud

F5 load-balancers do a lot of things very well, but they’re not good at lying. When you want your F5 DNS to give out IPs that aren’t the ones it’s getting from the LTMs, a bit of persuasion is required…

When you set up an F5 in Azure or AWS, your device only knows about private IPs. Your virtual servers will have IPs like 10.something or 192.168.0.something, probably. And if you’re only talking to other services in your own private virtual network, that’s fine. But you probably want your services to be available to the public Internet. (Especially if you’re using a pricey F5 instead of your cloud provider’s built-in load balancing offering, there’s probably a reason.)

Your F5 DNS will talk to your LTM using iQuery, and DNS will respond with the IP of your virtual server. Which unfortunately is going to be one of those private IPs, which isn’t very useful. The rest of the world can’t (hopefully) talk to your private network.

There are (at least) two ways to work around this.

The one suggested by F5 support to me involves using a feature called “Address Translation”. Makes sense, we’re trying to work with cloud NAT, so a somethingAT seems fitting. There’s a KB article and everything. Essentially, you tell F5 DNS to replace certain IPs with other IPs.

But then there’s another KB article that underplays the down-side of this approach. If you start defining manual address translations, you risk breaking auto-discovery. So all your new LTM objects may not show up in your DNS until you manually re-create them.

We settled on what we believe is a simpler, easier-to-maintain approach. We have to remember to make one additional change when deploying new virtual servers in Azure that need public IPs, but that beats having to make changes for every new VS, period.

We created a DNS iRule that just looks for responses using our private IPs, and rewrites them, thus:

when LB_SELECTED {
  if {[IP::addr [LB::server addr] equals 192.168.0.8]} { host "52.1.2.32" }
  if {[IP::addr [LB::server addr] equals 192.168.0.9]} { host "13.78.1.1" }
  if {[IP::addr [LB::server addr] equals 192.168.0.10]} { host "13.78.3.4" }
}

We applied that DNS iRule to the wide-IPs that have pool members in Azure.

A more elegant approach would probably involve an iRule data group, but so far it doesn’t look like data groups are supported in DNS iRules. (I don’t know why not, they work fine in LTM iRules, but…)

This certainly isn’t overly elegant or fancy, and there may well be edge cases where it doesn’t work. (The first one that comes to mind is if you’re returning more than one record in a query, this will override that.) But for our simple case, it’s cleaner and more maintainable than fiddling around with F5’s own translation features.

Using F5 DNS in the Public Cloud