56

I have a web sever that connects to an internal database through a VPN. There are 2 IPs (primary and secondary) to the database from the web server. How can I setup my /etc/hosts file so that if the primary IP is not available then the secondary IP will be used?

Would this work for my hosts file?

141.131.286.1   abc.efg.datastore.com   #primary

141.131.286.237 abc.efg.datastore.com   #secondary
dmourati
  • 26,498
Mike T
  • 673
  • 1
  • 5
  • 6

9 Answers9

41

The hosts file does not provide such mechanism. If you list two IPs for the same name, only the first one will be used. So, there is no such thing as primary and secondary IPs.

Also, the hosts file does not handle URLs. It just handles names like the ones provided in the question. A URL contains complete path and protocol such as http://host/path/to/resource.

fengqi
  • 103
Khaled
  • 37,789
21

You can't provide resilience or round robin load balancing via the /etc/hosts file - it is not designed for that purpose.

Instead, your options are ... (in no particular order)

  1. Configure your network properly, so that routes change when a link is dropped
  2. Use DNS round-robin load balancing (not A Good Idea TM) using a managed service (eg. loaddns.com or dnsmadeeasy.com etc.)
  3. Use a local L3 load balancer for the outbound traffic (HAProxy?) with the back-ends defined as necessary
  4. Build the resilience into your web application itself
Ben Lessani
  • 5,374
5

/etc/hosts doesn't support round robin but you can write a simple bash script to sed replace an entry tagged with a #RoundRobin comment (or any other tag you wish to use, just reflect it in the grep line in the script).

#!/bin/bash
fqdnips=( $(nslookup sub.domain.com|grep Address:|awk -F\  '{ print $2 }'|grep -v '#') )

new=`printf "${fqdnips[@]}"`
old=`grep "#RoundRobin" /etc/hosts|awk -F\  '{ print $1 }'`
sed -i "s/$old/$new/g" /etc/hosts

The above script grabs the output of nslookup for sub.domain.com and stores it in an array. It then prints the top most value to $new and grabs the existing value for tag #RoundRobin assigned in /etc/hosts ... lastly, it performs a sed replace

/etc/hosts file entry would look like this

127.0.0.1        localhost
::1              localhost
11.12.13.14      sub.domain.com      #RoundRobin

Lastly, place this script in the root's crontab to run every hour or so and you'll now have an /etc/host round-robin.

This is particularly useful if you have a coded page that is pulling some data from an API and the DNS lookup for the API server is causing a lot of hang time in the page's script execution... resulting in high cpu consumption for what would otherwise appear to be a simple page. To avoid the costly DNS lookup (particularly if your site is doing hundreds of them per minute do to heavy traffic), you should use /etc/hosts to resolve the FQDN of the remote API server. This will dramatically reduce the CPU usage for pulling the API data and generating the page.

Satalink
  • 188
3

Note that at least on macOS, in contradiction to what the other answers say, the system resolver will return all entries associated with a host name in /etc/hosts instead of stopping at the first.

zneak
  • 328
  • 2
  • 14
3

Easy to setup, please follow the instruction:

  1. install dnsmasq
  2. edit /etc/resolv.conf and set "nameserver 127.0.0.1" as a first DNS
  3. add normal DNS as alternative (google one for example) "nameserver 8.8.8.8" as a second line
  4. make sure two required records are in your /etc/hosts file
  5. now check with a command host abc.efg.datastore.com

    that should respond two records with RR-DNS so if one node from the list is down - your application will be connected to another one
1

I got to this page because I have laptops that are sometimes connected with wifi and sometimes connected with Ethernet. I also run dnsmasq on my network with each entry in that server's /etc/hosts file. If I want to rsync or ssh to one of my laptops with the hostname and its current interface connection is the second entry for that host in the dnsmasq-read hosts file, then the host is seen as "unreachable" because the IP address assigned to that host is for the interface that host is not using at that time. @Satalink's answer gave me an idea for a script that solves my issue. I put it on github - here is the raw file.

It:

  1. runs in cron every 15 minutes
  2. iterates through specified host names and their multiple ip options to determine the first of the list that is pingable
  3. updates the /etc/hosts files with the new pingable address
  4. does not change the IP if neither are pingable
  5. restarts dnsmasq
0

Yes multiple IPs in /etc/hosts works. Example, and test;

> echo "192.168.0.141 test
192.168.0.142 test
192.168.0.143 test" >> /etc/hosts

> dig test +short 192.168.0.141 192.168.0.142 192.168.0.143

This sort of thing will only work with services that are restful or have session sharing like http, smtp, pop, etc.

0

Easy way to make this happen would be to just use a public DNS service, like AWS Route53. You can enter multiple IP addresses per A record with priority

abc.efg.datastore.com

10 141.131.286.1  
20 141.131.286.237 

As long as no certificates are involved this is working and afaik not even against any norms or best practices.

NSLookup or other domain queries will return both addresses. Your app needs to be able to handle this. And yes, the domain needs to be a publicly registered one, not just a local hostname.

bortran
  • 109
-3

Yes, it would work.

However, the search mechanism simply goes does the list until it finds a match.

So while the answer to the question as written is YES, it is going to be a challenge. But nothing insurmountable.

Try this: Each of those IP addresses really do need to have differing names.

SDsolar
  • 155