
ในโลกของการพัฒนาซอฟต์แวร์และการจัดการโครงสร้างพื้นฐานยุคใหม่ การสร้างและดูแลสภาพแวดล้อมคลาวด์แบบ Manual เป็นเรื่องที่ทั้งเสียเวลา เกิดข้อผิดพลาดได้ง่าย และยังไม่สามารถขยายขนาดได้อย่างรวดเร็วครับ แต่ไม่ต้องกังวลไปครับ! วันนี้ SiamLancard.com จะพาคุณดำดิ่งสู่โลกของ Infrastructure as Code (IaC) ด้วยเครื่องมืออันทรงพลังอย่าง Terraform เพื่อพลิกโฉมการจัดการ Cloud AWS ของคุณให้เป็นไปโดยอัตโนมัติ มีประสิทธิภาพ และทำซ้ำได้ บทความนี้จะเจาะลึกทุกแง่มุมของการใช้ Terraform สำหรับ AWS ตั้งแต่พื้นฐานไปจนถึงเทคนิคขั้นสูง พร้อมตัวอย่างโค้ดที่ใช้งานได้จริง เพื่อให้คุณพร้อมนำไปปรับใช้ได้ทันทีครับ ถ้าคุณพร้อมแล้ว เรามาเริ่มต้นการเดินทางอันน่าตื่นเต้นนี้ด้วยกันเลยครับ!
สารบัญ
- บทนำ: ปลดล็อกศักยภาพ AWS ด้วย Terraform IaC (Infrastructure as Code) ครับ
- แก่นแท้ของ Terraform: ทำความเข้าใจหลักการทำงานครับ
- ติดตั้งและเริ่มต้นใช้งาน Terraform สำหรับ AWS ครับ
- เจาะลึกการสร้างโครงสร้างพื้นฐาน AWS ด้วย Terraform ครับ
- VPC (Virtual Private Cloud): หัวใจของเครือข่าย AWS
- EC2 (Elastic Compute Cloud): เซิร์ฟเวอร์ในคลาวด์
- S3 (Simple Storage Service): ที่เก็บข้อมูลอ็อบเจกต์
- RDS (Relational Database Service): ฐานข้อมูลที่จัดการได้
- IAM (Identity and Access Management): การจัดการสิทธิ์
- Load Balancers (ALB/NLB): การกระจายโหลด
- Auto Scaling Groups: ความยืดหยุ่นและความพร้อมใช้งาน
- คุณสมบัติขั้นสูงและแนวปฏิบัติที่ดีที่สุดของ Terraform ครับ
- Modules: การนำโค้ดกลับมาใช้ซ้ำ (Reusability)
- Workspaces: การจัดการสภาพแวดล้อม (Dev, Staging, Prod, UAT)
- Remote State: การทำงานร่วมกันเป็นทีม
- Data Sources: การดึงข้อมูลจากโครงสร้างพื้นฐานที่มีอยู่
- Terraform Backend: S3 เป็นที่เก็บ Remote State
- Terraform Cloud/Enterprise: ฟีเจอร์สำหรับองค์กร
- การจัดการ Secrets (Sensitive Data): AWS Secrets Manager, Parameter Store
- Testing Terraform Configurations: Terratest, InSpec
- Code Review และ Version Control: Git
- CI/CD Pipeline สำหรับ Terraform: Jenkins, GitLab CI, AWS CodePipeline
- เปรียบเทียบ Terraform กับเครื่องมือ IaC อื่นๆ ครับ
- ความท้าทายและข้อควรพิจารณาในการใช้ Terraform ครับ
- คำถามที่พบบ่อย (FAQ) เกี่ยวกับ Terraform บน AWS ครับ
- บทสรุปและก้าวต่อไปครับ
บทนำ: ปลดล็อกศักยภาพ AWS ด้วย Terraform IaC (Infrastructure as Code) ครับ
การจัดการโครงสร้างพื้นฐานบน Cloud AWS ในปัจจุบัน ไม่ใช่แค่การคลิกปุ่มในหน้า Console อีกต่อไปแล้วครับ การที่เราสามารถกำหนด สร้าง แก้ไข และลบโครงสร้างพื้นฐานผ่านโค้ดได้นั้น ได้กลายเป็นมาตรฐานทองคำสำหรับทีม DevOps และวิศวกรคลาวด์ไปแล้วครับ และในบรรดาเครื่องมือ Infrastructure as Code (IaC) ทั้งหมด Terraform ของ HashiCorp ก็โดดเด่นขึ้นมาในฐานะผู้นำ ด้วยความสามารถในการรองรับ Cloud Provider ที่หลากหลาย และความยืดหยุ่นในการทำงานครับ
ทำไม Infrastructure as Code (IaC) ถึงสำคัญในโลกคลาวด์ยุคใหม่?
ลองนึกภาพการตั้งค่าเซิร์ฟเวอร์, ฐานข้อมูล, เครือข่าย, และระบบรักษาความปลอดภัยสำหรับแอปพลิเคชันใหม่ทุกครั้งที่คุณต้องการสร้างสภาพแวดล้อมใหม่สิครับ มันทั้งใช้เวลานาน มีโอกาสผิดพลาดสูง และยากต่อการทำซ้ำให้เหมือนเดิมทุกครั้งใช่ไหมครับ IaC เข้ามาแก้ปัญหานี้ด้วยการแปลงโครงสร้างพื้นฐานของคุณให้เป็นโค้ด ทำให้เกิดประโยชน์มากมายดังนี้ครับ:
- ความสอดคล้อง (Consistency): สร้างสภาพแวดล้อมที่เหมือนกันทุกครั้ง ไม่ว่าจะเป็น Dev, Staging หรือ Production ลดปัญหา "It works on my machine!"
- ความรวดเร็ว (Speed): สามารถ Deploy โครงสร้างพื้นฐานขนาดใหญ่ได้อย่างรวดเร็วในไม่กี่นาที
- ลดข้อผิดพลาด (Reduced Errors): การใช้โค้ดช่วยลดข้อผิดพลาดที่เกิดจากมนุษย์ (human error)
- การทำซ้ำได้ (Repeatability): สามารถสร้างสภาพแวดล้อมเดียวกันซ้ำกี่ครั้งก็ได้
- การจัดการเวอร์ชัน (Version Control): โค้ดโครงสร้างพื้นฐานสามารถเก็บไว้ใน Git ทำให้ติดตามการเปลี่ยนแปลง ย้อนกลับเวอร์ชัน และทำงานร่วมกันเป็นทีมได้ง่ายขึ้น
- เอกสารประกอบ (Documentation): โค้ดนั้นทำหน้าที่เป็นเอกสารประกอบในตัว บอกว่าโครงสร้างพื้นฐานของเรามีอะไรบ้าง
Terraform คืออะไร? ทำไมต้อง Terraform?
Terraform คือเครื่องมือ Open-source IaC จาก HashiCorp ที่ช่วยให้คุณสามารถกำหนดและจัดเตรียมโครงสร้างพื้นฐานในสภาพแวดล้อมคลาวด์ใดๆ ก็ตาม (รวมถึง On-premises ด้วย) โดยใช้ภาษาที่เข้าใจง่ายที่เรียกว่า HashiCorp Configuration Language (HCL) ครับ
เหตุผลหลักที่ Terraform ได้รับความนิยมอย่างแพร่หลาย และเป็นตัวเลือกอันดับต้นๆ สำหรับการจัดการ AWS มีดังนี้ครับ:
- Cloud Agnostic: Terraform ไม่ได้จำกัดอยู่แค่ AWS เท่านั้นครับ แต่ยังรองรับ Cloud Provider ชั้นนำอื่นๆ เช่น Azure, Google Cloud Platform (GCP), Alibaba Cloud รวมถึง Kubernetes และ On-premises infrastructure อีกด้วย ทำให้คุณสามารถใช้เครื่องมือเดียวในการจัดการโครงสร้างพื้นฐานที่หลากหลายได้ครับ
- Declarative Syntax: คุณเพียงแค่บอก Terraform ว่าคุณต้องการโครงสร้างพื้นฐานแบบไหน โดยไม่ต้องระบุขั้นตอนการสร้าง (Imperative) Terraform จะจัดการส่วนที่เหลือเองครับ
- State Management: Terraform จะบันทึกสถานะปัจจุบันของโครงสร้างพื้นฐานของคุณไว้ในไฟล์ที่เรียกว่า State File ซึ่งใช้ในการเปรียบเทียบกับ Configuration ที่คุณเขียนไว้ ทำให้ Terraform ทราบว่าต้องเปลี่ยนแปลงอะไรบ้างเพื่อให้โครงสร้างพื้นฐานเป็นไปตามที่คุณต้องการครับ
- Execution Plan: ก่อนที่จะทำการเปลี่ยนแปลงใดๆ Terraform จะแสดง "Execution Plan" ให้คุณเห็นก่อนเสมอ ทำให้คุณสามารถตรวจสอบได้ว่าการเปลี่ยนแปลงที่จะเกิดขึ้นนั้นถูกต้องตามที่คุณคาดหวังหรือไม่ ช่วยป้องกันข้อผิดพลาดที่ไม่พึงประสงค์ครับ
- Modular Architecture: รองรับการสร้าง Modules เพื่อให้โค้ดสามารถนำกลับมาใช้ซ้ำได้ ทำให้การจัดการโปรเจกต์ขนาดใหญ่เป็นไปได้ง่ายขึ้นครับ
- Community & Ecosystem: มีชุมชนผู้ใช้งานขนาดใหญ่และมีทรัพยากรมากมายให้เรียนรู้และปรึกษาครับ
แก่นแท้ของ Terraform: ทำความเข้าใจหลักการทำงานครับ
ก่อนที่เราจะเริ่มลงมือเขียนโค้ด มาทำความเข้าใจหลักการสำคัญที่อยู่เบื้องหลัง Terraform กันก่อนนะครับ การเข้าใจสิ่งเหล่านี้จะช่วยให้คุณใช้งาน Terraform ได้อย่างมีประสิทธิภาพและแก้ปัญหาต่างๆ ได้อย่างถูกต้องครับ
Declarative Configuration Language (HCL)
หัวใจของ Terraform คือการใช้ภาษา HashiCorp Configuration Language (HCL) ซึ่งเป็นภาษาแบบ Declarative ครับ หมายความว่าคุณจะ "ประกาศ" หรือ "บอก" Terraform ว่าคุณต้องการให้โครงสร้างพื้นฐานของคุณ เป็นอย่างไร (Desired State) แทนที่จะบอกว่า ต้องทำอย่างไร (Imperative Steps) เพื่อให้ได้โครงสร้างนั้นมา
ตัวอย่างเช่น แทนที่จะเขียนสคริปต์ที่บอกว่า "ล็อกอินเข้า AWS console, คลิกสร้าง S3 bucket, ตั้งชื่อว่า…" คุณจะเขียนโค้ด HCL ที่ประกาศว่า "ฉันต้องการ S3 bucket ชื่อนี้" ครับ Terraform จะรับผิดชอบในการหาวิธีสร้างหรือแก้ไขให้เป็นไปตามที่คุณต้องการเองครับ
HCL มีไวยากรณ์ที่อ่านง่าย คล้าย JSON แต่มีความยืดหยุ่นและรองรับคุณสมบัติเฉพาะของ Terraform ได้ดีกว่าครับ
State Management
Terraform จะบันทึกสถานะปัจจุบันของโครงสร้างพื้นฐานที่คุณจัดการไว้ในไฟล์ที่เรียกว่า Terraform State File (ปกติคือ terraform.tfstate) ครับ ไฟล์นี้มีความสำคัญอย่างยิ่งเพราะมันคือ:
- Mapping ระหว่าง Configuration กับ Real Infrastructure: State File จะบันทึกว่า Resource ที่คุณประกาศไว้ใน HCL Configuration นั้น สอดคล้องกับ Resource ตัวไหนใน Cloud Provider จริงๆ ครับ
- บันทึก Attributes ของ Resource: มันจะเก็บข้อมูลและคุณสมบัติต่างๆ ของ Resource ที่ถูกสร้างขึ้น เช่น ID ของ S3 bucket, IP address ของ EC2 instance เป็นต้น
- ใช้ในการวางแผนการเปลี่ยนแปลง: เมื่อคุณรัน
terraform plan, Terraform จะเปรียบเทียบ Desired State (จาก Configuration files) กับ Current State (จาก State File) เพื่อกำหนดว่าต้องเปลี่ยนแปลงอะไรบ้างครับ
การจัดการ State File อย่างถูกต้องเป็นสิ่งสำคัญมากครับ เพราะหาก State File เสียหายหรือไม่ถูกต้อง Terraform อาจไม่สามารถจัดการโครงสร้างพื้นฐานของคุณได้อย่างถูกต้อง หรืออาจทำให้เกิดการเปลี่ยนแปลงที่ไม่พึงประสงค์ได้ครับ โดยเฉพาะอย่างยิ่งในการทำงานเป็นทีม การใช้ Remote State เป็นสิ่งจำเป็นครับ
Provider Model
Terraform มีความสามารถในการจัดการโครงสร้างพื้นฐานได้หลากหลาย ไม่ว่าจะเป็น AWS, Azure, GCP, Kubernetes, GitHub หรือแม้กระทั่ง Datadog ครับ สิ่งนี้เป็นไปได้ด้วยแนวคิดของ Providers ครับ
Provider คือปลั๊กอินที่ทำหน้าที่เป็นตัวกลางในการสื่อสารระหว่าง Terraform กับ API ของบริการต่างๆ ครับ เมื่อคุณระบุ provider "aws" ใน Configuration ของคุณ Terraform จะดาวน์โหลด AWS Provider มาใช้งาน ซึ่ง Provider นี้จะรู้ว่าจะต้องเรียก API ของ AWS อย่างไรเพื่อสร้างหรือจัดการ Resource ต่างๆ เช่น EC2, S3, RDS เป็นต้นครับ
แต่ละ Provider จะมีชุดของ Resource Types และ Data Sources ที่รองรับ ซึ่งคุณสามารถดูเอกสารประกอบของ Provider นั้นๆ เพื่อดูว่ามี Resource ใดให้ใช้งานได้บ้างครับ
Execution Plan: init, plan, apply, destroy
วงจรชีวิตพื้นฐานของการใช้งาน Terraform ประกอบด้วย 4 คำสั่งหลักๆ ดังนี้ครับ
terraform init:คำสั่งนี้ใช้สำหรับเริ่มต้นไดเรกทอรีการทำงานของ Terraform ครับ มันจะดาวน์โหลด Provider ที่จำเป็นทั้งหมดตามที่ระบุไว้ใน Configuration ของคุณ รวมถึงตั้งค่า Backend สำหรับ State Management ด้วยครับ คุณต้องรันคำสั่งนี้เสมอเมื่อเริ่มต้นโปรเจกต์ใหม่ หรือเมื่อมีการเพิ่ม/เปลี่ยนแปลง Provider หรือ Module ครับ
terraform plan:นี่คือคำสั่งที่สำคัญที่สุดคำสั่งหนึ่งครับ
terraform planจะวิเคราะห์ Configuration ของคุณ เปรียบเทียบกับ State File และสถานะปัจจุบันของโครงสร้างพื้นฐานใน Cloud AWS จริงๆ (ถ้ามี) จากนั้นจะสร้าง "Execution Plan" ขึ้นมา ซึ่งจะแสดงให้คุณเห็นอย่างละเอียดว่า Terraform จะทำอะไรบ้าง เช่น จะสร้าง (+), แก้ไข (~), หรือลบ (-) Resource ใดบ้างครับ การตรวจสอบ Plan อย่างละเอียดช่วยป้องกันการเปลี่ยนแปลงที่ไม่คาดคิดได้เป็นอย่างดีครับterraform apply:เมื่อคุณตรวจสอบ Execution Plan แล้วและพอใจกับสิ่งที่จะเกิดขึ้น ก็ถึงเวลาใช้คำสั่ง
terraform applyครับ คำสั่งนี้จะดำเนินการตามแผนที่ Terraform สร้างไว้จริง โดยจะเรียก API ของ AWS เพื่อสร้าง แก้ไข หรือลบ Resource ต่างๆ ตาม Configuration ของคุณครับ หลังจากที่ Terraform ทำงานเสร็จ มันจะอัปเดต State File ให้เป็นปัจจุบันครับterraform destroy:คำสั่งนี้ใช้สำหรับลบ Resource ทั้งหมดที่ถูกสร้างขึ้นโดย Configuration ของ Terraform ในไดเรกทอรีนั้นๆ ครับ ควรใช้ด้วยความระมัดระวังอย่างยิ่ง โดยเฉพาะในสภาพแวดล้อม Production เพราะมันจะลบทุกอย่างที่ Terraform รู้จักใน State File ออกไปครับ เช่นเดียวกับ
apply, คุณจะต้องยืนยันก่อนการดำเนินการครับ
ติดตั้งและเริ่มต้นใช้งาน Terraform สำหรับ AWS ครับ
ตอนนี้เรามาลงมือติดตั้ง Terraform และเตรียมพร้อมสำหรับการสร้างโครงสร้างพื้นฐานบน AWS ด้วยโค้ดกันเลยครับ
การติดตั้ง Terraform
Terraform เป็น Single Binary ครับ การติดตั้งจึงค่อนข้างง่าย คุณสามารถดาวน์โหลดได้จากเว็บไซต์ทางการของ HashiCorp
สำหรับ macOS (Homebrew):
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
สำหรับ Windows (Chocolatey):
choco install terraform
สำหรับ Linux (Debian/Ubuntu):
sudo apt update && sudo apt install -y gnupg software-properties-common curl
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt update
sudo apt install terraform
หลังจากติดตั้งเสร็จสิ้น ให้ลองตรวจสอบเวอร์ชันเพื่อยืนยันว่าติดตั้งสำเร็จครับ:
terraform --version
คุณควรจะเห็นผลลัพธ์ประมาณนี้ครับ:
Terraform v1.x.x
on linux_amd64
การกำหนดค่า AWS Provider
เพื่อให้ Terraform สามารถสื่อสารกับ AWS ได้ คุณจะต้องกำหนดค่า AWS Credentials และ Region ครับ มีหลายวิธีในการทำเช่นนี้:
- Environment Variables (แนะนำสำหรับ Local Development):
ตั้งค่า
AWS_ACCESS_KEY_IDและAWS_SECRET_ACCESS_KEYใน Environment Variables ของระบบครับexport AWS_ACCESS_KEY_ID="YOUR_AWS_ACCESS_KEY_ID" export AWS_SECRET_ACCESS_KEY="YOUR_AWS_SECRET_ACCESS_KEY" export AWS_DEFAULT_REGION="ap-southeast-1" # หรือ region ที่คุณต้องการข้อควรระวัง: อย่าเก็บ Access Key และ Secret Key ไว้ในโค้ด Terraform โดยตรงครับ!
- AWS Shared Credentials File:
ตั้งค่าในไฟล์
~/.aws/credentials(Linux/macOS) หรือ%USERPROFILE%\.aws\credentials(Windows) ครับ[default] aws_access_key_id = YOUR_AWS_ACCESS_KEY_ID aws_secret_access_key = YOUR_AWS_SECRET_ACCESS_KEYและอาจมีไฟล์
~/.aws/configสำหรับ Region:[default] region = ap-southeast-1 - IAM Roles for EC2 Instances (แนะนำสำหรับ Production):
หากคุณรัน Terraform บน EC2 instance คุณสามารถใช้ IAM Role ที่ผูกกับ Instance นั้นๆ ได้ครับ ซึ่งเป็นวิธีที่ปลอดภัยที่สุดในการให้สิทธิ์ Terraform ในการเข้าถึง AWS ครับ
นอกจากนี้ คุณต้องกำหนดค่า AWS Provider ในไฟล์ Terraform Configuration ของคุณด้วยครับ สร้างไฟล์ชื่อ main.tf:
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # กำหนดเวอร์ชันของ AWS Provider ที่ต้องการ
}
}
}
provider "aws" {
region = "ap-southeast-1" # กำหนด AWS Region ที่คุณต้องการสร้าง Resource
# หรือสามารถใช้ profile จาก ~/.aws/credentials ได้
# profile = "default"
}
หลังจากสร้างไฟล์นี้ ให้รัน terraform init ครับ เพื่อดาวน์โหลด AWS Provider มาใช้งาน
terraform init
คุณควรจะเห็นข้อความว่า Terraform ได้ Initialize Backend และดาวน์โหลด AWS Provider สำเร็จแล้วครับ
ตัวอย่างแรก: สร้าง S3 Bucket ด้วย Terraform
มาลองสร้าง Resource แรกของเรากันครับ นั่นคือ S3 Bucket ซึ่งเป็นบริการจัดเก็บข้อมูลอ็อบเจกต์ที่ได้รับความนิยมบน AWS ครับ
เพิ่มโค้ดต่อไปนี้ลงในไฟล์ main.tf หรือสร้างไฟล์ใหม่ชื่อ s3.tf ในไดเรกทอรีเดียวกันก็ได้ครับ:
# s3.tf หรือ main.tf
resource "aws_s3_bucket" "my_first_bucket" {
bucket = "siamlancard-my-unique-bucket-12345" # ต้องเป็นชื่อที่ไม่ซ้ำกันทั่วโลก
tags = {
Name = "SiamLancard First Bucket"
Environment = "Dev"
}
}
resource "aws_s3_bucket_acl" "my_first_bucket_acl" {
bucket = aws_s3_bucket.my_first_bucket.id
acl = "private"
}
resource "aws_s3_bucket_public_access_block" "my_first_bucket_public_access_block" {
bucket = aws_s3_bucket.my_first_bucket.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
output "s3_bucket_id" {
description = "The ID of the S3 bucket"
value = aws_s3_bucket.my_first_bucket.id
}
output "s3_bucket_arn" {
description = "The ARN of the S3 bucket"
value = aws_s3_bucket.my_first_bucket.arn
}
คำอธิบายโค้ด:
resource "aws_s3_bucket" "my_first_bucket": นี่คือการประกาศ Resource ครับaws_s3_bucketคือ Type ของ Resource (มาจาก AWS Provider) และmy_first_bucketคือชื่อเชิงตรรกะ (Local Name) ที่คุณตั้งขึ้นเพื่ออ้างอิงถึง Resource นี้ภายใน Terraform ครับbucket = "siamlancard-my-unique-bucket-12345": กำหนดชื่อ S3 Bucket ครับ ชื่อนี้ต้องไม่ซ้ำกันทั่วโลก (Global Unique) ครับtags = { ... }: เป็น Key-Value Pairs สำหรับใส่ Tag ให้กับ Resource เพื่อการจัดระเบียบและการจัดการต้นทุนครับaws_s3_bucket_aclและaws_s3_bucket_public_access_block: เป็น Resource เพิ่มเติมที่แนะนำให้ใช้เพื่อเพิ่มความปลอดภัยให้กับ S3 Bucket โดยการตั้งค่า ACL เป็น Private และ Block Public Access ทั้งหมดครับoutput "s3_bucket_id":outputคือค่าที่ Terraform จะแสดงให้เห็นเมื่อapplyสำเร็จครับ ใช้สำหรับส่งค่าจาก Resource ที่สร้างขึ้นไปใช้ต่อ หรือเพื่อดูข้อมูลสำคัญครับ
ขั้นตอนการ Deploy:
- Initialize Terraform (ถ้ายังไม่ได้ทำ):
terraform init - สร้าง Execution Plan:
terraform planTerraform จะแสดงให้คุณเห็นว่ากำลังจะสร้าง S3 Bucket 1 ตัว และ Resource อื่นๆ ที่เกี่ยวข้อง คุณจะเห็น
+หน้า Resource ที่จะถูกสร้างใหม่ครับ - Apply Configuration:
terraform applyTerraform จะขอให้คุณพิมพ์
yesเพื่อยืนยันการดำเนินการครับ เมื่อยืนยันแล้ว Terraform จะเริ่มสร้าง S3 Bucket บน AWS ครับ เมื่อเสร็จสิ้น คุณจะเห็น Output ที่เรากำหนดไว้ครับ
คุณสามารถเข้าไปตรวจสอบ S3 Bucket ที่สร้างขึ้นได้ใน AWS Console ของคุณครับ
การลบ Resource:
หากคุณต้องการลบ S3 Bucket ที่สร้างขึ้น ให้ใช้คำสั่ง:
terraform destroy
Terraform จะแสดง Execution Plan สำหรับการลบ (โดยมี - หน้า Resource) และขอให้คุณยืนยันด้วยการพิมพ์ yes ครับ
เจาะลึกการสร้างโครงสร้างพื้นฐาน AWS ด้วย Terraform ครับ
S3 Bucket เป็นแค่จุดเริ่มต้นครับ Terraform สามารถสร้างและจัดการ Resource AWS ได้เกือบทุกประเภท เรามาดูกันว่าเราจะใช้ Terraform เพื่อสร้างโครงสร้างพื้นฐานที่ซับซ้อนขึ้นได้อย่างไรบ้างครับ
VPC (Virtual Private Cloud): หัวใจของเครือข่าย AWS
VPC คือเครือข่ายเสมือนส่วนตัวของคุณบน AWS ซึ่งเป็นรากฐานสำคัญสำหรับโครงสร้างพื้นฐานทั้งหมดของคุณครับ การสร้าง VPC ด้วย Terraform ช่วยให้คุณสามารถกำหนดค่าเครือข่ายได้อย่างแม่นยำและทำซ้ำได้
# vpc.tf
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"
tags = {
Name = "siamlancard-main-vpc"
}
}
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.main.id
tags = {
Name = "siamlancard-igw"
}
}
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-southeast-1a" # เลือก AZ ที่เหมาะสม
map_public_ip_on_launch = true # EC2 ใน subnet นี้จะได้รับ Public IP
tags = {
Name = "siamlancard-public-subnet"
}
}
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw.id
}
tags = {
Name = "siamlancard-public-rt"
}
}
resource "aws_route_table_association" "public_rt_association" {
subnet_id = aws_subnet.public_subnet.id
route_table_id = aws_route_table.public_rt.id
}
output "vpc_id" {
description = "The ID of the main VPC"
value = aws_vpc.main.id
}
output "public_subnet_id" {
description = "The ID of the public subnet"
value = aws_subnet.public_subnet.id
}
คำอธิบาย:
aws_vpc: สร้าง VPC ด้วยช่วง IP (CIDR Block) ที่กำหนดaws_internet_gateway: สร้าง Internet Gateway เพื่อให้ VPC สามารถเชื่อมต่อกับอินเทอร์เน็ตได้aws_subnet: สร้าง Subnet ภายใน VPC กำหนด CIDR Block และ Availability Zone (AZ) ที่ต้องการmap_public_ip_on_launch = trueหมายความว่า EC2 Instance ที่รันใน Subnet นี้จะได้รับ Public IP โดยอัตโนมัติaws_route_table: สร้าง Route Table และกำหนด Route สำหรับการออกอินเทอร์เน็ต (0.0.0.0/0ไปยัง Internet Gateway)aws_route_table_association: เชื่อมโยง Subnet เข้ากับ Route Table
EC2 (Elastic Compute Cloud): เซิร์ฟเวอร์ในคลาวด์
EC2 คือบริการคอมพิวเตอร์เสมือนที่ปรับขนาดได้บน AWS ครับ
# ec2.tf
resource "aws_security_group" "web_sg" {
name = "siamlancard-web-sg"
description = "Allow HTTP and SSH inbound traffic"
vpc_id = aws_vpc.main.id # อ้างอิง VPC จาก resource aws_vpc.main
ingress {
description = "Allow SSH from anywhere"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "Allow HTTP from anywhere"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1" # -1 หมายถึง All Protocols
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "siamlancard-web-sg"
}
}
resource "aws_key_pair" "deployer_key" {
key_name = "siamlancard-deployer-key"
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3b...YOUR_PUBLIC_KEY... [email protected]" # ใส่ Public Key ของคุณ
}
resource "aws_instance" "web_server" {
ami = "ami-0eb30505191b4025a" # Ubuntu Server 22.04 LTS (HVM), SSD Volume Type, us-east-1 (ตรวจสอบ AMI ล่าสุดสำหรับ region ของคุณ)
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet.id # อ้างอิง public subnet
security_groups = [aws_security_group.web_sg.id]
key_name = aws_key_pair.deployer_key.key_name
user_data = <<-EOF
#!/bin/bash
sudo apt update -y
sudo apt install -y apache2
sudo systemctl start apache2
sudo systemctl enable apache2
echo "Hello from Terraform on SiamLancard!" > /var/www/html/index.html
EOF
tags = {
Name = "siamlancard-web-server"
}
}
output "web_server_public_ip" {
description = "Public IP of the web server"
value = aws_instance.web_server.public_ip
}
คำอธิบาย:
aws_security_group: สร้าง Security Group เพื่อควบคุมการเข้าออกของ Traffic กำหนดให้เปิด Port 22 (SSH) และ Port 80 (HTTP) จากทุกที่aws_key_pair: สร้าง Key Pair สำหรับ SSH เข้าสู่ Instance โดยใช้ Public Key ที่คุณเตรียมไว้aws_instance: สร้าง EC2 Instanceami: ระบุ Amazon Machine Image (AMI) ที่ต้องการ (เช่น Ubuntu Server)instance_type: กำหนดขนาดของ Instance (เช่นt2.micro)subnet_id: กำหนด Subnet ที่ Instance จะถูก Deploysecurity_groups: ผูก Instance กับ Security Group ที่สร้างไว้key_name: ผูก Instance กับ Key Pair ที่สร้างไว้user_data: เป็น Shell Script ที่จะรันเมื่อ Instance เริ่มต้นทำงานครั้งแรก ใช้สำหรับติดตั้ง Apache และสร้างไฟล์ index.html ง่ายๆ ครับ
ข้อควรระวัง: อย่าลืมเปลี่ยน
amiให้ตรงกับ Region ที่คุณใช้งาน และเปลี่ยนYOUR_PUBLIC_KEYด้วย Public Key ของคุณเองครับ และการเปิด SSH/HTTP จาก0.0.0.0/0ไม่แนะนำใน Production ควรจำกัด IP Source ให้เฉพาะเจาะจงครับ
S3 (Simple Storage Service): ที่เก็บข้อมูลอ็อบเจกต์
เราได้เห็นตัวอย่างพื้นฐานของ S3 ไปแล้วครับ คราวนี้มาดูคุณสมบัติขั้นสูงขึ้นบ้างครับ
# s3_advanced.tf
resource "aws_s3_bucket" "static_website" {
bucket = "siamlancard-static-website-example" # ชื่อ bucket ที่ไม่ซ้ำกัน
tags = {
Name = "SiamLancard Static Website"
}
}
resource "aws_s3_bucket_acl" "static_website_acl" {
bucket = aws_s3_bucket.static_website.id
acl = "public-read" # อนุญาตให้อ่านไฟล์ได้จากภายนอก สำหรับ Static Website
}
resource "aws_s3_bucket_website_configuration" "static_website_config" {
bucket = aws_s3_bucket.static_website.id
index_document {
suffix = "index.html"
}
error_document {
key = "error.html"
}
}
resource "aws_s3_bucket_policy" "static_website_policy" {
bucket = aws_s3_bucket.static_website.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Sid = "PublicReadGetObject",
Effect = "Allow",
Principal = "*",
Action = "s3:GetObject",
Resource = [
"${aws_s3_bucket.static_website.arn}/*",
],
},
],
})
}
output "website_endpoint" {
description = "The S3 static website endpoint"
value = aws_s3_bucket.static_website.website_endpoint
}
คำอธิบาย:
aws_s3_bucket_acl: กำหนด ACL เป็นpublic-readเพื่อให้ไฟล์ใน Bucket สามารถเข้าถึงได้ผ่านอินเทอร์เน็ตaws_s3_bucket_website_configuration: กำหนดให้ Bucket เป็น Static Website โดยระบุindex_documentและerror_documentaws_s3_bucket_policy: กำหนด Bucket Policy เพื่ออนุญาตให้ Public สามารถ GetObject จาก Bucket นี้ได้ Policy ถูกเขียนในรูปแบบ JSON และใช้ฟังก์ชันjsonencodeของ Terraform เพื่อแปลงเป็น String
หมายเหตุ: การเปิด Public Access ให้กับ S3 Bucket ควรทำด้วยความระมัดระวังและเฉพาะกรณีที่จำเป็นจริงๆ เช่น Static Website ครับ
RDS (Relational Database Service): ฐานข้อมูลที่จัดการได้
RDS ช่วยให้คุณสามารถรันฐานข้อมูล Relational ได้โดยไม่ต้องจัดการเซิร์ฟเวอร์ด้วยตัวเองครับ
# rds.tf
resource "aws_db_subnet_group" "db_subnet_group" {
name = "siamlancard-db-subnet-group"
subnet_ids = [aws_subnet.public_subnet.id] # ใน Production ควรใช้ Private Subnet
# ในตัวอย่างนี้ใช้ public_subnet เพื่อความง่ายในการสาธิต แต่ไม่แนะนำสำหรับ Production
tags = {
Name = "SiamLancard DB Subnet Group"
}
}
resource "aws_db_instance" "mysql_db" {
allocated_storage = 20
engine = "mysql"
engine_version = "8.0.32"
instance_class = "db.t3.micro"
name = "siamlancarddb"
username = "admin"
password = "MyStrongPassword123" # ไม่ควร Hardcode รหัสผ่านในโค้ด! ควรใช้ Secrets Manager
port = 3306
vpc_security_group_ids = [aws_security_group.web_sg.id] # กำหนด SG ที่มีสิทธิ์เข้าถึง DB
db_subnet_group_name = aws_db_subnet_group.db_subnet_group.name
skip_final_snapshot = true # ใน Production ควรเป็น false
publicly_accessible = true # ใน Production ควรเป็น false
identifier = "siamlancard-mysql-instance"
tags = {
Name = "SiamLancard MySQL DB"
}
}
output "rds_endpoint" {
description = "The endpoint of the RDS instance"
value = aws_db_instance.mysql_db.address
}
คำอธิบาย:
aws_db_subnet_group: สร้าง Subnet Group สำหรับ RDS ซึ่งจำเป็นสำหรับ Multi-AZ deployments ใน Production ควรใช้ Private Subnet เท่านั้นเพื่อความปลอดภัยaws_db_instance: สร้าง MySQL RDS Instanceallocated_storage: ขนาดพื้นที่เก็บข้อมูลengine,engine_version: ประเภทและเวอร์ชันของฐานข้อมูลinstance_class: ขนาด Instance ของฐานข้อมูลusername,password: ข้อมูลผู้ดูแลระบบ (ควรใช้ AWS Secrets Manager หรือ Parameter Store สำหรับรหัสผ่าน)vpc_security_group_ids: กำหนด Security Group ที่มีสิทธิ์เข้าถึงฐานข้อมูลskip_final_snapshot: หากเป็นtrueจะไม่สร้าง Snapshot สุดท้ายเมื่อลบ Instancepublicly_accessible: ใน Production ควรเป็นfalseเพื่อไม่ให้ฐานข้อมูลเข้าถึงได้จากอินเทอร์เน็ตโดยตรง
สำคัญมาก: รหัสผ่านและข้อมูลที่ละเอียดอ่อนอื่นๆ ไม่ควร Hardcode ลงใน Terraform Configuration โดยตรงครับ ควรใช้บริการจัดการ Secrets เช่น AWS Secrets Manager หรือ AWS Systems Manager Parameter Store เพื่อความปลอดภัยครับ อ่านเพิ่มเติมเกี่ยวกับการจัดการ Secrets
IAM (Identity and Access Management): การจัดการสิทธิ์
IAM ช่วยให้คุณจัดการผู้ใช้ กลุ่ม และสิทธิ์การเข้าถึง Resource ต่างๆ ใน AWS ได้อย่างปลอดภัยครับ
# iam.tf
resource "aws_iam_user" "siamlancard_admin" {
name = "siamlancard-admin-user"
tags = {
Department = "IT"
}
}
resource "aws_iam_policy" "s3_read_only_policy" {
name = "siamlancard-s3-read-only"
description = "Allows read-only access to S3 buckets"
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Action = [
"s3:Get*",
"s3:List*",
],
Effect = "Allow",
Resource = "*",
},
],
})
}
resource "aws_iam_user_policy_attachment" "attach_s3_read_only" {
user = aws_iam_user.siamlancard_admin.name
policy_arn = aws_iam_policy.s3_read_only_policy.arn
}
output "iam_user_name" {
description = "The name of the IAM user"
value = aws_iam_user.siamlancard_admin.name
}
output "s3_read_only_policy_arn" {
description = "The ARN of the S3 read-only policy"
value = aws_iam_policy.s3_read_only_policy.arn
}
คำอธิบาย:
aws_iam_user: สร้าง IAM Useraws_iam_policy: สร้าง IAM Policy แบบ Custom เพื่อให้สิทธิ์ในการอ่าน (Get, List) S3 Bucket ทั้งหมดaws_iam_user_policy_attachment: ผูก IAM Policy เข้ากับ IAM User
Best Practice: ควรใช้ IAM Roles มากกว่า IAM Users สำหรับแอปพลิเคชันหรือบริการต่างๆ ครับ และใช้ Principle of Least Privilege คือให้สิทธิ์เท่าที่จำเป็นเท่านั้นครับ
Load Balancers (ALB/NLB): การกระจายโหลด
Load Balancer ช่วยกระจาย Traffic ไปยัง EC2 Instances หลายๆ ตัวเพื่อเพิ่มความพร้อมใช้งานและความยืดหยุ่นครับ
# alb.tf
resource "aws_lb" "application_lb" {
name = "siamlancard-alb"
internal = false # External facing Load Balancer
load_balancer_type = "application"
security_groups = [aws_security_group.web_sg.id] # ใช้ SG เดียวกับ EC2 หรือสร้างใหม่
subnets = [aws_subnet.public_subnet.id] # ALB ต้องอยู่ใน Public Subnets
enable_deletion_protection = false # ใน Production ควรเป็น true
tags = {
Name = "SiamLancard ALB"
}
}
resource "aws_lb_target_group" "web_tg" {
name = "siamlancard-web-tg"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.main.id
health_check {
path = "/"
protocol = "HTTP"
matcher = "200"
interval = 30
timeout = 5
healthy_threshold = 2
unhealthy_threshold = 2
}
tags = {
Name = "SiamLancard Web TG"
}
}
resource "aws_lb_listener" "http_listener" {
load_balancer_arn = aws_lb.application_lb.arn
port = 80
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.web_tg.arn
}
}
resource "aws_lb_target_group_attachment" "web_target_attachment" {
target_group_arn = aws_lb_target_group.web_tg.arn
target_id = aws_instance.web_server.id # ผูก EC2 Instance เข้ากับ Target Group
port = 80
}
output "alb_dns_name" {
description = "The DNS name of the Application Load Balancer"
value = aws_lb.application_lb.dns_name
}
คำอธิบาย:
aws_lb: สร้าง Application Load Balancer (ALB)aws_lb_target_group: สร้าง Target Group ที่จะรับ Traffic จาก ALB และส่งไปยัง Target (เช่น EC2 Instance) พร้อมกำหนด Health Checkaws_lb_listener: สร้าง Listener สำหรับ ALB กำหนด Port และ Protocol ที่จะรับ Traffic และ Action ที่จะทำ (เช่น Forward ไปยัง Target Group)aws_lb_target_group_attachment: ผูก EC2 Instance เข้ากับ Target Group
Auto Scaling Groups: ความยืดหยุ่นและความพร้อมใช้งาน
Auto Scaling Groups (ASG) ช่วยให้แอปพลิเคชันของคุณปรับขนาดขึ้นหรือลงได้โดยอัตโนมัติตาม Traffic และความต้องการครับ
# asg.tf
resource "aws_launch_template" "web_lt" {
name_prefix = "siamlancard-web-lt"
image_id = "ami-0eb30505191b4025a" # Ubuntu Server 22.04 LTS (HVM), SSD Volume Type, us-east-1
instance_type = "t2.micro"
key_name = aws_key_pair.deployer_key.key_name
vpc_security_group_ids = [aws_security_group.web_sg.id]
user_data = base64encode(aws_instance.web_server.user_data) # ใช้ user_data เดียวกับ EC2
tag_specifications {
resource_type = "instance"
tags = {
Name = "siamlancard-asg-instance"
}
}
}
resource "aws_autoscaling_group" "web_asg" {
name = "siamlancard-web-asg"
vpc_zone_identifier = [aws_subnet.public_subnet.id]
desired_capacity = 1
max_size = 2
min_size = 1
health_check_type = "ELB"
health_check_grace_period = 300
target_group_arns = [aws_lb_target_group.web_tg.arn]
launch_template {
id = aws_launch_template.web_lt.id
version = "$Latest"
}
tag {
key = "Name"
value = "siamlancard-asg-instance"
propagate_at_launch = true
}
}
resource "aws_autoscaling_policy" "cpu_scaling_up" {
name = "siamlancard-cpu-scaling-up"
scaling_adjustment = 1
cooldown = 300
adjustment_type = "ChangeInCapacity"
autoscaling_group_name = aws_autoscaling_group.web_asg.name
}
resource "aws_cloudwatch_metric_alarm" "cpu_high_alarm" {
alarm_name = "siamlancard-cpu-high-alarm"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 2
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = 60
statistic = "Average"
threshold = 70
alarm_description = "This alarm monitors EC2 CPU utilization"
actions_enabled = true
alarm_actions = [aws_autoscaling_policy.cpu_scaling_up.arn]
dimensions = {
AutoScalingGroupName = aws_autoscaling_group.web_asg.name
}
}
คำอธิบาย:
aws_launch_template: เป็น Blueprint สำหรับการสร้าง EC2 Instance ครับ คล้ายกับ Launch Configuration แต่มีความยืดหยุ่นมากกว่าaws_autoscaling_group: สร้าง Auto Scaling Groupvpc_zone_identifier: กำหนด Subnet ที่ ASG จะ Deploy Instancedesired_capacity,max_size,min_size: กำหนดจำนวน Instance ที่ต้องการ, สูงสุด, และต่ำสุดhealth_check_type: ตั้งค่า Health Check โดยใช้ ELB (Load Balancer)target_group_arns: ผูก ASG เข้ากับ Target Group ของ ALBlaunch_template: อ้างอิง Launch Template ที่สร้างไว้
aws_autoscaling_policy: สร้าง Scaling Policy สำหรับการเพิ่มจำนวน Instanceaws_cloudwatch_metric_alarm: สร้าง CloudWatch Alarm เพื่อตรวจสอบ CPU Utilization หากเกิน Threshold ที่กำหนด จะ Trigger Scaling Policy ให้เพิ่ม Instance ครับ
คุณสมบัติขั้นสูงและแนวปฏิบัติที่ดีที่สุดของ Terraform ครับ
เมื่อโปรเจกต์ของคุณเติบโตขึ้น การใช้คุณสมบัติขั้นสูงของ Terraform และการปฏิบัติตาม Best Practices จะช่วยให้การจัดการโครงสร้างพื้นฐานของคุณมีประสิทธิภาพและยั่งยืนยิ่งขึ้นครับ
Modules: การนำโค้ดกลับมาใช้ซ้ำ (Reusability)
Modules คือวิธีการจัดระเบียบและห่อหุ้ม Terraform Configuration เป็นหน่วยที่นำกลับมาใช้ซ้ำได้ครับ ลองนึกภาพว่าคุณต้องการสร้าง VPC สำหรับหลายๆ สภาพแวดล้อม (Dev, Staging, Prod) แทนที่จะคัดลอกโค้ด VPC ทั้งหมด คุณสามารถสร้าง VPC Module ขึ้นมาหนึ่งครั้ง แล้วเรียกใช้ซ้ำได้หลายๆ ครั้งครับ
โครงสร้าง Module:
├── my-project/
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ └── modules/
│ └── vpc/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
ตัวอย่าง modules/vpc/main.tf:
# modules/vpc/main.tf
resource "aws_vpc" "this" {
cidr_block = var.vpc_cidr_block
tags = var.tags
}
resource "aws_internet_gateway" "this" {
vpc_id = aws_vpc.this.id
tags = var.tags
}
# ... เพิ่ม subnet, route table และอื่นๆ ที่เกี่ยวข้องกับ VPC ...
ตัวอย่าง modules/vpc/variables.tf:
# modules/vpc/variables.tf
variable "vpc_cidr_block" {
description = "CIDR block for the VPC"
type = string
}
variable "tags" {
description = "A map of tags to assign to the VPC and its resources"
type = map(string)
default = {}
}
ตัวอย่าง modules/vpc/outputs.tf:
# modules/vpc/outputs.tf
output "vpc_id" {
description = "The ID of the VPC"
value = aws_vpc.this.id
}
output "igw_id" {
description = "The ID of the Internet Gateway"
value = aws_internet_gateway.this.id
}
การเรียกใช้ Module ใน main.tf:
# main.tf
module "dev_vpc" {
source = "./modules/vpc" # อ้างอิงจาก Path ของ Module
vpc_cidr_block = "10.10.0.0/16"
tags = {
Environment = "Dev"
Project = "SiamLancardApp"
}
}
module "prod_vpc" {
source = "./modules/vpc"
vpc_cidr_block = "10.20.0.0/16"
tags = {
Environment = "Prod"
Project = "SiamLancardApp"
}
}
output "dev_vpc_id" {
value = module.dev_vpc.vpc_id
}
output "prod_vpc_id" {
value = module.prod_vpc.vpc_id
}
การใช้ Module ช่วยลดความซ้ำซ้อนของโค้ด ทำให้โค้ดอ่านง่ายขึ้น และง่ายต่อการบำรุงรักษาครับ อ่านเพิ่มเติมเกี่ยวกับ Terraform Modules
Workspaces: การจัดการสภาพแวดล้อม (Dev, Staging, Prod, UAT)
Terraform Workspaces ช่วยให้คุณสามารถจัดการ State File แยกกันสำหรับสภาพแวดล้อมที่แตกต่างกันได้โดยใช้ Configuration เดียวกันครับ เหมาะสำหรับการแยก Dev, Staging, Production หรือ UAT ครับ
การสร้างและสลับ Workspace:
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod
terraform workspace select dev # สลับไปใช้ workspace dev
terraform workspace show # ดูว่ากำลังอยู่ใน workspace ไหน
terraform workspace list # ดู workspace ทั้งหมดที่มี
การใช้ Workspace ใน Configuration:
คุณสามารถอ้างอิงชื่อ Workspace ได้ด้วย terraform.workspace ครับ
resource "aws_s3_bucket" "my_bucket" {
bucket = "siamlancard-${terraform.workspace}-bucket-example"
tags = {
Environment = terraform.workspace
}
}
เมื่อคุณรัน terraform apply ใน Workspace dev ก็จะได้ S3 Bucket ชื่อ siamlancard-dev-bucket-example และถ้าสลับไป Workspace prod ก็จะได้ siamlancard-prod-bucket-example ครับ
Remote State: การทำงานร่วมกันเป็นทีม
State File (terraform.tfstate) มีข้อมูลที่ละเอียดอ่อนและสำคัญมากครับ การเก็บ State File ไว้บนเครื่อง Local (Local State) ไม่เหมาะสมกับการทำงานเป็นทีม เพราะอาจเกิดปัญหาเช่น State File ล้าสมัย, ข้อมูลละเอียดอ่อนรั่วไหล หรือการชนกันของ State File ครับ
Remote State คือการเก็บ State File ไว้ในบริการจัดเก็บข้อมูลที่ปลอดภัยและเข้าถึงได้จากส่วนกลาง เช่น AWS S3 ครับ เมื่อใช้ Remote State จะมีประโยชน์ดังนี้ครับ:
- การทำงานร่วมกัน: สมาชิกในทีมทุกคนใช้ State File เดียวกัน
- ความปลอดภัย: สามารถเข้ารหัส (encryption) State File และควบคุมการเข้าถึงได้
- การล็อก (State Locking): ป้องกันไม่ให้หลายคนพยายามแก้ไขโครงสร้างพื้นฐานพร้อมกัน ซึ่งอาจทำให้ State File เสียหายได้
คุณสามารถกำหนด Backend สำหรับ Remote State ใน main.tf ได้ครับ:
# main.tf (ใน terraform block)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "siamlancard-terraform-state-bucket" # Bucket ที่จะเก็บ State File
key = "siamlancard-app/terraform.tfstate" # Path ภายใน bucket
region = "ap-southeast-1"
encrypt = true # เข้ารหัส State File
dynamodb_table = "siamlancard-terraform-lock" # ใช้ DynamoDB สำหรับ State Locking
}
}
คุณจะต้องสร้าง S3 Bucket และ DynamoDB Table สำหรับ State Locking ด้วยตัวเองก่อนนะครับ
เมื่อกำหนด Backend แล้ว ให้รัน terraform init เพื่อย้าย Local State ไปยัง Remote State (หรือเริ่มต้นใช้งาน Remote State) ครับ
Data Sources: การดึงข้อมูลจากโครงสร้างพื้นฐานที่มีอยู่
บางครั้งคุณอาจต้องการอ้างอิงถึง Resource ที่ไม่ได้ถูกสร้างด้วย Terraform ใน Configuration ปัจจุบัน หรือถูกสร้างโดย Terraform ใน Configuration อื่นครับ Data Sources ช่วยให้คุณสามารถ "อ่าน" ข้อมูลจาก Resource ที่มีอยู่แล้วใน Cloud Provider ได้ครับ
ตัวอย่าง: ดึงข้อมูล AMI ID ล่าสุดของ Ubuntu
# data_source_example.tf
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical's AWS account ID for Ubuntu
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
resource "aws_instance" "web_server_with_latest_ami" {
ami = data.aws_ami.ubuntu.id # ใช้ AMI ID ที่ได้จาก Data Source
instance_type = "t2.micro"
# ... (ส่วนอื่นๆ เหมือนเดิม)
}
output "latest_ubuntu_ami_id" {
description = "The ID of the most recent Ubuntu 22.04 AMI"
value = data.aws_ami.ubuntu.id
}
การใช้ Data Sources ช่วยให้ Configuration ของคุณมีความยืดหยุ่นและไม่ยึดติดกับค่าคงที่ที่อาจเปลี่ยนแปลงได้ครับ
Terraform Backend: S3 เป็นที่เก็บ Remote State
อย่างที่กล่าวไปในส่วนของ Remote State, S3 เป็น Backend ยอดนิยมสำหรับการเก็บ Terraform State File ครับ
ขั้นตอนการตั้งค่า S3 Backend:
- สร้าง S3 Bucket:
สร้าง S3 Bucket ที่จะใช้เก็บ State File และควรเปิด Versioning ให้กับ Bucket นี้เพื่อป้องกันการสูญหายของ State File ครับ
resource "aws_s3_bucket" "terraform_state_bucket" {
bucket = "siamlancard-tf-state-bucket-unique" # ชื่อ bucket