Tuesday, February 12, 2013

Hostname in Amazon Linux

When you launch an EC2 instance into a VPC it is given a private IP and hostname, but by default, you don't have access to DNS so the hostname can't resolve. Giles Write also sees this problem.

[ec2-user@ip-10-0-0-113 ~]$ hostname
ip-10-0-0-113

[ec2-user@ip-10-0-0-113 ~]$ ping ip-10-0-0-113
ping: unknown host ip-10-0-0-113

[ec2-user@ip-10-0-0-113 ~]$ nslookup ip-10-0-0-113
Server:         10.0.0.2
Address:        10.0.0.2#53
** server can't find ip-10-0-0-113: NXDOMAIN

[ec2-user@ip-10-0-0-113 ~]$ ifconfig
eth0      Link encap:Ethernet  HWaddr 0E:C5:E9:03:E4:51
          inet addr:10.0.0.113  Bcast:10.0.0.255  Mask:255.255.255.0
          ...
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          ...

[ec2-user@ip-10-0-0-113 ~]$ ping 10.0.0.113
PING 10.0.0.113 (10.0.0.113) 56(84) bytes of data.
64 bytes from 10.0.0.113: icmp_seq=1 ttl=64 time=0.049 ms
...

[ec2-user@ip-10-0-0-113 ~]$ cat /etc/hosts
127.0.0.1   localhost localhost.localdomain

[ec2-user@ip-10-0-0-113 ~]$ cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=localhost.localdomain
...

The hostname command will let you set the hostname, but as described on stackoverflow, that only persists until the next reboot.

[ec2-user@ip-10-0-0-113 ~]$ sudo hostname example.com

[ec2-user@ip-10-0-0-113 ~]$ hostname
example.com

[ec2-user@ip-10-0-0-113 ~]$ sudo shutdown -r now

[ec2-user@ip-10-0-0-113 ~]$ hostname
ip-10-0-0-113

The change can persist if you change the HOSTNAME in /etc/sysconfig/network, and contrary to other reports this doesn't cause your IP to change (although that may be the case in non-VPC EC2).

[ec2-user@ip-10-0-0-113 ~]$ sudo vi /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=example.com

[ec2-user@ip-10-0-0-113 ~]$ sudo shutdown -r now

[ec2-user@example ~]$ hostname
example.com

[ec2-user@example ~]$ ifconfig
eth0      Link encap:Ethernet  HWaddr 0E:C5:E9:03:E4:51
          inet addr:10.0.0.113  Bcast:10.0.0.255  Mask:255.255.255.0
          ...

So it appears that these EC2 boxes have a startup script that derives the hostname (and the name that appears in your shell prompt) from the value in /etc/sysconfig/network and when that value is localhost.localdomain it selects an ip- string based on your local IP. There is a good discussion of this on stackoverflow. An important observation is that cloud-init sets the hostname.

This can be a problem for software such as Tomcat because for example InetAddress.getLocalHost() throws java.net.UnknownHostException: ip-10-0-0-113: ip-10-0-0-113: Name or service not known

A solution to this is to enable DNS in your VPC. Amazon docs state that all instances in a VPC receive an unresolvable host name that AWS assigns (for example, ip-10-0-0-202). To use your own DNS servers you must specify DHCP options. The default DHCP options contains a single value domain-name-servers=AmazonProvidedDNS wich indicates an Amazon DNS server made available within your VPC as IPbase+2, i.e. 10.0.0.2. This is used when an internal machine makes an outbound call to a public machine on the web.

There is a good discussion about this on serverfault. It seems you need to run your own internal DNS server. There doesn't seem to be special support for this in Route53 (which is a generic DNS solution).

So it appers your options are to work around software problems like UnknownHostException, or use Route53 to support the unresolvable DNS names or operate your own DNS server in your VPC. To work around the UnknownHostException you can extract an IP given an interface name.

try // list them all
{
    String comma = "";
    String all = "Interfaces: ";
    Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
    while (interfaces.hasMoreElements())
    {
        NetworkInterface iface = interfaces.nextElement();
        if (iface.isLoopback() || !iface.isUp()) { continue; }
        Enumeration<InetAddress> addresses = iface.getInetAddresses();
        while(addresses.hasMoreElements())
        {
            InetAddress addr = addresses.nextElement();
            all += comma + iface.getDisplayName() + " " + addr.getHostAddress();
            comma = ", ";
        }
    }
    logger.debug(all);
}
catch (Exception e) { logger.debug(e); }

Feedback

From Thad at edointeractive.com on April 16, 2014

This is an interesting article; however, I found an interesting fix today. We use VPC with remote DNS. If you set the instance name ec2->Instances to the desired FQDN, it will be pushed down to the VM.

aws
{ "loggedin": false, "owner": false, "avatar": "", "render": "nothing", "trackingID": "UA-36983794-1", "description": "", "page": { "blogIds": [ 401 ] }, "domain": "holtstrom.com", "base": "\/michael", "url": "https:\/\/holtstrom.com\/michael\/", "frameworkFiles": "https:\/\/holtstrom.com\/michael\/_framework\/_files.4\/", "commonFiles": "https:\/\/holtstrom.com\/michael\/_common\/_files.3\/", "mediaFiles": "https:\/\/holtstrom.com\/michael\/media\/_files.3\/", "tmdbUrl": "http:\/\/www.themoviedb.org\/", "tmdbPoster": "http:\/\/image.tmdb.org\/t\/p\/w342" }