Lab: Deploy หลาย Environment
📖 text • 25 นาทีLab: Deploy หลาย Environment
สิ่งที่ต้องมี: Terraform + AWS Credentials ตั้งค่าแล้ว
เป้าหมาย
สร้างโปรเจคที่ deploy ได้ทั้ง dev และ prod ด้วย code ชุดเดียว — แค่เปลี่ยน tfvars file
Step 1: สร้างโปรเจค
mkdir terraform-multi-env-lab && cd terraform-multi-env-lab
mkdir environments
Step 2: เขียน variables.tf
variable "environment" {
description = "Deployment environment"
type = string
validation {
condition = contains(["dev", "prod"], var.environment)
error_message = "Environment must be dev or prod."
}
}
variable "project" {
description = "Project name"
type = string
default = "myapp"
}
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t2.micro"
}
variable "instance_count" {
description = "Number of instances"
type = number
default = 1
}
variable "enable_monitoring" {
description = "Enable detailed monitoring"
type = bool
default = false
}
variable "allowed_ssh_cidrs" {
description = "CIDRs allowed for SSH access"
type = list(string)
default = ["0.0.0.0/0"]
}
Step 3: เขียน locals.tf
locals {
name_prefix = "${var.project}-${var.environment}"
common_tags = {
Project = var.project
Environment = var.environment
ManagedBy = "terraform"
}
}
Step 4: เขียน main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
required_version = ">= 1.0"
}
provider "aws" {
region = "ap-southeast-1"
}
# หา AMI ล่าสุด
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-2023.*-x86_64"]
}
}
# Default VPC
data "aws_vpc" "default" {
default = true
}
# Security Group
resource "aws_security_group" "web" {
name = "${local.name_prefix}-web-sg"
description = "Security group for ${local.name_prefix}"
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 = var.allowed_ssh_cidrs
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-web-sg"
})
}
# EC2 Instances
resource "aws_instance" "web" {
count = var.instance_count
ami = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
monitoring = var.enable_monitoring
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
cat > /var/www/html/index.html <<HTML
<h1>${local.name_prefix} - Server ${count.index}</h1>
<p>Environment: ${var.environment}</p>
<p>Instance Type: ${var.instance_type}</p>
HTML
EOF
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-web-${count.index}"
})
}
Step 5: เขียน outputs.tf
output "instance_ids" {
description = "IDs ของ EC2 instances ทั้งหมด"
value = aws_instance.web[*].id
}
output "public_ips" {
description = "Public IPs ทั้งหมด"
value = aws_instance.web[*].public_ip
}
output "web_urls" {
description = "URLs ของเว็บทั้งหมด"
value = [for ip in aws_instance.web[*].public_ip : "http://${ip}"]
}
output "security_group_id" {
description = "Security Group ID"
value = aws_security_group.web.id
}
output "summary" {
description = "สรุปการ deploy"
value = <<-EOT
Environment: ${var.environment}
Instance Count: ${var.instance_count}
Instance Type: ${var.instance_type}
Monitoring: ${var.enable_monitoring}
EOT
}
Step 6: สร้าง tfvars files
environments/dev.tfvars
environment = "dev"
instance_type = "t2.micro"
instance_count = 1
enable_monitoring = false
allowed_ssh_cidrs = ["0.0.0.0/0"] # lab เท่านั้น
environments/prod.tfvars
environment = "prod"
instance_type = "t3.small"
instance_count = 2
enable_monitoring = true
allowed_ssh_cidrs = ["203.0.113.0/24"] # จำกัดเฉพาะ office IP
Step 7: Deploy Dev
terraform init
terraform plan -var-file="environments/dev.tfvars"
ดู plan — ควรเห็น:
- 1 Security Group
- 1 EC2 Instance (instance_count = 1)
- Instance type =
t2.micro
terraform apply -var-file="environments/dev.tfvars"
พิมพ์ yes
ดู output:
summary = <<-EOT
Environment: dev
Instance Count: 1
Instance Type: t2.micro
Monitoring: false
EOT
web_urls = [
"http://54.xx.xx.xx",
]
Step 8: ทดสอบ Dev
curl http://<DEV_PUBLIC_IP>
<h1>myapp-dev - Server 0</h1>
<p>Environment: dev</p>
<p>Instance Type: t2.micro</p>
Step 9: Destroy Dev
terraform destroy -var-file="environments/dev.tfvars"
พิมพ์ yes
หมายเหตุ: ใน lab นี้เราใช้ state เดียวกัน เพราะฉะนั้น ต้อง destroy ก่อนเปลี่ยน environment
ในงานจริง ควรใช้ remote state แยกตาม environment (backend key ต่างกัน)
Step 10: Deploy Prod (optional)
terraform plan -var-file="environments/prod.tfvars"
ดูความแตกต่าง:
- 2 EC2 Instances (instance_count = 2)
- Instance type =
t3.small - Monitoring = true
- SSH จำกัดเฉพาะ IP ที่กำหนด
terraform apply -var-file="environments/prod.tfvars" -auto-approve
ดู output:
web_urls = [
"http://54.xx.xx.xx",
"http://54.yy.yy.yy",
]
Step 11: Cleanup
# ลบ resource (ใช้ tfvars ที่ตรงกับ environment ปัจจุบัน)
terraform destroy -var-file="environments/prod.tfvars" -auto-approve
# ลบ lab directory
cd .. && rm -rf terraform-multi-env-lab
สิ่งที่ได้เรียนรู้
| Concept | สิ่งที่ฝึก |
|---|---|
| Variables | ประกาศ input variables พร้อม type + validation |
| Locals | สร้าง name prefix + common tags |
| tfvars | แยกค่าตาม environment |
| Outputs | แสดง summary และ URLs หลัง deploy |
-var-file |
เลือก environment ตอน plan/apply |
count |
สร้าง instance ตามจำนวนที่กำหนด |
[*] |
Splat expression ดึงค่าจาก list ของ resource |
สรุป
คุณเพิ่งสร้างโปรเจคที่ code ชุดเดียว deploy ได้หลาย environment — pattern นี้ใช้ในทุกโปรเจค Terraform จริง
Key takeaway:
- Code = เหมือนกันทุก environment
- tfvars = ค่าที่ต่างกันตาม environment
- State = แยกกันตาม environment (ในงานจริง)
บทถัดไปเราจะเรียนรู้เรื่อง Terraform Modules