AWS EC2起動時に自動でホスト名を設定する方法 - Route 53とユーザーデータの連携

AWS EC2起動時に自動でホスト名を設定する方法 - Route 53とユーザーデータの連携

AWS EC2起動時に自動でホスト名を設定する方法を紹介します。Route 53とユーザーデータスクリプトを連携させることで、ElasticIPを使わずにコスト効率よくDNS管理を自動化。開発環境やバッチサーバーなど頻繁に停止・起動するインスタンスでも、常に同じホスト名でアクセスできる環境を簡単に構築できます。
Clock Icon2025.04.24

AWSを使ったシステム構築において、EC2インスタンスに分かりやすいホスト名を割り当てることは、管理効率を高める重要な要素です。特に複数のインスタンスを運用する環境では、IPアドレスだけでなく意味のあるホスト名でアクセスできると便利です。

本記事では、EC2インスタンス起動時及び停止してから再度起動した際に自動的にRoute 53のDNSレコードを作成し、ホスト名を割り当てる方法を解説します。ユーザーデータスクリプトを活用することで、インスタンス起動のたびに手動設定する手間を省き、DNS管理を効率化できます。

今回は、あえてElasticIPを使わない方法を紹介します。これはElasticIPによるコストを抑えるためです。そのため、頻繁に停止するようなサーバーだけれど、ホスト名を定義したい場合などに役立ちます。開発や検証環境、バッチ用の環境などで特に有用です。

前提条件

この設定を行うには、以下の前提条件を満たしている必要があります。

  1. Route 53のホストゾーンが設定済みであること
  2. EC2インスタンスにRoute 53操作権限を持つIAMロールが割り当てられていること(記事の中盤で説明します)
  3. Amazon Linux 2023のEC2インスタンスを使用すること

Route 53ホストゾーンの準備

まず、AWS アカウントの Route 53 にホストゾーンが必要です。ホストゾーンがまだない場合は、以下のいずれかの方法で事前に作成してください。

1. AWSでドメインを購入する場合

AWS Route 53でドメインを直接購入すると、自動的にホストゾーンが作成されます。
実際の購入方法は以下を参考にしてください。

https://dev.classmethod.jp/articles/purchasing-a-domain-with-route-53/

2. 他のプロバイダーから購入したドメインを設定する場合

AWS以外のドメインレジストラで購入したドメインをRoute 53で管理するには、ホストゾーンを作成し、ネームサーバーの設定を変更する必要があります。
実際の設定方法は以下を参考にしてください。

https://dev.classmethod.jp/articles/route53-domain-onamae/

3. サブドメインのホストゾーンを設定する場合

既存のドメインのサブドメイン用にホストゾーンを作成することもできます。この方法では、サブドメイン専用のホストゾーンが作成されます。

https://dev.classmethod.jp/articles/route53-transfer-hostedzones-2021/

いずれの方法でも、設定が完了したらホストゾーンIDをメモしておきましょう。このIDは以下のような形式になります。

ZXXXXXXXXXXXXXXXXXXXX

EC2用のIAMロールの準備

EC2インスタンスがRoute 53のDNSレコードを更新するためには、適切な権限を持つIAMロールが必要です。以下の手順でIAMロールを作成します。

  1. AWSマネジメントコンソールから「IAM」サービスに移動
  2. 左側のメニューから「ロール」を選択し、「ロールの作成」をクリック
  3. 「AWS サービス」を選択し、「EC2」を選択して「次へ」をクリック
  4. 以下のポリシーをアタッチ:
    • AmazonRoute53FullAccess(本番環境ではより制限されたポリシーを推奨)
  5. 必要に応じて、タグを追加
  6. ロール名「ec2-route53-access」を入力して「ロールの作成」をクリック

より細かい権限制御が必要な場合は、以下のようなカスタムポリシーを作成し、特定のホストゾーンに対する操作のみを許可することをお勧めします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "route53:ChangeResourceRecordSets",
                "route53:ListResourceRecordSets",
                "route53:GetHostedZone"
            ],
            "Resource": [
                "arn:aws:route53:::hostedzone/ZXXXXXXXXXXXXXXXXXXXX"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "route53:GetChange"
            ],
            "Resource": [
                "arn:aws:route53:::change/*"
            ]
        }
    ]
}

このポリシーでは、特定のホストゾーン(ZXXXXXXXXXXXXXXXXXXXXの部分を実際のホストゾーンIDに置き換えてください)に対するDNSレコードの変更操作のみを許可しています。

EC2インスタンスの起動

Amazon Linux 2023のEC2インスタンスを起動します。インスタンスの詳細設定で、以下の点に注意してください。

  1. 先ほど作成したIAMロール(ec2-route53-access)をインスタンスに割り当てる
  2. パブリックIPアドレスを有効にする(DNSレコードに登録するため)
  3. 「詳細設定」の「ユーザーデータ」セクションに、次のセクションで紹介するスクリプトを入力

詳細なEC2インスタンスの起動手順については、以下の記事を参考にしてください。

https://dev.classmethod.jp/articles/how-to-install-amazon-linux-2023-on-ec2-jp/

ユーザーデータスクリプトの設定

EC2インスタンスの起動時及び停止してから再度起動時に自動的にホスト名を設定するために、以下のユーザーデータスクリプトを使用します。このスクリプトは、インスタンスのメタデータからIPアドレスを取得し、Route 53にDNSレコードを登録します。

以下のスクリプトをEC2インスタンスのユーザーデータに設定してください。HOSTED_ZONE_IDHOSTNAMEDOMAINの値は、実際の環境に合わせて変更してください。

Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud_final_modules:
- [scripts-user, always]

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash

# 設定パラメータ
HOSTED_ZONE_ID="Z0XXXXXXXXXX"  # あなたのホストゾーンID
HOSTNAME="dev"                 # 設定したいホスト名
DOMAIN="example.com"           # あなたのドメイン
FQDN="${HOSTNAME}.${DOMAIN}"
TTL=300

# ログ出力先を設定
exec > /var/log/user-data.log 2>&1

# 環境変数を設定
export PATH=$PATH:/usr/local/bin:/usr/bin
export HOME=/root

# ネットワークの準備を待つ
echo "ネットワークの準備を待機中..."
sleep 10

# エラーハンドリングを有効化
set -e

# デバッグ出力を有効化
set -x

# IMDSv2用のトークンを取得
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# メタデータからインスタンス情報を取得(IMDSv2対応)
INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id)
AZ=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
REGION=${AZ%?} # 最後の文字(a,b,cなど)を削除してリージョンを取得

# パブリックIPアドレスを取得
PUBLIC_IP=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/public-ipv4)

# パブリックIPが取得できない場合のエラーハンドリング
if [ -z "$PUBLIC_IP" ]; then
    echo "警告: パブリックIPアドレスが取得できませんでした。"
    echo "このインスタンスにはパブリックIPが割り当てられていないか、取得に失敗した可能性があります。"
    echo "代わりにプライベートIPを使用します。"
    PRIVATE_IP=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/local-ipv4)
    IP_TO_USE=$PRIVATE_IP
    echo "使用するIP: $IP_TO_USE (プライベートIP)"
else
    IP_TO_USE=$PUBLIC_IP
    echo "使用するIP: $IP_TO_USE (パブリックIP)"
fi

# リージョンが取得できているか確認
if [ -z "$REGION" ]; then
    echo "リージョンの取得に失敗しました。デフォルトリージョンを使用します。"
    REGION=$(aws configure get region)
    if [ -z "$REGION" ]; then
        REGION="us-east-1"  # 適切なリージョンに変更してください
    fi
fi

# 設定パラメータ
echo "インスタンスID: $INSTANCE_ID"
echo "リージョン: $REGION"
echo "ホスト名: $HOSTNAME"
echo "FQDN: $FQDN"
echo "IPアドレス: $IP_TO_USE"

# Route53にDNSレコードを登録
echo "Route53にDNSレコードを登録中..."
CHANGE_BATCH='{
    "Changes": [
      {
        "Action": "UPSERT",
        "ResourceRecordSet": {
          "Name": "'$FQDN'",
          "Type": "A",
          "TTL": '$TTL',
          "ResourceRecords": [
            {
              "Value": "'$IP_TO_USE'"
            }
          ]
        }
      }
    ]
  }'

echo "変更内容: $CHANGE_BATCH"

# AWS CLIコマンドを実行
CHANGE_ID=$(aws route53 change-resource-record-sets \
  --hosted-zone-id "$HOSTED_ZONE_ID" \
  --change-batch "$CHANGE_BATCH" \
  --output text \
  --query 'ChangeInfo.Id')

echo "DNSレコード更新リクエスト送信完了: $CHANGE_ID"

# ホスト名をシステムに設定
echo "システムのホスト名を設定中..."
hostnamectl set-hostname $HOSTNAME || hostname $HOSTNAME
echo "127.0.0.1 $HOSTNAME $FQDN localhost" > /etc/hosts

# 変更が反映されたことを確認
echo "設定完了:"
echo "ホスト名: $(hostname)"
echo "hosts ファイル:"
cat /etc/hosts

# オプション: DNSの変更が伝播するまで待機
echo "DNSの変更が伝播するまで待機中..."
aws route53 wait resource-record-sets-changed --id "$CHANGE_ID"
echo "DNSの変更が伝播しました。"

echo "セットアップ完了: $FQDN は $IP_TO_USE に紐づけられました"

--//--

スクリプトの設定例

実際の環境に合わせて、以下のパラメータを変更してください。

  • HOSTED_ZONE_ID: Route 53のホストゾーンID(例: Z0XXXXXXXXXX
  • HOSTNAME: 設定したいホスト名(例: dev, db-master, app-server-1
  • DOMAIN: ドメイン名(例: example.com, mycompany.internal

例えば、dev.example.comというドメインで開発サーバーを設定する場合。

HOSTED_ZONE_ID="Z0XXXXXXXXXX"
HOSTNAME="dev"
DOMAIN="example.com"

動作確認方法

EC2インスタンスが起動し、ユーザーデータスクリプトが実行されると、以下の方法で動作を確認できます。(インスタンスの停止から再度起動した場合でも動作します)

  1. EC2インスタンスにSSH接続
    ホスト名が正しく設定されているか確認してください。

  2. ローカルマシンからDNS解決をテスト

    nslookup dev.example.com
    # または
    dig dev.example.com
    
  3. ユーザーデータスクリプトのログを確認

    cat /var/log/user-data.log
    

トラブルシューティング

スクリプトが正常に動作しない場合は、以下の点を確認してください。

  1. IAMロールの権限:EC2インスタンスに割り当てられたIAMロールがRoute 53の変更権限を持っているか確認

  2. ネットワーク接続:EC2インスタンスがRoute 53 APIにアクセスできるか確認(VPCエンドポイントまたはNATゲートウェイが必要な場合があります)

  3. ログの確認/var/log/user-data.logを確認して、エラーメッセージを確認

  4. パブリックIPの有無:インスタンスにパブリックIPが割り当てられているか確認

まとめ

この記事では、EC2インスタンスの起動時に自動的にRoute 53のDNSレコードを作成し、ホスト名を設定する方法を解説しました。ユーザーデータスクリプトを活用することで、インスタンスのプロビジョニングプロセスを自動化し、管理の手間を大幅に削減できます。

特にElasticIPを使用せずにこの設定を行うことで、コスト効率を高めながらも、開発環境や検証環境、バッチ処理用のサーバーなど、頻繁に停止・起動するインスタンスに対して一貫したホスト名でアクセスできる環境を構築できます。

ぜひこの方法を活用して、AWS環境でのEC2インスタンス管理を効率化してください。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.