Lab: สร้าง EC2 + Security Group
📖 text • 25 นาทีLab: สร้าง EC2 + Security Group
สิ่งที่ต้องมี: Terraform + AWS Credentials ตั้งค่าแล้ว (ดูบท Install Terraform)
เป้าหมาย
สร้าง EC2 Instance พร้อม Security Group ที่เปิด port 80 (HTTP) — ฝึกการเขียน resource หลายตัวที่เชื่อมกัน
Step 1: สร้างโปรเจค
mkdir terraform-ec2-lab && cd terraform-ec2-lab
Step 2: Provider Configuration
สร้างไฟล์ main.tf:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
required_version = ">= 1.0"
}
provider "aws" {
region = "ap-southeast-1"
}
Step 3: Data Source — หา AMI และ VPC
เพิ่มต่อใน main.tf:
# หา Amazon Linux 2023 AMI ล่าสุด
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-2023.*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# ใช้ Default VPC
data "aws_vpc" "default" {
default = true
}
Step 4: Security Group
เพิ่มต่อ:
resource "aws_security_group" "web" {
name = "web-sg"
description = "Allow HTTP and SSH"
vpc_id = data.aws_vpc.default.id
# อนุญาต HTTP จากทุกที่
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# อนุญาต SSH จากทุกที่ (lab เท่านั้น — production ควรจำกัด IP)
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# อนุญาต outbound ทั้งหมด
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "web-sg"
}
}
อธิบาย Security Group
| Rule | ความหมาย |
|---|---|
ingress port 80 |
อนุญาตคนเข้าเว็บ (HTTP) |
ingress port 22 |
อนุญาต SSH เข้า server |
egress all |
อนุญาต server ออกไปข้างนอกได้ทุก port |
cidr_blocks = ["0.0.0.0/0"] |
จากทุก IP address |
Step 5: EC2 Instance
เพิ่มต่อ:
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.web.id]
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello from Terraform!</h1><p>Instance: $(hostname)</p>" > /var/www/html/index.html
EOF
tags = {
Name = "web-server"
Environment = "lab"
ManagedBy = "terraform"
}
}
อธิบาย
ami= ใช้ AMI ที่หาจาก data source (ไม่ต้อง hardcode)vpc_security_group_ids= ผูก Security Group ที่สร้างไว้user_data= script ที่รันตอน instance เปิดครั้งแรก — ติดตั้ง Apache แล้วสร้างหน้าเว็บ
Step 6: Output
เพิ่มต่อ:
output "instance_id" {
description = "ID ของ EC2 instance"
value = aws_instance.web.id
}
output "public_ip" {
description = "Public IP ของ EC2 instance"
value = aws_instance.web.public_ip
}
output "web_url" {
description = "URL สำหรับเปิดเว็บ"
value = "http://${aws_instance.web.public_ip}"
}
output "ami_used" {
description = "AMI ที่ใช้"
value = data.aws_ami.amazon_linux.name
}
Step 7: Init & Plan
terraform init
terraform plan
ดู plan ให้ดี — ควรเห็น:
Plan: 2 to add, 0 to change, 0 to destroy.
2 resource = Security Group + EC2 Instance
Step 8: Apply
terraform apply
พิมพ์ yes แล้วรอ — EC2 ใช้เวลาสร้างประมาณ 30 วินาที
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
ami_used = "al2023-ami-2023.x.x-x86_64"
instance_id = "i-0abc123def456789"
public_ip = "54.xx.xx.xx"
web_url = "http://54.xx.xx.xx"
Step 9: ทดสอบ
เปิด URL จาก output web_url ในเบราว์เซอร์:
curl http://<PUBLIC_IP>
ควรเห็น:
<h1>Hello from Terraform!</h1><p>Instance: ip-xxx-xxx-xxx-xxx</p>
หมายเหตุ: อาจต้องรอ 1-2 นาทีให้ user_data ทำงานเสร็จ
Step 10: ดูข้อมูลใน State
# ดู resource ทั้งหมด
terraform state list
data.aws_ami.amazon_linux
data.aws_vpc.default
aws_instance.web
aws_security_group.web
# ดูรายละเอียด EC2
terraform state show aws_instance.web
Step 11: ลอง Modify
เพิ่ม tag ให้ EC2:
tags = {
Name = "web-server"
Environment = "lab"
ManagedBy = "terraform"
Course = "terraform-fundamentals" # เพิ่มบรรทัดนี้
}
terraform plan
~ resource "aws_instance" "web" {
~ tags = {
+ "Course" = "terraform-fundamentals"
}
}
Plan: 0 to add, 1 to change, 0 to destroy.
~ = update in-place (ไม่ต้องสร้างใหม่ แค่เพิ่ม tag)
terraform apply -auto-approve
Step 12: Destroy
สำคัญ: ลบ resource ทิ้งเมื่อเสร็จ lab เพื่อไม่ให้เสียค่าใช้จ่าย
terraform destroy
Plan: 0 to add, 0 to change, 2 to destroy.
Do you really want to destroy all resources?
Enter a value: yes
Destroy complete! Resources: 2 destroyed.
Cleanup
cd .. && rm -rf terraform-ec2-lab
สิ่งที่ได้เรียนรู้
| Concept | สิ่งที่ฝึก |
|---|---|
| Data Source | หา AMI และ VPC ที่มีอยู่ |
| Security Group | สร้าง firewall rules (ingress/egress) |
| EC2 Instance | สร้าง server พร้อม user_data |
| Resource Reference | เชื่อม SG กับ EC2 ด้วย aws_security_group.web.id |
| Output | แสดงข้อมูลหลัง apply (IP, URL) |
| Modify | เพิ่ม tag โดยไม่ต้องสร้าง resource ใหม่ |
ไฟล์ main.tf เต็ม
คลิกเพื่อดูโค้ดทั้งหมด
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
required_version = ">= 1.0"
}
provider "aws" {
region = "ap-southeast-1"
}
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-2023.*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
data "aws_vpc" "default" {
default = true
}
resource "aws_security_group" "web" {
name = "web-sg"
description = "Allow HTTP and SSH"
vpc_id = data.aws_vpc.default.id
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "web-sg"
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.web.id]
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello from Terraform!</h1><p>Instance: $(hostname)</p>" > /var/www/html/index.html
EOF
tags = {
Name = "web-server"
Environment = "lab"
ManagedBy = "terraform"
}
}
output "instance_id" {
description = "ID ของ EC2 instance"
value = aws_instance.web.id
}
output "public_ip" {
description = "Public IP ของ EC2 instance"
value = aws_instance.web.public_ip
}
output "web_url" {
description = "URL สำหรับเปิดเว็บ"
value = "http://${aws_instance.web.public_ip}"
}
output "ami_used" {
description = "AMI ที่ใช้"
value = data.aws_ami.amazon_linux.name
}
สรุป
คุณเพิ่งสร้าง infrastructure หลายชิ้นที่เชื่อมกัน: Data Source → Security Group → EC2 Instance
นี่คือ pattern ที่ใช้ในงานจริง — สร้าง resource หลายตัวแล้วเชื่อมกันด้วย reference
บทถัดไปเราจะเรียนรู้เรื่อง State Management