Amazon Linux 2でAMIからのEC2インスタンス起動時に、cloud-initを使ってhostnameの設定とRoute53への登録を自動で行う

本記事は、[サムザップ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/sumzap) の12/6の記事です。

#はじめに

はじめまして、サムザップの[北島](https://twitter.com/RyotoKitajima)です。

突然ですが、数ヶ月前、Amazon Linux 2のEC2インスタンスをAMIから起動したときに、設定してあったホスト名が反映されず、デフォルトの ``ip-XX-XX-XX-XX`` になってしまうという事象に当たりました。
これは面倒だ！ということで、cloud-initを使って自動でホスト名を設定するようにした（ついでにRoute53への登録も）ので、その時のメモとしてこの記事を残します。

#clound-initの設定

では、さっそくですが以下、手順になります。

まず、bootcmdにスクリプトを仕込みます。

**/etc/cloud/cloud.cfg.d/init.cfg**

```
bootcmd:
  - /etc/cloud/cloud.cfg.d/init.sh
```

ここでclund-initの実行順序を詳しく解説することはしませんが、bootcmdだとインスタンス起動時に毎回実行され、runcmdだとインスタンスの初回起動時だけの実行になります。

続いて、仕込んだスクリプトの中身を用意します。

**/etc/cloud/cloud.cfg.d/init.sh**

```
#!/bin/bash

## シェルプロンプトの変更

instance_id=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
region="ap-northeast-1"

host_name=`aws ec2 describe-instances --instance-ids $instance_id --region $region --query 'Reservations[].Instances[].Tags[?Key==\`Name\`].Value[]' --output text`

if [ -z "$host_name" ]; then
  echo "Name tag is not set" 1>&2
  exit 1
fi

hostnamectl set-hostname $host_name

## Route 53 のレコード追加

env=`aws ec2 describe-instances --instance-ids $instance_id --region $region --query 'Reservations[].Instances[].Tags[?Key==\`Env\`].Value[]' --output text`

r53_zone_name="hogehoge-${env}.internal"

r53_zone_id=`aws route53 list-hosted-zones | jq -r ".HostedZones[] | [.Id, .Name] |@csv" | grep internal | awk -F "," '{print $1}' | xargs basename`

private_ip_address=`aws ec2 describe-instances --instance-ids $instance_id --region $region --query 'Reservations[].Instances[].PrivateIpAddress[]' --output text`

old_ip=`aws route53 list-resource-record-sets --hosted-zone-id $r53_zone_id |jq -r ".ResourceRecordSets[]|select(.Name == \"${host_name}.${r53_zone_name}.\").ResourceRecords[].Value"`

if [ "$old_ip" != "$private_ip_address"  ]; then
  echo "private ip          : $private_ip_address"
  echo "route53 record value: $old_ip"

  # delete record
  if [ "$old_ip" != "" ]; then
    cp /usr/local/src/dns_recordset.json /tmp/
    sed -i \
      -e "s;__RECORD__;${old_ip};g" \
      -e "s;__NAME__;${host_name}.${r53_zone_name}.;g" \
      -e "s;__ACTION__;DELETE;g" \
      /tmp/dns_recordset.json

    aws route53 change-resource-record-sets --hosted-zone-id ${r53_zone_id} --change-batch file:///tmp/dns_recordset.json && \
    rm -fr /tmp/dns_recordset.json
  fi

  # create record
  cp /usr/local/src/dns_recordset.json /tmp/
  sed -i \
    -e "s;__RECORD__;${private_ip_address};g" \
    -e "s;__NAME__;${host_name}.${r53_zone_name}.;g" \
    -e "s;__ACTION__;CREATE;g" \
    /tmp/dns_recordset.json

  aws route53 change-resource-record-sets --hosted-zone-id ${r53_zone_id} --change-batch file:///tmp/dns_recordset.json && \
  rm -fr /tmp/dns_recordset.json

fi
```

以上です、簡単ですね！

なお、EC2とRoute53へのアクセス権限はロールを付与しておかないと動かないのでご注意ください。
cloud-initはインスタンスの起動時に動いてくれるので、こんな感じで最初に設定したいものなんかを書いておけば自動で設定してくれるので便利ですね！

#まとめ

というわけで、今回はcloud-initを使ってhostnameの設定とRoute53への登録を自動で行う方法を紹介しました。
同じ問題に当たった人の参考になれば嬉しいです。

以上、[サムザップ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/sumzap) の12/6の記事でした。
明日は [@Gaku_Ishii](https://qiita.com/Gaku_Ishii) さんの記事です、お楽しみに！