Terraform คืออะไร?
Terraform เป็น Infrastructure as Code (IaC) Tool ที่ช่วยให้เราสร้าง จัดการ และรื้อถอน Infrastructure ผ่าน Configuration Files แทนการทำผ่าน UI หรือ CLI แบบ Manual
ข้อดีของ Infrastructure as Code
- Version Control: เก็บ Infrastructure ใน Git
- Reproducible: สร้าง Environment เหมือนกันได้หลายครั้ง
- Collaborative: ทีมงานทำงานร่วมกันได้
- Automation: รวมเข้ากับ CI/CD Pipeline
- Documentation: Code เป็น Documentation
Terraform Core Concepts
1. Provider
Provider คือ Plugin ที่ใช้สื่อสารกับ Cloud Services
# AWS Provider
provider "aws" {
region = "ap-southeast-1"
profile = "default"
}
# Azure Provider
provider "azurerm" {
features {}
subscription_id = var.subscription_id
}
# Google Cloud Provider
provider "google" {
project = var.project_id
region = "asia-southeast1"
zone = "asia-southeast1-a"
}
# Multiple AWS Providers (Multi-Region)
provider "aws" {
alias = "us_east"
region = "us-east-1"
}
provider "aws" {
alias = "ap_southeast"
region = "ap-southeast-1"
}
2. Resources
Resource คือ Infrastructure Components ที่ต้องการสร้าง
# AWS EC2 Instance
resource "aws_instance" "web_server" {
ami = "ami-0c02fb55956c7d316" # Amazon Linux 2
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.web_sg.id]
subnet_id = aws_subnet.public.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>" > /var/www/html/index.html
EOF
tags = {
Name = "WebServer"
Environment = var.environment
Project = var.project_name
}
}
# AWS RDS Database
resource "aws_db_instance" "postgres" {
identifier = "${var.project_name}-postgres"
engine = "postgres"
engine_version = "13.7"
instance_class = "db.t3.micro"
allocated_storage = 20
max_allocated_storage = 100
storage_encrypted = true
db_name = var.database_name
username = var.database_username
password = var.database_password
vpc_security_group_ids = [aws_security_group.database_sg.id]
db_subnet_group_name = aws_db_subnet_group.main.name
backup_retention_period = 7
backup_window = "03:00-04:00"
maintenance_window = "sun:04:00-sun:05:00"
skip_final_snapshot = true
deletion_protection = false
tags = {
Name = "${var.project_name}-postgres"
}
}
3. Variables
Variables ทำให้ Configuration มีความยืดหยุ่น
# variables.tf
variable "environment" {
description = "Environment name (dev, staging, prod)"
type = string
default = "dev"
}
variable "project_name" {
description = "Name of the project"
type = string
validation {
condition = can(regex("^[a-z0-9-]+$", var.project_name))
error_message = "Project name must contain only lowercase letters, numbers, and hyphens."
}
}
variable "instance_types" {
description = "Map of instance types by environment"
type = map(string)
default = {
dev = "t3.micro"
staging = "t3.small"
prod = "t3.medium"
}
}
variable "database_config" {
description = "Database configuration"
type = object({
engine = string
engine_version = string
instance_class = string
allocated_storage = number
})
default = {
engine = "postgres"
engine_version = "13.7"
instance_class = "db.t3.micro"
allocated_storage = 20
}
}
variable "allowed_cidr_blocks" {
description = "List of CIDR blocks allowed to access resources"
type = list(string)
default = ["10.0.0.0/8"]
}
variable "tags" {
description = "Common tags for all resources"
type = map(string)
default = {
Terraform = "true"
Owner = "DevOps Team"
}
}
4. Outputs
Outputs ส่งออกข้อมูลที่สำคัญ
# outputs.tf
output "web_server_public_ip" {
description = "Public IP of the web server"
value = aws_instance.web_server.public_ip
}
output "web_server_public_dns" {
description = "Public DNS of the web server"
value = aws_instance.web_server.public_dns
}
output "database_endpoint" {
description = "Database endpoint"
value = aws_db_instance.postgres.endpoint
sensitive = true
}
output "load_balancer_dns" {
description = "Load balancer DNS name"
value = aws_lb.main.dns_name
}
output "vpc_id" {
description = "ID of the VPC"
value = aws_vpc.main.id
}
Real-World Example: Complete AWS Infrastructure
Project Structure
terraform/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── prod/
├── modules/
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── compute/
│ ├── database/
│ └── monitoring/
├── shared/
│ ├── s3-backend.tf
│ └── provider.tf
└── scripts/
├── deploy.sh
└── destroy.sh
Networking Module
# modules/networking/main.tf
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = merge(var.common_tags, {
Name = "${var.project_name}-vpc"
})
}
# Internet Gateway
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = merge(var.common_tags, {
Name = "${var.project_name}-igw"
})
}
# Public Subnets
resource "aws_subnet" "public" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 4, count.index)
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = merge(var.common_tags, {
Name = "${var.project_name}-public-${count.index + 1}"
Type = "Public"
})
}
# Private Subnets
resource "aws_subnet" "private" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 4, count.index + length(var.availability_zones))
availability_zone = var.availability_zones[count.index]
tags = merge(var.common_tags, {
Name = "${var.project_name}-private-${count.index + 1}"
Type = "Private"
})
}
# NAT Gateways
resource "aws_eip" "nat" {
count = length(var.availability_zones)
domain = "vpc"
depends_on = [aws_internet_gateway.main]
tags = merge(var.common_tags, {
Name = "${var.project_name}-nat-eip-${count.index + 1}"
})
}
resource "aws_nat_gateway" "main" {
count = length(var.availability_zones)
allocation_id = aws_eip.nat[count.index].id
subnet_id = aws_subnet.public[count.index].id
depends_on = [aws_internet_gateway.main]
tags = merge(var.common_tags, {
Name = "${var.project_name}-nat-${count.index + 1}"
})
}
# Route Tables
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = merge(var.common_tags, {
Name = "${var.project_name}-public-rt"
})
}
resource "aws_route_table" "private" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.main[count.index].id
}
tags = merge(var.common_tags, {
Name = "${var.project_name}-private-rt-${count.index + 1}"
})
}
# Route Table Associations
resource "aws_route_table_association" "public" {
count = length(aws_subnet.public)
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
resource "aws_route_table_association" "private" {
count = length(aws_subnet.private)
subnet_id = aws_subnet.private[count.index].id
route_table_id = aws_route_table.private[count.index].id
}
Compute Module
# modules/compute/main.tf
# Application Load Balancer
resource "aws_lb" "main" {
name = "${var.project_name}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = var.public_subnet_ids
enable_deletion_protection = var.enable_deletion_protection
tags = var.common_tags
}
# Target Group
resource "aws_lb_target_group" "main" {
name = "${var.project_name}-tg"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
health_check {
enabled = true
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 5
interval = 30
path = "/health"
matcher = "200"
port = "traffic-port"
protocol = "HTTP"
}
tags = var.common_tags
}
# ALB Listener
resource "aws_lb_listener" "main" {
load_balancer_arn = aws_lb.main.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.main.arn
}
}
# Launch Template
resource "aws_launch_template" "main" {
name_prefix = "${var.project_name}-"
image_id = var.ami_id
instance_type = var.instance_type
vpc_security_group_ids = [aws_security_group.web.id]
user_data = base64encode(templatefile("${path.module}/user_data.sh", {
project_name = var.project_name
database_url = var.database_url
}))
tag_specifications {
resource_type = "instance"
tags = merge(var.common_tags, {
Name = "${var.project_name}-instance"
})
}
lifecycle {
create_before_destroy = true
}
}
# Auto Scaling Group
resource "aws_autoscaling_group" "main" {
name = "${var.project_name}-asg"
vpc_zone_identifier = var.private_subnet_ids
target_group_arns = [aws_lb_target_group.main.arn]
health_check_type = "ELB"
health_check_grace_period = 300
min_size = var.min_size
max_size = var.max_size
desired_capacity = var.desired_capacity
launch_template {
id = aws_launch_template.main.id
version = "$Latest"
}
dynamic "tag" {
for_each = var.common_tags
content {
key = tag.key
value = tag.value
propagate_at_launch = true
}
}
tag {
key = "Name"
value = "${var.project_name}-asg-instance"
propagate_at_launch = true
}
}
# Auto Scaling Policies
resource "aws_autoscaling_policy" "scale_up" {
name = "${var.project_name}-scale-up"
scaling_adjustment = 1
adjustment_type = "ChangeInCapacity"
cooldown = 300
autoscaling_group_name = aws_autoscaling_group.main.name
}
resource "aws_autoscaling_policy" "scale_down" {
name = "${var.project_name}-scale-down"
scaling_adjustment = -1
adjustment_type = "ChangeInCapacity"
cooldown = 300
autoscaling_group_name = aws_autoscaling_group.main.name
}
# CloudWatch Alarms
resource "aws_cloudwatch_metric_alarm" "cpu_high" {
alarm_name = "${var.project_name}-cpu-high"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "2"
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = "300"
statistic = "Average"
threshold = "80"
alarm_description = "This metric monitors ec2 cpu utilization"
alarm_actions = [aws_autoscaling_policy.scale_up.arn]
dimensions = {
AutoScalingGroupName = aws_autoscaling_group.main.name
}
}
resource "aws_cloudwatch_metric_alarm" "cpu_low" {
alarm_name = "${var.project_name}-cpu-low"
comparison_operator = "LessThanThreshold"
evaluation_periods = "2"
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = "300"
statistic = "Average"
threshold = "20"
alarm_description = "This metric monitors ec2 cpu utilization"
alarm_actions = [aws_autoscaling_policy.scale_down.arn]
dimensions = {
AutoScalingGroupName = aws_autoscaling_group.main.name
}
}
State Management
Remote State with S3
# shared/s3-backend.tf
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "environments/dev/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
# S3 Bucket for State
resource "aws_s3_bucket" "terraform_state" {
bucket = "my-terraform-state-bucket"
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_encryption" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
resource "aws_s3_bucket_public_access_block" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# DynamoDB Table for State Locking
resource "aws_dynamodb_table" "terraform_state_lock" {
name = "terraform-state-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
tags = {
Name = "Terraform State Lock Table"
}
}
Workspace Management
# สร้าง Workspace สำหรับ environments ต่างๆ
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod
# เปลี่ยน Workspace
terraform workspace select dev
terraform workspace select prod
# ดู Workspace ปัจจุบัน
terraform workspace show
# ดู Workspace ทั้งหมด
terraform workspace list
Environment-Specific Configuration
# environments/dev/terraform.tfvars
project_name = "myapp-dev"
environment = "dev"
region = "ap-southeast-1"
vpc_cidr = "10.0.0.0/16"
availability_zones = ["ap-southeast-1a", "ap-southeast-1b"]
# Instance configuration
instance_type = "t3.micro"
min_size = 1
max_size = 2
desired_capacity = 1
# Database configuration
database_config = {
engine = "postgres"
engine_version = "13.7"
instance_class = "db.t3.micro"
allocated_storage = 20
}
# Security
allowed_cidr_blocks = ["0.0.0.0/0"] # Dev environment - open access
tags = {
Environment = "dev"
Project = "myapp"
Owner = "DevOps Team"
Terraform = "true"
}
# environments/prod/terraform.tfvars
project_name = "myapp-prod"
environment = "prod"
region = "ap-southeast-1"
vpc_cidr = "10.1.0.0/16"
availability_zones = ["ap-southeast-1a", "ap-southeast-1b", "ap-southeast-1c"]
# Instance configuration
instance_type = "t3.large"
min_size = 2
max_size = 10
desired_capacity = 3
# Database configuration
database_config = {
engine = "postgres"
engine_version = "13.7"
instance_class = "db.r5.large"
allocated_storage = 100
}
# Security - restrictive access
allowed_cidr_blocks = ["10.0.0.0/8", "172.16.0.0/12"]
tags = {
Environment = "prod"
Project = "myapp"
Owner = "DevOps Team"
Terraform = "true"
Backup = "daily"
}
Advanced Terraform Patterns
1. Data Sources
# ใช้ AMI ล่าสุดของ Amazon Linux
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# ใช้ Availability Zones ที่มีอยู่
data "aws_availability_zones" "available" {
state = "available"
}
# ใช้ Route53 Hosted Zone ที่มีอยู่
data "aws_route53_zone" "main" {
name = var.domain_name
private_zone = false
}
# การใช้งาน
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t3.micro"
availability_zone = data.aws_availability_zones.available.names[0]
}
2. Conditional Resources
# สร้าง NAT Gateway เฉพาะใน Production
resource "aws_nat_gateway" "main" {
count = var.environment == "prod" ? length(var.availability_zones) : 0
allocation_id = aws_eip.nat[count.index].id
subnet_id = aws_subnet.public[count.index].id
}
# สร้าง RDS Multi-AZ เฉพาะใน Production
resource "aws_db_instance" "postgres" {
# ... other configuration
multi_az = var.environment == "prod" ? true : false
backup_retention_period = var.environment == "prod" ? 7 : 1
deletion_protection = var.environment == "prod" ? true : false
}
3. For Each Loops
# สร้าง Security Groups หลายตัว
variable "security_groups" {
type = map(object({
description = string
ingress = list(object({
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))
}))
default = {
web = {
description = "Security group for web servers"
ingress = [
{
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
},
{
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
]
}
database = {
description = "Security group for database"
ingress = [
{
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"]
}
]
}
}
}
resource "aws_security_group" "main" {
for_each = var.security_groups
name = "${var.project_name}-${each.key}-sg"
description = each.value.description
vpc_id = aws_vpc.main.id
dynamic "ingress" {
for_each = each.value.ingress
content {
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(var.common_tags, {
Name = "${var.project_name}-${each.key}-sg"
})
}
4. Local Values
locals {
# Common tags
common_tags = merge(var.tags, {
Environment = var.environment
Project = var.project_name
ManagedBy = "Terraform"
CreatedAt = formatdate("YYYY-MM-DD", timestamp())
})
# Environment-specific configuration
instance_type = var.environment == "prod" ? "t3.large" : "t3.micro"
# Naming convention
name_prefix = "${var.project_name}-${var.environment}"
# CIDR calculations
public_subnets = [
for i in range(length(var.availability_zones)) :
cidrsubnet(var.vpc_cidr, 4, i)
]
private_subnets = [
for i in range(length(var.availability_zones)) :
cidrsubnet(var.vpc_cidr, 4, i + length(var.availability_zones))
]
}
CI/CD Integration
GitHub Actions
# .github/workflows/terraform.yml
name: Terraform
on:
push:
branches: [ main, develop ]
paths: [ 'terraform/**' ]
pull_request:
branches: [ main ]
paths: [ 'terraform/**' ]
env:
TF_VERSION: '1.6.0'
AWS_REGION: 'ap-southeast-1'
jobs:
terraform:
name: Terraform
runs-on: ubuntu-latest
strategy:
matrix:
environment: [dev, staging, prod]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Terraform Format Check
run: |
cd terraform/environments/${{ matrix.environment }}
terraform fmt -check -recursive
- name: Terraform Init
run: |
cd terraform/environments/${{ matrix.environment }}
terraform init
- name: Terraform Validate
run: |
cd terraform/environments/${{ matrix.environment }}
terraform validate
- name: Terraform Plan
run: |
cd terraform/environments/${{ matrix.environment }}
terraform plan -out=tfplan
- name: Terraform Apply (Auto-approve for dev)
if: github.ref == 'refs/heads/develop' && matrix.environment == 'dev'
run: |
cd terraform/environments/${{ matrix.environment }}
terraform apply -auto-approve tfplan
- name: Terraform Apply (Manual approval for prod)
if: github.ref == 'refs/heads/main' && matrix.environment == 'prod'
uses: hashicorp/terraform-github-actions/apply@v0.4.0
with:
tf_actions_working_dir: terraform/environments/${{ matrix.environment }}
tf_actions_comment: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Deployment Script
#!/bin/bash
# scripts/deploy.sh
set -e
ENVIRONMENT=${1:-dev}
ACTION=${2:-plan}
if [[ ! "$ENVIRONMENT" =~ ^(dev|staging|prod)$ ]]; then
echo "Error: Environment must be dev, staging, or prod"
exit 1
fi
if [[ ! "$ACTION" =~ ^(plan|apply|destroy)$ ]]; then
echo "Error: Action must be plan, apply, or destroy"
exit 1
fi
echo "🚀 Deploying to $ENVIRONMENT environment..."
cd "terraform/environments/$ENVIRONMENT"
# Initialize Terraform
echo "📦 Initializing Terraform..."
terraform init -upgrade
# Validate configuration
echo "✅ Validating configuration..."
terraform validate
# Format check
echo "🎨 Checking format..."
terraform fmt -check -recursive || {
echo "❌ Format check failed. Run 'terraform fmt -recursive' to fix."
exit 1
}
# Security scan (optional)
if command -v tfsec &> /dev/null; then
echo "🔒 Running security scan..."
tfsec .
fi
case $ACTION in
plan)
echo "📋 Creating execution plan..."
terraform plan -out=tfplan
;;
apply)
if [ ! -f tfplan ]; then
echo "❌ No plan file found. Run plan first."
exit 1
fi
if [ "$ENVIRONMENT" = "prod" ]; then
read -p "⚠️ Are you sure you want to apply to PRODUCTION? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "❌ Deployment cancelled."
exit 1
fi
fi
echo "🚀 Applying changes..."
terraform apply tfplan
echo "📊 Showing outputs..."
terraform output
;;
destroy)
read -p "⚠️ Are you sure you want to DESTROY $ENVIRONMENT environment? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "❌ Destroy cancelled."
exit 1
fi
echo "💥 Destroying infrastructure..."
terraform destroy -auto-approve
;;
esac
echo "✅ $ACTION completed successfully for $ENVIRONMENT environment!"
Best Practices
1. Security
# ใช้ AWS Secrets Manager สำหรับ sensitive data
resource "aws_secretsmanager_secret" "database_password" {
name = "${var.project_name}-${var.environment}-db-password"
description = "Database password for ${var.project_name}"
replica {
region = "us-west-2"
}
}
resource "aws_secretsmanager_secret_version" "database_password" {
secret_id = aws_secretsmanager_secret.database_password.id
secret_string = var.database_password
}
# ใช้ data source แทน hardcode
data "aws_secretsmanager_secret_version" "database_password" {
secret_id = aws_secretsmanager_secret.database_password.id
}
resource "aws_db_instance" "main" {
# ...
password = data.aws_secretsmanager_secret_version.database_password.secret_string
}
2. Resource Lifecycle Management
resource "aws_s3_bucket" "important_data" {
bucket = "${var.project_name}-important-data"
lifecycle {
prevent_destroy = true
ignore_changes = [
# Ignore changes to tags, e.g. because a management agent
# updates these based on some ruleset managed elsewhere.
tags,
]
}
}
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
lifecycle {
create_before_destroy = true
}
}
3. State File Management
# Backup state files
aws s3 sync s3://my-terraform-state-bucket s3://my-terraform-state-backup-bucket
# Import existing resources
terraform import aws_instance.web i-1234567890abcdef0
# Remove resources from state without destroying
terraform state rm aws_instance.old_instance
# Move resources in state
terraform state mv aws_instance.old aws_instance.new
# Show current state
terraform state list
terraform state show aws_instance.web
4. Monitoring และ Alerting
# CloudWatch Dashboard
resource "aws_cloudwatch_dashboard" "main" {
dashboard_name = "${var.project_name}-dashboard"
dashboard_body = jsonencode({
widgets = [
{
type = "metric"
x = 0
y = 0
width = 12
height = 6
properties = {
metrics = [
["AWS/ApplicationELB", "RequestCount", "LoadBalancer", aws_lb.main.arn_suffix],
["AWS/ApplicationELB", "TargetResponseTime", "LoadBalancer", aws_lb.main.arn_suffix],
["AWS/ApplicationELB", "HTTPCode_Target_2XX_Count", "LoadBalancer", aws_lb.main.arn_suffix]
]
period = 300
stat = "Sum"
region = var.aws_region
title = "Application Load Balancer Metrics"
}
}
]
})
}
# SNS Topic for Alerts
resource "aws_sns_topic" "alerts" {
name = "${var.project_name}-alerts"
}
resource "aws_sns_topic_subscription" "email" {
topic_arn = aws_sns_topic.alerts.arn
protocol = "email"
endpoint = var.alert_email
}
สรุป
Terraform เป็นเครื่องมือที่ทรงพลังสำหรับการจัดการ Infrastructure:
- Infrastructure as Code: ทำให้ Infrastructure มี Version Control และ Reproducible
- State Management: ใช้ Remote State และ State Locking เพื่อความปลอดภัย
- Modularity: แยก Code เป็น Modules เพื่อการใช้งานซ้ำ
- Environment Separation: แยก Environment ชัดเจนด้วย Workspace หรือ Directory
- CI/CD Integration: รวมเข้ากับ Pipeline สำหรับ Automation
- Security: ใช้ Secrets Management และ IAM Roles อย่างเหมาะสม
- Monitoring: ติดตาม State Changes และ Resource Usage
การใช้ Terraform อย่างถูกต้องจะช่วยให้เราจัดการ Infrastructure ได้อย่างมีประสิทธิภาพ ลดความผิดพลาด และเพิ่มความเร็วในการ Deploy!