วิธีตั้งค่า Hostname โดยอัตโนมัติเมื่อ EC2 Instance เริ่มทำงาน - การเชื่อมโยงระหว่าง User data กับ Route 53

วิธีตั้งค่า Hostname โดยอัตโนมัติเมื่อ EC2 Instance เริ่มทำงาน - การเชื่อมโยงระหว่าง User data กับ Route 53

ในบทความนี้จะแนะนำวิธีตั้งค่า Hostname อัตโนมัติเมื่อ Amazon EC2 เริ่มทำงาน โดยใช้การเชื่อมต่อระหว่าง User Data Script และ Route 53 เพื่อให้สามารถจัดการ DNS ได้แบบอัตโนมัติ โดยไม่ต้องใช้ Elastic IP ซึ่งช่วยประหยัดค่าใช้จ่าย แม้จะเป็นอินสแตนซ์ที่มีการ Stop/Start บ่อย เช่นในสภาพแวดล้อมสำหรับการพัฒนา หรือเซิร์ฟเวอร์สำหรับรันงานแบบแบตช์ ก็ยังสามารถเข้าถึงได้ด้วย Hostname เดิมทุกครั้ง ทำให้สามารถสร้างระบบที่มีความยืดหยุ่นและคุ้มค่าได้อย่างง่ายดาย

ในการสร้างระบบด้วย AWS การกำหนด Hostname ที่เข้าใจง่ายให้กับ EC2 Instance ถือเป็นปัจจัยสำคัญที่ช่วยเพิ่มประสิทธิภาพในการจัดการระบบ โดยเฉพาะในสภาพแวดล้อมที่มีการใช้งาน Instance หลายตัว การที่สามารถเข้าถึงอินสแตนซ์ผ่าน Hostname ที่มีความหมาย แทนการใช้เพียงแค่ IP Address จะช่วยให้การดูแลระบบสะดวกยิ่งขึ้น

ในบทความนี้ เราจะอธิบายวิธีการสร้าง DNS Record บน Route 53 และกำหนด Hostname โดยอัตโนมัติเมื่อ EC2 Instance เริ่มทำงาน หรือเมื่อ Stop แล้ว Start Instance ใหม่อีกครั้ง โดยใช้ User data script จะช่วยลดภาระในการตั้งค่าด้วยตนเองทุกครั้งที่ Instance เริ่มทำงาน และช่วยให้การจัดการ DNS มีประสิทธิภาพมากยิ่งขึ้น

ในครั้งนี้เราจะนำเสนอวิธีที่ไม่ใช้ Elastic IP เพื่อหลีกเลี่ยงค่าใช้จ่ายที่เกิดจากการใช้ Elastic IP ดังนั้นวิธีนี้จึงเหมาะสำหรับเซิร์ฟเวอร์ที่มีการหยุดทำงานบ่อย แต่ยังต้องการกำหนด Hostname เช่น สภาพแวดล้อมสำหรับการพัฒนา (development environment), การทดสอบ (testing environment) หรือระบบสำหรับงานแบบ batch ซึ่งจะมีประโยชน์เป็นพิเศษในกรณีเหล่านี้

ข้อกำหนดเบื้องต้น

ในการตั้งค่านี้ จำเป็นต้องมีข้อกำหนดเบื้องต้นดังต่อไปนี้

  1. ต้องมีการตั้งค่า Hosted zone บน Route 53 เรียบร้อยแล้ว
  2. ต้องกำหนด IAM Role ที่มีสิทธิ์ในการจัดการ Route 53 ให้กับ EC2 Instance แล้ว (จะอธิบายในช่วงกลางของบทความ)
  3. ใช้ EC2 instance ที่เป็น Amazon Linux 2023

เตรียม Hosted zone บน Route 53

ก่อนอื่นจำเป็นต้องมี Hosted zone บน Route 53 ใน AWS Account หากยังไม่มี Hosted zone ให้สร้างเตรียมไว้ล่วงหน้าตามตัวอย่างในลิงก์บทความด้านล่างนี้

1. กรณีที่จด Domain บน AWS

หากจด Domain โดยตรงผ่าน Amazon Route 53 ระบบจะสร้าง Hosted zone ให้โดยอัตโนมัติ
ดูตัวอย่างการจด Domain ได้ที่ลิงก์ด้านล่างนี้
https://dev.classmethod.jp/articles/how-to-buy-a-domain-on-route-53/

2. กรณีที่ตั้งค่า Domain ที่จดจากผู้ให้บริการรายอื่น

หากต้องการจัดการ Domain ที่จดจาก Domain Registrar ที่ไม่ใช่ AWS ด้วย Route 53 คุณจำเป็นต้องสร้าง Hosted zone และเปลี่ยนการตั้งค่า Name servers ของ Domain นั้นให้ชี้มาที่ Name servers ของ Route 53

ให้ดูที่หัวข้อ ขั้นตอนในการเปลี่ยนชื่อ Domain Name
https://dev.classmethod.jp/articles/how-to-static-website-ep3-domain-ssl/#1.%2520%25E0%25B8%25AA%25E0%25B8%25A3%25E0%25B9%2589%25E0%25B8%25B2%25E0%25B8%2587%2520Hosted%2520Zone

3. กรณีที่ตั้งค่า Hosted zone สำหรับ Subdomain

คุณสามารถสร้าง Hosted zone สำหรับ Subdomain ของ Domain ที่มีอยู่แล้วได้เช่นกัน โดยวิธีนี้จะเป็นการสร้าง Hosted zone ที่ใช้เฉพาะสำหรับ Subdomain นั้นโดยเฉพาะ
https://dev.classmethod.jp/articles/route53-transfer-hostedzones-th/

ไม่ว่าจะใช้วิธีใด เมื่อการตั้งค่าเสร็จสมบูรณ์แล้ว อย่าลืมจดบันทึก Hosted zone ID เตรียมไว้ด้วย โดย ID นี้จะมีรูปแบบประมาณนี้

ZXXXXXXXXXXXXXXXXXXXX

เตรียม IAM Role ที่ใช้สำหรับ EC2

เพื่อให้ EC2 Instance สามารถอัปเดต DNS Record บน Route 53 ได้ จำเป็นต้องมี IAM Role ที่มีสิทธิ์ที่เหมาะสม โดยสามารถสร้าง IAM Role ได้ตามขั้นตอนด้านล่างนี้

  1. ไปที่บริการ "Identity and Access Management (IAM)"
  2. เลือก "Roles" จากเมนูด้านซ้าย แล้วคลิก "Create role"
  3. เลือก "AWS service" และเลือก "EC2" จากนั้นคลิก "Next"
  4. แนบ Policy: AmazonRoute53FullAccess (ในสภาพแวดล้อมจริง แนะนำให้ใช้ Policy ที่จำกัดสิทธิ์มากกว่านี้)
  5. เพิ่ม Tag ตามความจำเป็น
  6. ป้อน Role name เช่น "ec2-route53-access" แล้วคลิก "Create role"

หากต้องการควบคุมสิทธิ์การเข้าถึงอย่างละเอียดมากขึ้น แนะนำให้สร้าง Custom Policy ตามตัวอย่างด้านล่างนี้ เพื่ออนุญาตให้ดำเนินการเฉพาะกับ Hosted zone ที่ระบุเท่านั้น

{
    "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/*"
            ]
        }
    ]
}

Policy นี้จะอนุญาตเฉพาะการดำเนินการเปลี่ยนแปลง DNS Record สำหรับ Hosted zone ที่ระบุเท่านั้น (อย่าลืมแทนที่ส่วนที่เป็น ZXXXXXXXXXXXXXXXXXXXX ด้วย Hosted zone ID จริงของคุณ)

สร้าง EC2 Instance

สร้าง EC2 Instance ที่ใช้ OS ของ Amazon Linux 2023 และในการตั้งค่ารายละเอียดต่างๆ ของ Instance โปรดระวังในจุดต่อไปนี้

  1. เปิดใช้งาน Public IP Address (เพื่อให้สามารถลงทะเบียนใน DNS Record ได้)
  2. หัวข้อ "IAM instance profile" ในส่วนของ "Advanced details" ให้เลือก IAM Role (ec2-route53-access) ที่สร้างไว้ก่อนหน้านี้ให้กับ Instance
  3. หัวข้อ "User data" ในส่วนของ "Advanced details" ให้ป้อน Script ที่จะแนะนำในหัวข้อถัดไป

ดูตัวอย่างการสร้าง EC2 Instance ได้ที่ลิงก์ด้านล่างนี้
https://dev.classmethod.jp/articles/how-to-install-amazon-linux-2023-on-ec2/

ตั้งค่า User data script

ใช้ User data script ด้านล่างนี้เพื่อตั้งค่า Hostname โดยอัตโนมัติเมื่อ EC2 Instance เริ่มทำงาน หรือเมื่อ Stop แล้ว Start Instance ใหม่อีกครั้ง ซึ่ง Script นี้จะดึง IP Address จาก Metadata ของ Instance และลงทะเบียน DNS Record บน Route 53

ให้ตั้งค่า Script นี้ไว้ในส่วน User data ของ EC2 Instance โดยอย่าลืมเปลี่ยนค่า HOSTED_ZONE_ID, HOSTNAME และ DOMAIN ให้ตรงกับสภาพแวดล้อมจริงของคุณ

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

# การตั้งค่า Parameters
HOSTED_ZONE_ID="ZXXXXXXXXXXXXXXXXXXXX"  # Hosted zone ID ของคุณ
HOSTNAME="dev"                 # Hostname ที่ต้องการตั้งค่า
DOMAIN="example.com"           # Domain ของคุณ
FQDN="${HOSTNAME}.${DOMAIN}"
TTL=300

# ตั้งค่าปลายทางสำหรับการบันทึก log
exec > /var/log/user-data.log 2>&1

# ตั้งค่า Environmental variables
export PATH=$PATH:/usr/local/bin:/usr/bin
export HOME=/root

# รอการเตรียมความพร้อมของ Network
echo "กำลังรอการเตรียม Network..."
sleep 10

# เปิดใช้งานการจัดการข้อผิดพลาด (Error Handling)
set -e

# เปิดใช้งานการแสดงผล debug
set -x

# รับ Token สำหรับ IMDSv2
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# รับข้อมูล Instance จาก Metadata (รองรับ 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) เพื่อรับ Region

# รับ Public IP address
PUBLIC_IP=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/public-ipv4)

# การจัดการข้อผิดพลาด (Error Handling) ในกรณีที่ไม่สามารถรับ Public IP ได้
if [ -z "$PUBLIC_IP" ]; then
    echo "คำเตือน: ไม่สามารถรับ Public IP address ได้"
    echo "Instance นี้อาจไม่มี Public IP ที่กำหนดไว้ หรืออาจล้มเหลวในการรับข้อมูล"
    echo "จะใช้ Private 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 (Private IP)"
else
    IP_TO_USE=$PUBLIC_IP
    echo "IP ที่จะใช้: $IP_TO_USE (Public IP)"
fi

# ตรวจสอบว่าได้รับข้อมูล Region หรือไม่
if [ -z "$REGION" ]; then
    echo "การรับข้อมูล Region ล้มเหลว จะใช้ Region เริ่มต้น"
    REGION=$(aws configure get region)
    if [ -z "$REGION" ]; then
        REGION="us-east-1"  # โปรดเปลี่ยนเป็น Region ที่เหมาะสม
    fi
fi

# การตั้งค่า Parameters
echo "Instance ID: $INSTANCE_ID"
echo "Region: $REGION"
echo "Hostname: $HOSTNAME"
echo "FQDN: $FQDN"
echo "IP Address: $IP_TO_USE"

# ลงทะเบียน DNS record ใน Route 53
echo "กำลังลงทะเบียน DNS record ใน Route 53..."
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 record เรียบร้อยแล้ว: $CHANGE_ID"

# ตั้งค่า Hostname ให้กับระบบ
echo "กำลังตั้งค่า Hostname ของระบบ..."
hostnamectl set-hostname $HOSTNAME || hostname $HOSTNAME
echo "127.0.0.1 $HOSTNAME $FQDN localhost" > /etc/hosts

# ตรวจสอบว่าการเปลี่ยนแปลงถูกนำไปใช้แล้ว
echo "การตั้งค่าเสร็จสมบูรณ์:"
echo "Hostname: $(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 แล้ว"

--//--

ตัวอย่างการตั้งค่า Script

กรุณาแก้ไขค่า Parameters ด้านล่างให้เหมาะสมกับสภาพแวดล้อมของคุณ

  • HOSTED_ZONE_ID: Hosted zone ID ของ Route 53 (เช่น: ZXXXXXXXXXXXXXXXXXXXX)
  • HOSTNAME: Hostname ที่ต้องการตั้งค่า (ตัวอย่าง: dev, db-master, app-server-1)
  • DOMAIN: Domain name (ตัวอย่าง: example.com, mycompany.internal)

ตัวอย่างเช่น หากต้องการตั้งค่า Server สำหรับการพัฒนาโดยใช้ Domain ชื่อ dev.example.com

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

วิธีการตรวจสอบการทำงาน

เมื่อเปิดใช้งาน EC2 Instance และ User data script ถูกเรียกใช้งานแล้ว จะสามารถตรวจสอบการทำงานได้ด้วยวิธีต่อไปนี้ (แม้แต่ในกรณีที่ Stop และ Start Instance อีกครั้ง ก็สามารถตรวจสอบการทำงานได้)

  1. เชื่อมต่อ SSH ไปยัง EC2 Instance
    ตรวจสอบว่า Hostname ถูกตั้งค่าอย่างถูกต้องหรือไม่

  2. ทดสอบการแก้ไข DNS จาก Local Machine

nslookup dev.example.com
# หรือ
dig dev.example.com
  1. ตรวจสอบ log ของ User data script
cat /var/log/user-data.log

Troubleshooting

หาก Script ไม่ทำงานตามปกติ กรุณาตรวจสอบสิ่งต่อไปนี้

  1. สิทธิ์ของ IAM Role: ตรวจสอบว่า IAM Role ที่กำหนดให้กับ EC2 Instance มีสิทธิ์ในการแก้ไขข้อมูลบน Route 53 หรือไม่
  2. การเชื่อมต่อ Network: ตรวจสอบว่า EC2 Instance สามารถเข้าถึง Route 53 API ได้หรือไม่ (ในบางกรณีอาจต้องใช้ VPC Endpoint หรือ NAT Gateway)
  3. ตรวจสอบ Log: ตรวจสอบไฟล์ /var/log/user-data.log เพื่อดู Error Message
  4. การมีอยู่ของ Public IP: ตรวจสอบว่า Instance ได้รับการกำหนด Public IP แล้วหรือไม่

ทดสอบ URL

ติดตั้ง PHP 8.2 และ Apache ใน Amazon Linux 2023 บน EC2 แล้วทดสอบด้วย Domain name ที่ถูกสร้างขึ้น ในตัวอย่างนี้คือ dev.subdomain.cmthai.click

ดูตัวอย่างได้ที่ลิงก์ด้านล่างนี้
https://dev.classmethod.jp/articles/how-to-install-php82-and-apache-in-ec2-amazon-linux-2023/

สรุป

ในบทความนี้เราได้อธิบายวิธีการสร้าง DNS Record บน Route 53 และตั้งค่า Hostname โดยอัตโนมัติเมื่อ EC2 Instance เริ่มทำงาน หรือเมื่อ Stop แล้ว Start ใหม่อีกครั้ง โดยการใช้ User data script ช่วยให้สามารถทำกระบวนการ Provisioning ของ Instance ได้แบบอัตโนมัติ และลดภาระในการจัดการลงได้อย่างมาก

โดยการตั้งค่านี้สามารถทำได้โดยไม่ต้องใช้ Elastic IP ซึ่งช่วยเพิ่มความคุ้มค่าด้านต้นทุน และยังสามารถเข้าถึง Instance ที่มีการ Start และ Stop บ่อยๆ เช่น สภาพแวดล้อมสำหรับการพัฒนา (development environment), การทดสอบ (testing environment) หรือระบบสำหรับงานแบบ batch ได้ด้วย Hostname ที่คงที่

ขอแนะนำให้คุณลองนำวิธีนี้ไปใช้งาน เพื่อเพิ่มประสิทธิภาพในการจัดการ EC2 Instance บน AWS ของคุณครับ

บทความต้นฉบับ

https://dev.classmethod.jp/articles/aws-ec2-auto-hostname-route53-userdata/

แปลโดย: POP(Tinnakorn Maneewong) จากบริษัท Classmethod (Thailand) ครับ !

บทความที่เกี่ยวข้อง

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.