Automatically setting hostname of an EC2 instance using Ansible

Automatically setting hostname of an EC2 instance using Ansible

Sometimes there's a need to automatically setup the hostname of an EC2 instance. This post shows how to do it from 'outside' of the instance itself, using Ansible.

Let's assume here that the instance already has a tag Name, that will be used as the hostname and the VPC uses DHCP options that set the correct domain.

The instance must have an IAM Profile that allows for DescribeInstances.

Prerequisites

For the change to work the EC2 instance must have two Python packages installed:

  • boto3
  • botocore

They can be installed using pip.

Workflow

First we have to determine the region the instance is in. The easiest way is to look at the search domains in /etc/resolv.conf. One of them contains the region, for example: ap-southeast-2.compute.internal. Those domains are available in Ansible facts via ansible_dns.search, there is another domain there too (sourced from DHCP options) so it has to be filtered out:

- name: "set region"
  set_fact:
    aws_region: "{{ domain.split('.')[0] }}"
  when: "'compute' in domain"
  loop: "{{ ansible_dns.search }}"
  loop_control:
    loop_var: domain
    label: "{{ domain }}"

The next step is to determine the instance id. The easiest way of doing it is to call the meta-data service:

- name: get instance id
  uri:
    url: "http://169.254.169.254/latest/meta-data/instance-id"
    return_content: true
  register: inststance_id_raw

That instance id can be used by ec2_instance_facts Ansible module to filter out only information that pertains to current instance:

- name: get ec2 instance facts
  ec2_instance_facts:
    region: "{{ aws_region }}"
    instance_ids: "{{ inststance_id_raw.content }}"
  register: ec2_facts

Finally, we can set the hostname to the value extracted from instance tag Name and the ansible domain (in this case on Amazon Linux 2):

- name: setup hostname
  command: hostnamectl set-hostname {{ ec2_facts.instances[0].tags.Name }}.{{ ansible_domain }}
Show Comments