0
votes

Is there a way to use the values from instance tags to set the hostname on an EC2 instance, using cloud-init in user-data?

Something like this?

#cloud-config
preserve_hostname: false
hostname: my-custom-hostname
fqdn: my-custom-hostname.local
manage_etc_hosts: true

Except using an instance tag, such a "Name" or "hostname". I've seen some examples using Jinja templates, which seems to be along the right lines. But I'm not sure if/how to reference the instance tags in the user-data/cloud-init. If this makes more sense to bake into the AMI, I don't mind that - it doesn't have to be user-data. However, I currently am running a hostmod.sh shell script at instance launch that reads the tags, and sets the hostname.

## template: jinja
preserve_hostname: false
hostname: {% tags.hostname %}
fqdn: {% tags.hostname %}.local
manage_etc_hosts: true
2
I can see in the /var/log/cloud-init.log that the EC2 instance metadata is being read. I feel like I'm either close, or approaching this completely the wrong way? cloud-init[2412]: url_helper.py[DEBUG]: [0/6] open 'http://169.254.169.254/latest/meta-data/local-hostname' with {'url': 'http://169.254.169.254/latest/meta-data/local-hostname', 'headers': {'User-Agent': 'Cloud-Init/0.7.6'}, 'allow_redirects': True, 'method': 'GET', 'timeout': 5.0} configurationshawnjohnson

2 Answers

2
votes

One idea that worked for me was use shell parameter expansion (I think that's the right term). I am still maintaining my own script, baked into my AMI, but I prefer the template-like approach versus my previous script that used sed to modify the /etc/hosts file.

#!/bin/bash

# Get Name tag from AWS instance metadata
ec2id=$(curl http://169.254.169.254/latest/meta-data/instance-id)
hostname=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$ec2id" "Name=key,Values=Name" --region us-east-1 | awk '/"Value":/ {print $2}' | tr -d '",')
fqdn="${hostname}.local"

# Write a new hosts file using variable expansion
cat >/etc/hosts <<EOF
# The following lines are desirable for IPv4 capable hosts
127.0.0.1 ${fqdn} ${hostname}
127.0.0.1 localhost.localdomain localhost
127.0.0.1 localhost4.localdomain4 localhost4
# The following lines are desirable for IPv6 capable hosts
::1 ${fqdn} ${hostname}
::1 localhost.localdomain localhost
::1 localhost6.localdomain6 localhost6
EOF

I run the script via cloud-init defined in user data:

#cloud-config
runcmd:
  - bash /usr/local/bin/hostmod.sh

I also tried creating the entire script within user data via cloud-config. This works as well, but I split the file out to make it easier to manage separately in Ansible.

#cloud-config
write_files:
  - path: /usr/local/bin/hostmod.sh
    permissions: 0744
    owner: root
    content: |
      #!/bin/bash

      ec2id=$(curl http://169.254.169.254/latest/meta-data/instance-id)
      hostname=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$ec2id" "Name=key,Values=Name" --region us-east-1 | awk '/"Value":/ {print $2}' | tr -d '",')
      fqdn="${hostname}.local"

      cat >/etc/hosts <<EOF
      # The following lines are desirable for IPv4 capable hosts
      127.0.0.1 ${fqdn} ${hostname}
      127.0.0.1 localhost.localdomain localhost
      127.0.0.1 localhost4.localdomain4 localhost4
      # The following lines are desirable for IPv6 capable hosts
      ::1 ${fqdn} ${hostname}
      ::1 localhost.localdomain localhost
      ::1 localhost6.localdomain6 localhost6
      EOF

runcmd:
  - bash /usr/local/bin/hostmod.sh

This obviously doesn't change the hostname, which is a bit more platform dependent. That is why I preferred to use cloud-init from the start. I may later add a similar template for updating the hostname.

0
votes

This script will allow you to update the Amazon Linux (v1) hostname configured in /etc/sysconfig/network - both parts are necessary to correctly configure the hostname.

#! /bin/bash
#
export EC2_AVAIL_ZONE=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone` 
export EC2_REGION="`echo \"$EC2_AVAIL_ZONE\" | sed 's/[a-z]$//'`"
export ec2id=$(curl http://169.254.169.254/latest/meta-data/instance-id )
export ec2name=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$ec2id" "Name=key,Values=Name" --region $EC2_REGION | awk '/"Value":/ {print $2}' | tr -d '",')
#
hostname ${ec2name}
cat > /etc/sysconfig/network << EOF
NETWORKING=yes
HOSTNAME=${ec2name}
NOZEROCONF=yes
EOF