
ในยุคดิจิทัลที่ธุรกิจต่างพึ่งพาโครงสร้างพื้นฐานคลาวด์อย่าง AWS การจัดการทรัพยากรเหล่านี้ให้มีประสิทธิภาพ ความสอดคล้องกัน และความปลอดภัย จึงเป็นสิ่งสำคัญที่ไม่ควรมองข้ามครับ หากคุณกำลังเผชิญกับความท้าทายในการจัดการ AWS infrastructure ด้วยวิธีแบบ manual ที่กินเวลา เสี่ยงต่อความผิดพลาด และยากต่อการ Scale Up หรือ Scale Out วันนี้ SiamLancard.com ขอชวนคุณมาทำความรู้จักกับ Terraform Infrastructure as Code (IaC) เครื่องมือทรงพลังที่จะปฏิวัติวิธีการบริหารจัดการคลาวด์ของคุณบน AWS ให้กลายเป็นเรื่องง่าย มีระเบียบ และสามารถทำซ้ำได้ บทความนี้จะเจาะลึกตั้งแต่พื้นฐานไปจนถึงการใช้งานจริง พร้อมตัวอย่างโค้ดที่สามารถนำไปปรับใช้ได้ทันที เพื่อให้คุณพร้อมก้าวสู่โลกของการจัดการโครงสร้างพื้นฐานคลาวด์ยุคใหม่ได้อย่างมั่นใจครับ
- ทำไมต้อง Infrastructure as Code (IaC) และ Terraform?
- รู้จักกับ Terraform: พื้นฐานและการทำงาน
- เตรียมความพร้อมสำหรับ Terraform บน AWS
- ลงมือสร้าง Infrastructure บน AWS ด้วย Terraform (ตัวอย่างการใช้งานจริง)
- คุณสมบัติขั้นสูงและแนวทางปฏิบัติที่ดีที่สุด (Best Practices)
- Terraform Modules: การนำโค้ดกลับมาใช้ซ้ำ
- Terraform State Management: หัวใจสำคัญของ Terraform
- Terraform Workspaces: การจัดการสภาพแวดล้อมที่แตกต่างกัน
- Terraform Variables และ Outputs: เพิ่มความยืดหยุ่นและข้อมูลที่จำเป็น
- Terraform Data Sources: การอ้างอิงทรัพยากรที่มีอยู่แล้ว
- การทดสอบ (Testing) Terraform Configuration
- CI/CD Pipeline สำหรับ Terraform: การทำงานอัตโนมัติ
- ความปลอดภัย (Security) ใน Terraform: แนวทางปฏิบัติที่ดีที่สุด
- เปรียบเทียบ Terraform กับเครื่องมือ IaC อื่นๆ
- คำถามที่พบบ่อย (FAQ)
- สรุปและ Call-to-Action
ทำไมต้อง Infrastructure as Code (IaC) และ Terraform?
ในโลกของการพัฒนาซอฟต์แวร์ที่เปลี่ยนแปลงอย่างรวดเร็ว ความสามารถในการปรับเปลี่ยนและ Scale โครงสร้างพื้นฐานให้ทันต่อความต้องการทางธุรกิจเป็นสิ่งจำเป็นครับ การจัดการทรัพยากรคลาวด์แบบดั้งเดิมมักนำมาซึ่งความท้าทายหลายประการ ซึ่ง IaC และ Terraform เข้ามาตอบโจทย์ได้อย่างลงตัว
ปัญหาของการจัดการโครงสร้างพื้นฐานแบบดั้งเดิม
- การกำหนดค่าด้วยตนเอง (Manual Configuration): การเข้าสู่ AWS Console เพื่อสร้างหรือปรับเปลี่ยนทรัพยากรทีละชิ้นนั้นใช้เวลานาน เสี่ยงต่อความผิดพลาด และไม่สามารถทำซ้ำได้อย่างแม่นยำทุกครั้งครับ
- ความแตกต่างของการกำหนดค่า (Configuration Drift): เมื่อเวลาผ่านไป สภาพแวดล้อม Dev, Staging และ Production อาจมี Configuration ที่แตกต่างกัน ทำให้เกิดปัญหา “มันทำงานได้ในเครื่องของฉันนะ!”
- การปรับใช้ที่ล่าช้า (Slow Deployment): การเตรียมโครงสร้างพื้นฐานสำหรับแอปพลิเคชันใหม่หรือการ Scale Up อาจใช้เวลาหลายวันหรือหลายสัปดาห์ ทำให้กระบวนการพัฒนาช้าลง
- ความผิดพลาดของมนุษย์ (Human Error): การกำหนดค่าด้วยตนเองย่อมมีความเสี่ยงที่จะเกิดข้อผิดพลาด ซึ่งอาจนำไปสู่ปัญหาด้านประสิทธิภาพ ความปลอดภัย หรือแม้แต่การหยุดชะงักของบริการครับ
- การขาดการควบคุมเวอร์ชัน (Lack of Version Control): ไม่มีการบันทึกประวัติการเปลี่ยนแปลงของโครงสร้างพื้นฐาน ทำให้ยากต่อการติดตาม แก้ไข หรือย้อนกลับไปยังสถานะก่อนหน้า
แนวคิดของ Infrastructure as Code (IaC)
Infrastructure as Code คือแนวทางปฏิบัติที่ใช้โค้ดและเครื่องมือในการจัดการและจัดเตรียมโครงสร้างพื้นฐานแทนการกำหนดค่าด้วยตนเองครับ โดยมีหลักการสำคัญคือ:
- ความสอดคล้องและทำซ้ำได้ (Consistency & Repeatability): โค้ด IaC สามารถนำไปใช้สร้างสภาพแวดล้อมที่เหมือนกันได้ทุกครั้ง ไม่ว่าจะเป็น Dev, Staging หรือ Production
- ความเร็วและความคล่องตัว (Speed & Agility): การจัดเตรียมโครงสร้างพื้นฐานทำได้รวดเร็วและเป็นอัตโนมัติ ช่วยให้ทีมพัฒนาสามารถทดลองและปรับใช้แอปพลิเคชันได้ไวขึ้น
- ความน่าเชื่อถือ (Reliability): ลดข้อผิดพลาดที่เกิดจากมนุษย์ ทำให้โครงสร้างพื้นฐานมีความเสถียรมากขึ้น
- การควบคุมเวอร์ชัน (Version Control): โค้ด IaC สามารถจัดเก็บในระบบ Version Control เช่น Git ทำให้สามารถติดตามการเปลี่ยนแปลง ย้อนกลับเวอร์ชัน และทำงานร่วมกันได้ง่ายขึ้น
- เอกสารประกอบในตัว (Self-documenting): โค้ดเองทำหน้าที่เป็นเอกสารประกอบที่บอกว่าโครงสร้างพื้นฐานของเรามีอะไรบ้าง และทำงานอย่างไรครับ
- การทำงานร่วมกัน (Collaboration): ทีมหลายคนสามารถทำงานบนโครงสร้างพื้นฐานเดียวกันได้ โดยใช้เครื่องมือ Version Control
ทำไม Terraform ถึงโดดเด่น?
ในบรรดาเครื่องมือ IaC ที่มีอยู่มากมาย Terraform ของ HashiCorp ได้รับความนิยมอย่างสูงด้วยเหตุผลหลายประการครับ:
- รองรับหลายคลาวด์ (Multi-cloud): Terraform ไม่ได้จำกัดอยู่แค่ AWS เท่านั้น แต่ยังรองรับ Cloud Providers ชั้นนำอื่นๆ เช่น Azure, Google Cloud, VMware, OpenStack และอีกมากมาย ทำให้คุณสามารถใช้เครื่องมือเดียวจัดการโครงสร้างพื้นฐานข้ามคลาวด์ได้
- เป็น Open-source: การเป็น Open-source ทำให้มีชุมชนผู้ใช้งานและนักพัฒนาขนาดใหญ่ที่ช่วยกันปรับปรุง แก้ไขบั๊ก และสร้าง Modules ใหม่ๆ
- การกำหนดค่าแบบประกาศ (Declarative Configuration): แทนที่จะบอกว่า “ทำ A แล้วไป B แล้วไป C” (Imperative) Terraform จะบอกว่า “ฉันต้องการให้โครงสร้างพื้นฐานของฉันมีลักษณะเป็นแบบนี้” (Declarative) Terraform จะคำนวณและดำเนินการที่จำเป็นเพื่อให้ได้สถานะที่ต้องการเองครับ
- ภาษา HCL (HashiCorp Configuration Language): เป็นภาษาที่อ่านง่าย เข้าใจง่าย และออกแบบมาเพื่อการจัดการ Infrastructure โดยเฉพาะ
- จัดการทรัพยากรได้หลากหลาย: ไม่เพียงแค่ Cloud Resources แต่ยังสามารถจัดการ Software as a Service (SaaS), Platform as a Service (PaaS) หรือแม้แต่ On-premise Infrastructure ได้ด้วย Providers ที่มีให้เลือกมากมาย
ด้วยคุณสมบัติเหล่านี้ Terraform จึงเป็นตัวเลือกที่ยอดเยี่ยมสำหรับการนำ IaC มาใช้ในองค์กรของคุณ โดยเฉพาะอย่างยิ่งบน AWS ครับ
รู้จักกับ Terraform: พื้นฐานและการทำงาน
ก่อนที่เราจะไปลงมือเขียนโค้ด มาทำความเข้าใจหลักการและส่วนประกอบพื้นฐานของ Terraform กันก่อนครับ เพื่อให้เราสามารถใช้งานเครื่องมือนี้ได้อย่างมีประสิทธิภาพ
Terraform คืออะไร?
Terraform คือเครื่องมือ Infrastructure as Code (IaC) ที่พัฒนาโดย HashiCorp ใช้สำหรับสร้าง เปลี่ยนแปลง และจัดการโครงสร้างพื้นฐานได้อย่างปลอดภัยและมีประสิทธิภาพ โดยใช้ภาษา HashiCorp Configuration Language (HCL) ที่เป็นมิตรกับผู้ใช้งาน คุณสมบัติเด่นคือความสามารถในการจัดการทรัพยากรได้ทั้งบน Public Cloud, Private Cloud และ On-premise ผ่านระบบ “Providers” ครับ
หลักการทำงานของ Terraform
Terraform ทำงานโดยการอ่าน Configuration Files ที่เราเขียนขึ้น ซึ่งไฟล์เหล่านี้จะอธิบายถึงสถานะที่เราต้องการให้โครงสร้างพื้นฐานของเราเป็น (Desired State) จากนั้น Terraform จะเปรียบเทียบ Desired State นี้กับสถานะปัจจุบันของโครงสร้างพื้นฐานจริง (Current State) ที่บันทึกไว้ใน Terraform State File เพื่อกำหนดว่าต้องดำเนินการอะไรบ้างเพื่อให้โครงสร้างพื้นฐานไปถึง Desired State นั้นครับ
องค์ประกอบสำคัญในการทำงานของ Terraform ประกอบด้วย:
- Providers: เปรียบเสมือนปลั๊กอินที่เชื่อมต่อ Terraform เข้ากับ API ของ Cloud Providers หรือบริการต่างๆ เช่น
aws,azurerm,google,kubernetesเป็นต้น Providers เหล่านี้มีหน้าที่ในการเข้าใจและแปลงคำสั่ง HCL ให้เป็นการเรียกใช้ API ของบริการนั้นๆ ครับ - Resources: คือบล็อกโค้ดหลักที่ใช้ในการกำหนดทรัพยากรที่คุณต้องการสร้างหรือจัดการ เช่น
aws_instance(EC2),aws_vpc(Virtual Private Cloud),aws_s3_bucket(S3 Bucket) แต่ละ Resource จะมี Argument ของตัวเองที่ใช้กำหนดคุณสมบัติของทรัพยากรนั้นๆ ครับ - Data Sources: ใช้สำหรับอ้างอิงถึงทรัพยากรที่มีอยู่แล้วใน Cloud Provider โดยที่ Terraform ไม่ได้เป็นคนสร้างขึ้นมาเอง เช่น การอ้างอิงถึง AMI ID ล่าสุด หรือ VPC ID ที่สร้างด้วยมือ เป็นต้น
- Modules: เป็นกลุ่มของ Configuration Files ที่นำมารวมกันเป็นชุด เพื่อให้สามารถนำกลับมาใช้ซ้ำได้ (Reusable) ช่วยในการจัดระเบียบโค้ดและลดความซับซ้อนครับ
- State File: คือไฟล์ที่ Terraform ใช้บันทึกสถานะปัจจุบันของโครงสร้างพื้นฐานที่ถูกจัดการโดย Terraform ของคุณ เป็นไฟล์สำคัญที่ต้องได้รับการดูแลอย่างดี เพราะมันเป็นสะพานเชื่อมระหว่าง Configuration File และโครงสร้างพื้นฐานจริงครับ โดยปกติจะเป็นไฟล์ชื่อ
terraform.tfstate
ภาษา HCL (HashiCorp Configuration Language) เบื้องต้น
HCL เป็นภาษาที่ถูกออกแบบมาให้มนุษย์อ่านง่ายและใช้งานง่าย โครงสร้างพื้นฐานของ HCL มักประกอบด้วยบล็อกต่างๆ เช่น:
# กำหนด Provider ที่จะใช้งาน
provider "aws" {
region = "ap-southeast-1" # กำหนด Region ของ AWS
}
# กำหนด Resource ที่จะสร้าง (เช่น EC2 Instance)
resource "aws_instance" "my_web_server" {
ami = "ami-0abcdef1234567890" # AMI ID
instance_type = "t2.micro" # ชนิดของ Instance
tags = {
Name = "MyWebServer"
}
}
# กำหนด Variable เพื่อให้ Configuration มีความยืดหยุ่น
variable "instance_count" {
description = "Number of EC2 instances to deploy"
type = number
default = 1
}
# กำหนด Output เพื่อแสดงข้อมูลสำคัญหลังจาก Apply
output "instance_ip_address" {
description = "Public IP address of the EC2 instance"
value = aws_instance.my_web_server.public_ip
}
จะเห็นว่าแต่ละบล็อกจะเริ่มต้นด้วยคีย์เวิร์ด (เช่น provider, resource, variable, output) ตามด้วยประเภทของบล็อกและชื่อของบล็อกนั้นๆ ภายในบล็อกจะมีการกำหนด Arguments และ Values ครับ
วงจรการทำงานของ Terraform (Init, Plan, Apply, Destroy)
การทำงานกับ Terraform จะเป็นไปตามวงจรพื้นฐาน 4 ขั้นตอนหลักๆ ดังนี้ครับ:
terraform init:- เป็นคำสั่งแรกที่คุณต้องเรียกใช้ในไดเรกทอรีที่มี Terraform Configuration Files ครับ
- คำสั่งนี้จะดาวน์โหลด Providers ที่จำเป็นตามที่ระบุใน Configuration และตั้งค่า Backend สำหรับการจัดเก็บ State File
- ต้องรันเพียงครั้งเดียวเมื่อเริ่มต้นโปรเจกต์ หรือเมื่อมีการเพิ่ม/อัปเดต Providers/Modules
terraform plan:- คำสั่งนี้จะทำการวิเคราะห์ Configuration Files เปรียบเทียบกับ State File และสถานะจริงของโครงสร้างพื้นฐานใน Cloud (ถ้ามี)
- มันจะแสดงผลลัพธ์เป็น “แผนการ” ว่า Terraform จะสร้าง (
+), เปลี่ยนแปลง (~) หรือลบ (-) ทรัพยากรอะไรบ้าง - เป็นขั้นตอนที่สำคัญมากในการตรวจสอบความถูกต้องก่อนที่จะทำการเปลี่ยนแปลงจริงครับ
- คุณสามารถบันทึกแผนนี้เป็นไฟล์ได้ เช่น
terraform plan -out "myplan.tfplan"
terraform apply:- คำสั่งนี้จะดำเนินการตามแผนที่สร้างไว้ในขั้นตอน
planเพื่อสร้างหรือปรับเปลี่ยนโครงสร้างพื้นฐานจริงใน Cloud Provider - หากคุณไม่ได้ระบุไฟล์แผนที่สร้างไว้ด้วย
-outTerraform จะสร้างแผนใหม่และขอการยืนยันก่อนดำเนินการ - หลังจากการ Apply สำเร็จ Terraform จะอัปเดต State File ด้วยสถานะล่าสุดของโครงสร้างพื้นฐานครับ
- คำสั่งนี้จะดำเนินการตามแผนที่สร้างไว้ในขั้นตอน
terraform destroy:- คำสั่งนี้ใช้สำหรับลบทรัพยากรทั้งหมดที่ Terraform ได้สร้างและจัดการออกไปครับ
- เป็นคำสั่งที่มีความเสี่ยงสูง ควรใช้ด้วยความระมัดระวังและตรวจสอบให้แน่ใจว่าเป็นสิ่งที่คุณต้องการจริงๆ
- Terraform จะแสดงรายการทรัพยากรที่จะถูกลบและขอการยืนยันก่อนดำเนินการ
การทำความเข้าใจวงจรนี้จะช่วยให้คุณใช้งาน Terraform ได้อย่างมีประสิทธิภาพและปลอดภัยครับ
เตรียมความพร้อมสำหรับ Terraform บน AWS
ก่อนที่เราจะเริ่มเขียนโค้ดเพื่อสร้างโครงสร้างพื้นฐานบน AWS เราต้องเตรียมเครื่องมือและสภาพแวดล้อมให้พร้อมก่อนครับ
ติดตั้ง Terraform
Terraform เป็น Single Binary ที่ติดตั้งง่าย ไม่มี Dependency ที่ซับซ้อน คุณสามารถดาวน์โหลดได้จากเว็บไซต์ทางการของ HashiCorp
- ไปที่ หน้าดาวน์โหลด Terraform
- เลือกเวอร์ชันที่ตรงกับระบบปฏิบัติการของคุณ (Windows, macOS, Linux)
- ดาวน์โหลดไฟล์ Zip
- แตกไฟล์ Zip คุณจะพบไฟล์
terraform(หรือterraform.exeสำหรับ Windows) - ย้ายไฟล์
terraformไปยังไดเรกทอรีที่อยู่ใน PATH ของระบบปฏิบัติการของคุณ (เช่น/usr/local/binสำหรับ Linux/macOS, หรือเพิ่มโฟลเดอร์ที่เก็บไฟล์ใน Environment Variables ของ Windows) - เปิด Terminal/Command Prompt แล้วพิมพ์
terraform -vเพื่อตรวจสอบว่าติดตั้งสำเร็จและเห็นเวอร์ชันของ Terraform ครับ
terraform -v
ผลลัพธ์ที่ได้ควรมีลักษณะประมาณนี้:
Terraform v1.x.x
on linux_amd64
ตั้งค่า AWS CLI และ Credential
Terraform จำเป็นต้องมีสิทธิ์ในการเข้าถึง AWS API เพื่อสร้างและจัดการทรัพยากร วิธีที่แนะนำคือการใช้ AWS Credentials ที่ตั้งค่าไว้ในเครื่องของคุณ โดยผ่าน AWS CLI ครับ
- ติดตั้ง AWS CLI: หากยังไม่ได้ติดตั้ง ให้ดาวน์โหลดและติดตั้งจาก เว็บไซต์ทางการของ AWS CLI
- กำหนดค่า AWS Credentials: ใช้คำสั่ง
aws configureเพื่อตั้งค่า Access Key ID, Secret Access Key, Default Region และ Output Format ครับ
aws configure
คุณจะถูกถามข้อมูลดังนี้:
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: ap-southeast-1
Default output format [None]: json
ข้อควรระวัง: อย่าใช้ Root User Credentials สำหรับการทำงานทั่วไป แต่ควรสร้าง IAM User ที่มีสิทธิ์เพียงพอต่อการทำงาน (Least Privilege) และใช้ Credentials ของ IAM User นั้นครับ
สำหรับบทความเกี่ยวกับ IAM User เพิ่มเติม สามารถอ่านได้ที่ อ่านเพิ่มเติม
โครงสร้างโปรเจกต์ Terraform เบื้องต้น
การจัดระเบียบไฟล์ Configuration ให้เป็นระเบียบเป็นสิ่งสำคัญสำหรับการทำงานกับ Terraform ครับ โครงสร้างพื้นฐานที่แนะนำคือ:
main.tf: ไฟล์หลักที่ใช้กำหนด Providers, Resources, Data Sources และ Modulesvariables.tf: ไฟล์ที่ใช้ประกาศตัวแปร (Variables) ที่คุณต้องการให้ผู้ใช้งานกำหนดค่าoutputs.tf: ไฟล์ที่ใช้กำหนดค่า Output ที่ต้องการแสดงผลหลังจาก Terraform ทำงานเสร็จversions.tf(หรือproviders.tf): ไฟล์สำหรับกำหนดเวอร์ชันของ Terraform และ Providers ที่ใช้งาน
คุณสามารถสร้างไดเรกทอรีใหม่สำหรับแต่ละโปรเจกต์หรือแต่ละชุดของ Infrastructure ที่ต้องการจัดการได้ครับ
mkdir my-aws-infra
cd my-aws-infra
touch main.tf variables.tf outputs.tf versions.tf
เริ่มต้นด้วยไฟล์ versions.tf เพื่อกำหนดเวอร์ชันของ Terraform และ AWS Provider:
# versions.tf
terraform {
required_version = "~> 1.0" # กำหนดเวอร์ชันของ Terraform ที่ต้องการ
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # กำหนดเวอร์ชันของ AWS Provider
}
}
}
provider "aws" {
region = "ap-southeast-1" # กำหนด AWS Region ที่จะใช้งาน
}
เมื่อคุณมีไฟล์ versions.tf แล้ว ให้รัน terraform init เพื่อดาวน์โหลด AWS Provider ครับ
terraform init
หากสำเร็จ คุณจะเห็นข้อความประมาณว่า “Terraform has been successfully initialized!” ครับ
ลงมือสร้าง Infrastructure บน AWS ด้วย Terraform (ตัวอย่างการใช้งานจริง)
ตอนนี้เราพร้อมที่จะเริ่มเขียนโค้ด Terraform เพื่อสร้างทรัพยากรบน AWS กันแล้วครับ ผมจะยกตัวอย่างการสร้างทรัพยากรพื้นฐานที่ใช้บ่อย เพื่อให้คุณเห็นภาพและนำไปปรับใช้ได้จริงครับ
ตัวอย่าง 1: สร้าง AWS VPC และ Subnet พื้นฐาน
Virtual Private Cloud (VPC) คือเครือข่ายเสมือนส่วนตัวของคุณบน AWS ซึ่งเป็นรากฐานของโครงสร้างพื้นฐานทั้งหมดครับ
สร้างไฟล์ vpc.tf:
# vpc.tf
# Resource: AWS VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16" # ช่วง IP Address ของ VPC
enable_dns_hostnames = true # เปิดใช้งาน DNS Hostnames
enable_dns_support = true # เปิดใช้งาน DNS Support
tags = {
Name = "siamlancard-main-vpc"
}
}
# Resource: Internet Gateway
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id # ผูก Internet Gateway กับ VPC ที่สร้างไว้
tags = {
Name = "siamlancard-main-igw"
}
}
# Resource: Public Subnet (สำหรับทรัพยากรที่ต้องเข้าถึงอินเทอร์เน็ต)
resource "aws_subnet" "public_a" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-southeast-1a" # เลือก Availability Zone
map_public_ip_on_launch = true # กำหนดให้ Instance ที่สร้างใน Subnet นี้ได้ Public IP
tags = {
Name = "siamlancard-public-subnet-a"
}
}
# Resource: Private Subnet (สำหรับทรัพยากรที่ไม่ต้องเข้าถึงอินเทอร์เน็ตโดยตรง)
resource "aws_subnet" "private_a" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.10.0/24"
availability_zone = "ap-southeast-1a"
tags = {
Name = "siamlancard-private-subnet-a"
}
}
# Resource: Route Table สำหรับ Public Subnet
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0" # ทุก Traffic
gateway_id = aws_internet_gateway.main.id # ส่งออกผ่าน Internet Gateway
}
tags = {
Name = "siamlancard-public-rt"
}
}
# Resource: Route Table Association สำหรับ Public Subnet
resource "aws_route_table_association" "public_a" {
subnet_id = aws_subnet.public_a.id
route_table_id = aws_route_table.public.id
}
# Output: VPC ID และ Public Subnet 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 A"
value = aws_subnet.public_a.id
}
output "private_subnet_id" {
description = "The ID of the private subnet A"
value = aws_subnet.private_a.id
}
คำอธิบายโค้ด:
aws_vpc.main: สร้าง VPC ชื่อsiamlancard-main-vpcพร้อม CIDR Block10.0.0.0/16aws_internet_gateway.main: สร้าง Internet Gateway และผูกเข้ากับ VPCaws_subnet.public_a: สร้าง Public Subnet ใน Availability Zoneap-southeast-1aพร้อม CIDR Block10.0.1.0/24และกำหนดให้ Instance ที่เปิดใน Subnet นี้ได้รับ Public IP โดยอัตโนมัติaws_subnet.private_a: สร้าง Private Subnet ใน Availability Zoneap-southeast-1aพร้อม CIDR Block10.0.10.0/24aws_route_table.public: สร้าง Route Table สำหรับ Public Subnet โดยกำหนด Route ให้ Traffic ที่มุ่งไปยัง0.0.0.0/0(ทุกที่) ออกผ่าน Internet Gatewayaws_route_table_association.public_a: ผูก Public Subnet เข้ากับ Route Table ที่สร้างไว้output: แสดงค่า ID ของ VPC และ Subnet ที่สร้างขึ้นมา เพื่อให้สามารถนำไปใช้ใน Configuration อื่นๆ ได้ง่ายขึ้น
เมื่อเขียนโค้ดเสร็จแล้ว ให้ดำเนินการตามวงจรของ Terraform:
terraform init # ดาวน์โหลด Provider (ถ้ายังไม่ได้ทำ)
terraform plan # ตรวจสอบแผนการสร้างทรัพยากร
terraform apply # สร้างทรัพยากรบน AWS
ในขั้นตอน terraform apply คุณจะต้องพิมพ์ yes เพื่อยืนยันการสร้างทรัพยากรครับ
ตัวอย่าง 2: สร้าง EC2 Instance
เราจะสร้าง EC2 Instance ใน Public Subnet ที่เราเพิ่งสร้างไปครับ
สร้างไฟล์ ec2.tf:
# ec2.tf
# Data Source: ค้นหา AMI ล่าสุดสำหรับ Amazon Linux 2
data "aws_ami" "amazon_linux_2" {
most_recent = true
owners = ["amazon"] # AMI ของ Amazon Official
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# Resource: Security Group สำหรับ EC2 Instance
resource "aws_security_group" "web_sg" {
name = "siamlancard-web-sg"
description = "Allow HTTP and SSH access"
vpc_id = aws_vpc.main.id # อ้างอิง VPC จากไฟล์ vpc.tf
# Rule สำหรับ SSH
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # อนุญาต SSH จากทุกที่ (ควรจำกัด IP จริงๆ)
}
# Rule สำหรับ HTTP
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # อนุญาต HTTP จากทุกที่
}
# Rule สำหรับ Egress (อนุญาตให้ออกไปได้ทุกที่)
egress {
from_port = 0
to_port = 0
protocol = "-1" # -1 คือทุก Protocol
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "siamlancard-web-sg"
}
}
# Resource: Key Pair สำหรับ SSH เข้า EC2
resource "aws_key_pair" "deployer_key" {
key_name = "siamlancard-deployer-key"
public_key = file("~/.ssh/id_rsa.pub") # ระบุ Path ไปยัง Public Key ของคุณ
}
# Resource: EC2 Instance
resource "aws_instance" "web_server" {
ami = data.aws_ami.amazon_linux_2.id # ใช้ AMI ID ที่ได้จาก Data Source
instance_type = "t2.micro"
subnet_id = aws_subnet.public_a.id # ใช้ Public Subnet ID
vpc_security_group_ids = [aws_security_group.web_sg.id] # ผูกกับ Security Group
key_name = aws_key_pair.deployer_key.key_name # ผูกกับ Key Pair
# user_data ใช้สำหรับรัน Script เมื่อ Instance เริ่มทำงาน
user_data = <<-EOF
#!/bin/bash
sudo yum update -y
sudo yum install -y httpd
sudo systemctl start httpd
sudo systemctl enable httpd
echo "Hello from Terraform on AWS!
" > /var/www/html/index.html
EOF
tags = {
Name = "siamlancard-web-server"
}
}
# Output: Public IP ของ EC2 Instance
output "web_server_public_ip" {
description = "The public IP address of the web server"
value = aws_instance.web_server.public_ip
}
ข้อควรระวัง: ก่อนรันโค้ดนี้ ตรวจสอบให้แน่ใจว่าคุณมี SSH Public Key อยู่ที่ ~/.ssh/id_rsa.pub หรือเปลี่ยน Path ให้ถูกต้องครับ หากไม่มี คุณสามารถสร้างได้ด้วยคำสั่ง ssh-keygen
คำอธิบายโค้ด:
data "aws_ami" "amazon_linux_2": ค้นหา AMI ID ล่าสุดของ Amazon Linux 2aws_security_group.web_sg: สร้าง Security Group ที่อนุญาตการเชื่อมต่อ SSH (Port 22) และ HTTP (Port 80) จากทุกที่ (ใน Production ควรจำกัด IP ที่เข้าถึงได้)aws_key_pair.deployer_key: สร้าง Key Pair บน AWS โดยใช้ Public Key จากเครื่องคอมพิวเตอร์ของคุณaws_instance.web_server: สร้าง EC2 Instance โดยใช้ AMI, Instance Type, Subnet ID, Security Group และ Key Pair ที่กำหนดไว้user_data: เป็น Bash Script ที่จะรันเมื่อ EC2 Instance เริ่มต้นทำงานครั้งแรก ในตัวอย่างนี้จะทำการอัปเดตระบบ ติดตั้ง Apache Web Server และสร้างไฟล์index.htmlง่ายๆ ครับoutput "web_server_public_ip": แสดง Public IP ของ EC2 Instance ที่สร้างขึ้น
ดำเนินการ:
terraform plan
terraform apply
เมื่อ apply เสร็จ คุณจะได้ Public IP ของ EC2 Instance สามารถลองเข้าถึงด้วยเบราว์เซอร์เพื่อดูหน้าเว็บ หรือ SSH เข้าไปจัดการได้ครับ
ตัวอย่าง 3: สร้าง S3 Bucket สำหรับเก็บข้อมูล
Amazon S3 (Simple Storage Service) เป็น Object Storage ที่มีความทนทานสูงและ Scale ได้ไม่จำกัด เหมาะสำหรับเก็บข้อมูลหลากหลายประเภท
สร้างไฟล์ s3.tf:
# s3.tf
# Resource: S3 Bucket
resource "aws_s3_bucket" "siamlancard_data" {
bucket = "siamlancard-data-bucket-unique-name-12345" # ชื่อ Bucket ต้องไม่ซ้ำกันทั่วโลก
# เปิดใช้งาน Versioning เพื่อเก็บประวัติการเปลี่ยนแปลงไฟล์
versioning {
enabled = true
}
tags = {
Name = "siamlancard-data-bucket"
Environment = "Dev"
}
}
# Resource: S3 Bucket Public Access Block (แนะนำให้ปิด Public Access)
resource "aws_s3_bucket_public_access_block" "siamlancard_data_block" {
bucket = aws_s3_bucket.siamlancard_data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# Output: S3 Bucket ID และ ARN
output "s3_bucket_id" {
description = "The ID of the S3 bucket"
value = aws_s3_bucket.siamlancard_data.id
}
output "s3_bucket_arn" {
description = "The ARN of the S3 bucket"
value = aws_s3_bucket.siamlancard_data.arn
}
ข้อควรระวัง: ชื่อ S3 Bucket ต้องไม่ซ้ำกันทั่วโลก! กรุณาเปลี่ยน siamlancard-data-bucket-unique-name-12345 เป็นชื่อที่ไม่ซ้ำใครของคุณเองครับ
คำอธิบายโค้ด:
aws_s3_bucket.siamlancard_data: สร้าง S3 Bucket พร้อมกำหนดชื่อ และเปิดใช้งาน Versioning เพื่อป้องกันการเผลอลบไฟล์หรือต้องการย้อนกลับเวอร์ชันaws_s3_bucket_public_access_block.siamlancard_data_block: เป็น Best Practice ในการบล็อก Public Access ให้กับ S3 Bucket เพื่อเพิ่มความปลอดภัย โดยการตั้งค่าทั้ง 4 ตัวเป็นtrueจะช่วยป้องกันไม่ให้ Bucket นี้ถูกเข้าถึงแบบสาธารณะได้ครับoutput: แสดง ID และ ARN ของ S3 Bucket
ดำเนินการ:
terraform plan
terraform apply
ตอนนี้คุณมี S3 Bucket ที่พร้อมใช้งานสำหรับการจัดเก็บข้อมูลแล้วครับ
ตัวอย่าง 4: สร้าง RDS Database (MySQL)
Amazon RDS (Relational Database Service) ช่วยให้การตั้งค่า ใช้งาน และ Scale Relational Database เป็นเรื่องง่ายครับ
สร้างไฟล์ rds.tf:
# rds.tf
# Variables สำหรับ RDS (ควรเก็บใน variables.tf และใช้ .tfvars file สำหรับค่าจริง)
variable "db_name" {
description = "Name of the RDS database"
type = string
default = "siamlancarddb"
}
variable "db_username" {
description = "Master username for the RDS database"
type = string
default = "admin"
}
# *****************************************************************
# WARNING: ไม่ควร hardcode รหัสผ่านในโค้ดจริง! ควรใช้ Secrets Manager หรือ environment variables
# *****************************************************************
variable "db_password" {
description = "Master password for the RDS database"
type = string
sensitive = true # ทำให้ค่านี้ไม่แสดงใน Output หรือ logs
default = "ChangeMeStrongPassword123!" # เปลี่ยนเป็นรหัสผ่านที่รัดกุมยิ่งขึ้น
}
# Resource: RDS Subnet Group (RDS ต้องอยู่ใน Subnet Group ที่ครอบคลุมอย่างน้อย 2 AZ)
resource "aws_db_subnet_group" "siamlancard_rds_subnet_group" {
name = "siamlancard-rds-subnet-group"
subnet_ids = [aws_subnet.private_a.id] # ใช้ Private Subnet ที่สร้างไว้ใน vpc.tf
# ใน Production ควรมีอย่างน้อย 2 Private Subnet ใน 2 AZs ที่แตกต่างกัน
tags = {
Name = "siamlancard-rds-subnet-group"
}
}
# Resource: Security Group สำหรับ RDS (อนุญาต Traffic จาก EC2 Security Group)
resource "aws_security_group" "rds_sg" {
name = "siamlancard-rds-sg"
description = "Allow inbound traffic from web servers to RDS"
vpc_id = aws_vpc.main.id
# อนุญาต Traffic จาก Security Group ของ EC2 Web Server
ingress {
from_port = 3306 # Port สำหรับ MySQL
to_port = 3306
protocol = "tcp"
security_groups = [aws_security_group.web_sg.id] # อ้างอิง Security Group ของ EC2
description = "Allow MySQL traffic from web servers"
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "siamlancard-rds-sg"
}
}
# Resource: RDS MySQL Instance
resource "aws_db_instance" "siamlancard_mysql" {
allocated_storage = 20
engine = "mysql"
engine_version = "8.0"
instance_class = "db.t3.micro"
db_name = var.db_name
username = var.db_username
password = var.db_password
db_subnet_group_name = aws_db_subnet_group.siamlancard_rds_subnet_group.name
vpc_security_group_ids = [aws_security_group.rds_sg.id]
skip_final_snapshot = true # ใน Production ควรตั้งเป็น false
publicly_accessible = false # ไม่ควรให้ RDS เข้าถึงได้จากอินเทอร์เน็ตโดยตรง
tags = {
Name = "siamlancard-mysql-db"
}
}
# Output: Endpoint ของ RDS
output "rds_endpoint" {
description = "The endpoint of the RDS instance"
value = aws_db_instance.siamlancard_mysql.endpoint
}
คำอธิบายโค้ด:
variable "db_name","db_username","db_password": กำหนดตัวแปรสำหรับชื่อฐานข้อมูล, ชื่อผู้ใช้ และรหัสผ่านaws_db_subnet_group.siamlancard_rds_subnet_group: สร้าง DB Subnet Group โดยระบุ Subnet ID ที่ RDS จะใช้ ใน Production ควรมี Private Subnet อย่างน้อยสอง Subnet ในสอง Availability Zone ที่แตกต่างกันเพื่อ High Availability ครับaws_security_group.rds_sg: สร้าง Security Group สำหรับ RDS ที่อนุญาตการเชื่อมต่อ MySQL (Port 3306) เฉพาะจาก Security Group ของ EC2 Web Server เท่านั้นaws_db_instance.siamlancard_mysql: สร้าง RDS Instance ชนิด MySQL 8.0 โดยกำหนดขนาดพื้นที่เก็บข้อมูล, Instance Class, ชื่อผู้ใช้, รหัสผ่าน, DB Subnet Group และ Security Grouppublicly_accessible = false: เป็น Best Practice ที่สำคัญมาก เพื่อไม่ให้ฐานข้อมูลสามารถเข้าถึงได้จากอินเทอร์เน็ตโดยตรง เพิ่มความปลอดภัยskip_final_snapshot = true: สำหรับการทดสอบ แต่ใน Production ควรตั้งเป็นfalseเพื่อให้มีการสร้าง Snapshot สุดท้ายเมื่อลบ Instance ครับoutput "rds_endpoint": แสดง Endpoint ของ RDS Instance
ดำเนินการ:
terraform plan
terraform apply
การสร้าง RDS Instance อาจใช้เวลาพอสมควรครับ โปรดรอจนกว่าจะเสร็จสมบูรณ์
หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับการจัดการ RDS ด้วย Terraform สามารถอ่านได้ที่ อ่านเพิ่มเติม
ตัวอย่าง 5: สร้าง IAM Role และ Policy
AWS Identity and Access Management (IAM) เป็นบริการที่ช่วยให้คุณจัดการการเข้าถึงบริการและทรัพยากรบน AWS ได้อย่างปลอดภัยครับ
สร้างไฟล์ iam.tf:
# iam.tf
# Resource: IAM Role สำหรับ EC2 ที่จะเข้าถึง S3
resource "aws_iam_role" "s3_access_role" {
name = "siamlancard-ec2-s3-access-role"
# Trust Policy: อนุญาตให้ EC2 Service สามารถ assume role นี้ได้
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
},
]
})
tags = {
Name = "siamlancard-ec2-s3-access-role"
}
}
# Resource: IAM Policy สำหรับการอ่าน S3 Bucket
resource "aws_iam_policy" "s3_read_policy" {
name = "siamlancard-s3-read-policy"
description = "Policy to allow read access to specific S3 bucket"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"s3:GetObject",
"s3:ListBucket",
]
Effect = "Allow"
Resource = [
aws_s3_bucket.siamlancard_data.arn, # อ้างอิง ARN ของ S3 Bucket
"${aws_s3_bucket.siamlancard_data.arn}/*", # อนุญาตเข้าถึง Object ภายใน Bucket
]
},
]
})
}
# Resource: IAM Role Policy Attachment (ผูก Policy กับ Role)
resource "aws_iam_role_policy_attachment" "s3_read_attachment" {
role = aws_iam_role.s3_access_role.name
policy_arn = aws_iam_policy.s3_read_policy.arn
}
# Resource: IAM Instance Profile สำหรับ EC2
resource "aws_iam_instance_profile" "s3_access_profile" {
name = "siamlancard-ec2-s3-access-profile"
role = aws_iam_role.s3_access_role.name
}
# Output: ARN ของ IAM Role
output "iam_role_arn" {
description = "The ARN of the IAM role for S3 access"
value = aws_iam_role.s3_access_role.arn
}
output "iam_instance_profile_name" {
description = "The name of the IAM instance profile"
value = aws_iam_instance_profile.s3_access_profile.name
}
คำอธิบายโค้ด:
aws_iam_role.s3_access_role: สร้าง IAM Role ที่ EC2 Service สามารถassumeได้ (สวมบทบาทนี้)aws_iam_policy.s3_read_policy: สร้าง IAM Policy ที่อนุญาตให้GetObjectและListBucketบน S3 Bucket ที่เราสร้างไว้เท่านั้น (หลักการ Least Privilege)aws_iam_role_policy_attachment.s3_read_attachment: ผูก Policys3_read_policyเข้ากับ Roles3_access_roleaws_iam_instance_profile.s3_access_profile: สร้าง Instance Profile ที่ผูกกับ Role นี้ Instance Profile เป็นสิ่งที่ EC2 Instance ใช้ในการassumeIAM Role ครับoutput: แสดง ARN ของ IAM Role และชื่อของ Instance Profile
หลังจากสร้าง IAM Role และ Policy แล้ว คุณสามารถแก้ไขไฟล์ ec2.tf เพื่อผูก Instance Profile เข้ากับ EC2 Instance ได้ครับ:
อัปเดตไฟล์ ec2.tf โดยเพิ่ม iam_instance_profile ในบล็อก aws_instance.web_server
# ในไฟล์ ec2.tf (ส่วนของ aws_instance.web_server)
resource "aws_instance" "web_server" {
# ... (โค้ดเดิม) ...
iam_instance_profile = aws_iam_instance_profile.s3_access_profile.name # เพิ่มบรรทัดนี้
tags = {
Name = "siamlancard-web-server"
}
}
ดำเนินการอีกครั้ง:
terraform plan
terraform apply
ตอนนี้ EC2 Instance ของคุณจะมีสิทธิ์ในการเข้าถึง S3 Bucket ที่เราสร้างไว้แล้วครับ
คุณสมบัติขั้นสูงและแนวทางปฏิบัติที่ดีที่สุด (Best Practices)
เมื่อคุณคุ้นเคยกับพื้นฐานของ Terraform แล้ว การทำความเข้าใจคุณสมบัติขั้นสูงและแนวทางปฏิบัติที่ดีที่สุดจะช่วยให้คุณจัดการโครงสร้างพื้นฐานที่ซับซ้อนได้อย่างมีประสิทธิภาพและปลอดภัยยิ่งขึ้นครับ
Terraform Modules: การนำโค้ดกลับมาใช้ซ้ำ
Modules คือบล็อกของ Terraform Configuration ที่รวมเอา Resources หลายๆ ตัวเข้าด้วยกันเป็นหน่วยเดียว เพื่อให้สามารถนำไปใช้ซ้ำได้ง่ายและจัดการโครงสร้างพื้นฐานที่ซับซ้อนให้เป็นระเบียบครับ
- ประโยชน์:
- การนำกลับมาใช้ซ้ำ (Reusability): คุณสามารถสร้าง Module สำหรับ VPC, EC2 หรือ RDS แล้วนำไปใช้ซ้ำในหลายๆ โปรเจกต์หรือหลายๆ สภาพแวดล้อมได้
- การจัดระเบียบ (Organization): ช่วยจัดระเบียบโค้ดให้เป็นโครงสร้างที่ชัดเจนและอ่านง่ายขึ้น
- ลดความซับซ้อน (Abstraction): ผู้ใช้ Module ไม่จำเป็นต้องรู้รายละเอียดการทำงานภายในของ Module เพียงแค่กำหนด Input Variables ก็สามารถใช้งานได้
- มาตรฐาน (Standardization): ช่วยให้มั่นใจว่าโครงสร้างพื้นฐานที่สร้างขึ้นมีมาตรฐานเดียวกัน
- การใช้งาน: คุณสามารถสร้าง Modules ของตัวเอง หรือใช้ Modules ที่มีอยู่ใน Terraform Registry ได้ครับ
# ตัวอย่างการเรียกใช้ Module
module "my_vpc" {
source = "./modules/vpc" # Path ไปยัง Module ของคุณ
# หรือใช้ Module จาก Terraform Registry
# source = "terraform-aws-modules/vpc/aws"
# version = "3.1.0"
name = "siamlancard-app-vpc"
cidr_block = "10.0.0.0/16"
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.10.0/24", "10.0.11.0/24"]
}
Terraform State Management: หัวใจสำคัญของ Terraform
State File (terraform.tfstate) เป็นสิ่งสำคัญที่สุดในการทำงานของ Terraform เพราะมันบันทึกสถานะของทรัพยากรที่ Terraform กำลังจัดการอยู่ครับ
- Local State: โดยค่าเริ่มต้น State File จะถูกเก็บไว้ในเครื่องที่คุณรัน Terraform (
.terraform/terraform.tfstate) ซึ่งเหมาะสำหรับการทดลองหรือโปรเจกต์ส่วนตัว - Remote State: สำหรับทีมงานหรือ Production Environment การใช้ Remote State เป็นสิ่งจำเป็นอย่างยิ่งครับ โดย State File จะถูกเก็บไว้ในบริการจัดเก็บข้อมูลระยะไกลที่ปลอดภัย เช่น Amazon S3, Azure Blob Storage หรือ HashiCorp Consul/Terraform Cloud
- ประโยชน์ของ Remote State:
- การทำงานร่วมกัน (Collaboration): ทีมหลายคนสามารถเข้าถึงและอัปเดต State เดียวกันได้
- ความน่าเชื่อถือ (Reliability): State File ถูกจัดเก็บอย่างปลอดภัยและสำรองข้อมูลไว้
- การล็อก (Locking): ป้องกันไม่ให้หลายคนพยายาม Apply การเปลี่ยนแปลงพร้อมกัน ซึ่งอาจทำให้ State File เสียหาย
- การตั้งค่า S3 Backend สำหรับ AWS:
สร้างไฟล์ backend.tf (หรือรวมไว้ใน versions.tf):
# backend.tf
terraform {
backend "s3" {
bucket = "siamlancard-terraform-state-bucket-12345" # ชื่อ Bucket ต้องไม่ซ้ำกันทั่วโลก
key = "dev/siamlancard-infra.tfstate" # Path ภายใน Bucket
region = "ap-southeast-1"
encrypt = true # เข้ารหัส State File
dynamodb_table = "siamlancard-terraform-state-lock" # ใช้ DynamoDB สำหรับ State Locking
}
}
ข้อควรระวัง: ชื่อ Bucket ต้องไม่ซ้ำกันทั่วโลก! และคุณต้องสร้าง S3 Bucket และ DynamoDB Table นี้ด้วยตนเองก่อนที่จะรัน terraform init ครั้งแรกครับ
ตัวอย่างการสร้าง S3 Bucket และ DynamoDB Table สำหรับ Backend ด้วย Terraform (หากคุณต้องการแยกโปรเจกต์):
# infra-state-backend.tf (ไฟล์แยกสำหรับสร้าง Backend Resources)
resource "aws_s3_bucket" "terraform_state_bucket" {
bucket = "siamlancard-terraform-state-bucket-12345"
acl = "private" # จำกัดการเข้าถึง
versioning {
enabled = true
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
tags = {
Name = "siamlancard-terraform-state-bucket"
}
}
resource "aws_dynamodb_table" "terraform_state_lock" {
name = "siamlancard-terraform-state-lock"
billing_mode = "PAY_PER_REQUEST" # คิดค่าใช้จ่ายตามการใช้งานจริง
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
tags = {
Name = "siamlancard-terraform-state-lock"
}
}
หลังจากที่คุณสร้าง Backend Resources และกำหนด backend "s3" ใน Configuration แล้ว ให้รัน terraform init อีกครั้งเพื่อย้าย State File ไปยัง S3 ครับ
Terraform Workspaces: การจัดการสภาพแวดล้อมที่แตกต่างกัน
Workspaces ช่วยให้คุณสามารถจัดการสภาพแวดล้อมที่แตกต่างกัน (เช่น Dev, Staging, Production) โดยใช้ชุด Configuration Files ชุดเดียวกันครับ แต่ละ Workspace จะมี State File เป็นของตัวเอง
terraform workspace new dev # สร้าง Workspace ชื่อ 'dev'
terraform workspace new staging # สร้าง Workspace ชื่อ 'staging'
terraform workspace new prod # สร้าง Workspace ชื่อ 'prod'
terraform workspace select dev # เลือก Workspace 'dev' เพื่อทำงาน
terraform apply # Apply กับสภาพแวดล้อม dev
terraform workspace select prod # เลือก Workspace 'prod'
terraform apply # Apply กับสภาพแวดล้อม prod
คุณสามารถใช้ terraform.workspace ในโค้ดของคุณเพื่อปรับเปลี่ยนค่าตาม Workspace ที่กำลังใช้งานอยู่ได้ เช่น การตั้งชื่อทรัพยากร:
resource "aws_instance" "web_server" {
# ...
tags = {
Name = "siamlancard-web-server-${terraform.workspace}"
Environment = terraform.workspace
}
}
Terraform Variables และ Outputs: เพิ่มความยืดหยุ่นและข้อมูลที่จำเป็น
- Variables: ใช้ในการทำให้ Configuration มีความยืดหยุ่น คุณสามารถกำหนดค่าตัวแปรจาก Command Line, จากไฟล์
.tfvarsหรือจาก Environment Variables ครับ - Outputs: ใช้ในการแสดงข้อมูลสำคัญหลังจาก Terraform Apply เสร็จสิ้น เช่น IP Address ของ Instance, Endpoint ของ Database, หรือ ARN ของ Bucket
การใช้ variables.tf และ outputs.tf ที่ดีจะช่วยให้โค้ดของคุณอ่านง่าย จัดการง่าย และนำไปใช้ซ้ำได้ครับ
Terraform Data Sources: การอ้างอิงทรัพยากรที่มีอยู่แล้ว
Data Sources ช่วยให้ Terraform สามารถดึงข้อมูลเกี่ยวกับทรัพยากรที่มีอยู่แล้วใน Cloud Provider โดยที่ Terraform ไม่ได้เป็นคนสร้างขึ้นมาเองครับ มีประโยชน์มากเมื่อคุณต้องการอ้างอิงถึง:
- AMI ล่าสุด
- VPC ที่สร้างด้วยมือหรือโดยทีมอื่น
- Security Group ที่มีอยู่แล้ว
# ตัวอย่าง Data Source สำหรับ VPC ID ที่มีอยู่แล้ว
data "aws_vpc" "existing_vpc" {
filter {
name = "tag:Name"
values = ["my-existing-vpc"]
}
}
resource "aws_subnet" "new_subnet" {
vpc_id = data.aws_vpc.existing_vpc.id
cidr_block = "10.0.1.0/24"
# ...
}
การทดสอบ (Testing) Terraform Configuration
การทดสอบโค้ด Terraform เป็นสิ่งสำคัญเพื่อให้มั่นใจว่าโครงสร้างพื้นฐานที่สร้างขึ้นเป็นไปตามที่คาดหวังและทำงานได้อย่างถูกต้องครับ
- Static Analysis: ใช้เครื่องมือเช่น
terraform validateเพื่อตรวจสอบ Syntax และความถูกต้องของ Configuration - Linting: ใช้เครื่องมือเช่น
tflintเพื่อตรวจสอบ Best Practices และ Potential Errors - Unit/Integration Testing: ใช้ Frameworks เช่น Terratest (Go-based) หรือ Kitchen-Terraform เพื่อทำการทดสอบ End-to-End โดยการสร้างทรัพยากรจริงใน Cloud, รัน Test Cases และลบทรัพยากรทิ้งครับ
- Sentinel Policies (HashiCorp Terraform Cloud/Enterprise): สำหรับ Enterprise level สามารถใช้ Sentinel เพื่อบังคับใช้ Policy เกี่ยวกับความปลอดภัยหรือ Cost Management
CI/CD Pipeline สำหรับ Terraform: การทำงานอัตโนมัติ
การรวม Terraform เข้ากับ CI/CD Pipeline (เช่น Jenkins, GitLab CI, GitHub Actions, AWS CodePipeline) ช่วยให้กระบวนการจัดเตรียมและอัปเดตโครงสร้างพื้นฐานเป็นไปโดยอัตโนมัติและสอดคล้องกันครับ
- GitOps: แนวทางปฏิบัติที่ใช้ Git Repository เป็นแหล่งความจริง (Single Source of Truth) สำหรับโครงสร้างพื้นฐาน การเปลี่ยนแปลงทั้งหมดจะถูก Commit เข้า Git และ Pipeline จะ Trigger การ
terraform planและterraform applyโดยอัตโนมัติ (หรือกึ่งอัตโนมัติ) - ขั้นตอนหลักใน Pipeline:
terraform initterraform validateterraform plan(สร้าง Artifact เป็นไฟล์แผน)- (การตรวจสอบด้วยตนเอง/การอนุมัติ)
terraform apply "myplan.tfplan"
ความปลอดภัย (Security) ใน Terraform: แนวทางปฏิบัติที่ดีที่สุด
- Least Privilege: กำหนดสิทธิ์ให้กับ IAM User/Role ที่ใช้รัน Terraform ให้มีเพียงพอต่อการสร้าง/จัดการทรัพยากรที่จำเป็นเท่านั้น ไม่มากเกินไป
- Secrets Management: ไม่ควรเก็บ Sensitive Data เช่น Database Passwords หรือ API Keys ไว้ใน Configuration Files โดยตรง แต่ควรใช้บริการ Secrets Management เช่น AWS Secrets Manager หรือ AWS Parameter Store
- State File Security:
- ใช้ Remote State ที่มีการเข้ารหัส (เช่น S3 Bucket ที่เปิดใช้งาน Server-Side Encryption)
- จำกัดการเข้าถึง State File อย่างเข้มงวด
- เปิดใช้งาน Versioning สำหรับ State File เพื่อให้สามารถย้อนกลับได้หากเกิดปัญหา
- Code Review: ทำ Code Review สำหรับ Terraform Configuration เพื่อตรวจสอบความถูกต้อง ความปลอดภัย และ Best Practices
- Terraform Plan Review: ตรวจสอบผลลัพธ์ของ
terraform planอย่างละเอียดก่อนที่จะทำการapplyเสมอ
เปรียบเทียบ Terraform กับเครื่องมือ IaC อื่นๆ
Terraform ไม่ใช่เครื่องมือ IaC เพียงตัวเดียวในตลาด มีเครื่องมืออื่นๆ ที่มีจุดเด่นและเหมาะกับการใช้งานที่แตกต่างกันไปครับ มาดูกันว่า Terraform แตกต่างจากเครื่องมือยอดนิยมอื่นๆ อย่างไร
| คุณสมบัติ | Terraform | AWS CloudFormation | Ansible | Pulumi |
|---|---|---|---|---|
| ผู้พัฒนา | HashiCorp | Amazon Web Services (AWS) | Red Hat (เดิม Ansible, Inc.) | Pulumi Corp. |
| แนวคิดหลัก | Declarative (Describe desired state), Multi-cloud orchestration | Declarative (Describe desired state), AWS-specific | Imperative (Describe steps to reach state), Configuration Management | Declarative (Describe desired state), Multi-cloud, General-purpose programming languages |
| ภาษาที่ใช้ | HCL (HashiCorp Configuration Language) / JSON | YAML / JSON | YAML (for Playbooks) | TypeScript, Python, Go, C#, Java |
| รองรับ Cloud/Platform | Multi-cloud (AWS, Azure, GCP, VMware, Kubernetes, etc.) | AWS-only | Multi-cloud (via modules), On-prem, OS-level config | Multi-cloud (AWS, Azure, GCP, Kubernetes, etc.) |
| State Management | Managed by Terraform (Local or Remote State) | Managed by AWS (Stack) | Stateless (typically) | Managed by Pulumi (Local or Remote State) |
| ความสามารถหลัก | Provisioning Infrastructure resources | Provisioning AWS resources | Configuration Management, Application Deployment, Provisioning (less common) | Provisioning Infrastructure using general-purpose languages |
| ข้อดี | Multi-cloud, Extensible with Providers, Strong community, Modular design | Deep integration with AWS, Native AWS support, No external state management needed | Agentless, Simple YAML syntax, Great for config management, Idempotent by design | Use familiar programming languages, Strong IDE support, Rich testing frameworks |
| ข้อเสีย | Requires external state management for teams, HCL learning curve, Not ideal for config management | AWS-only, YAML/JSON can be verbose, Stack updates can be complex for large changes | Imperative approach can be less predictable, Not primarily for infrastructure provisioning | Steeper learning curve if unfamiliar with IaC concepts, Debugging can be complex |
สรุปการเปรียบเทียบ:
- Terraform: โดดเด่นในเรื่องการ Provisioning Infrastructure ข้าม Cloud ได้หลากหลาย เหมาะสำหรับองค์กรที่ต้องการย้ายหรือทำงานร่วมกับหลาย Cloud Providers และต้องการความยืดหยุ่นในการจัดการทรัพยากร
- AWS CloudFormation: เป็นตัวเลือกที่ดีที่สุดหากคุณต้องการทำงานบน AWS เท่านั้น เพราะมีการ Integrate กับบริการของ AWS ได้อย่างลึกซึ้งและเป็น Native Tool
- Ansible: