
ในยุคที่เทคโนโลยีคลาวด์เข้ามามีบทบาทสำคัญในการขับเคลื่อนธุรกิจ การจัดการโครงสร้างพื้นฐาน (Infrastructure) อย่างมีประสิทธิภาพและเป็นระบบระเบียบถือเป็นหัวใจสำคัญสู่ความสำเร็จครับ หนึ่งในแนวทางปฏิบัติที่ได้รับความนิยมและพิสูจน์แล้วว่ามีประสิทธิภาพสูงสุดคือ Infrastructure as Code (IaC) และเมื่อพูดถึง IaC บนแพลตฟอร์มคลาวด์ที่ใหญ่ที่สุดอย่าง AWS (Amazon Web Services) ชื่อของ Terraform จาก HashiCorp ก็มักจะถูกเอ่ยถึงเป็นอันดับต้น ๆ เสมอ บทความนี้จะพาทุกท่านดำดิ่งสู่โลกของ Terraform และ AWS เพื่อทำความเข้าใจว่าเครื่องมืออันทรงพลังนี้จะช่วยให้การสร้าง จัดการ และปรับปรุงโครงสร้างพื้นฐานบนคลาวด์ของคุณเป็นเรื่องง่าย มีความน่าเชื่อถือ และปรับขนาดได้ในแบบที่ไม่เคยมีมาก่อนได้อย่างไรครับ
ไม่ว่าคุณจะเป็นนักพัฒนา, DevOps Engineer, หรือผู้ดูแลระบบที่กำลังมองหาวิธีการจัดการ AWS Infrastructure ที่ดีกว่าเดิม บทความนี้จะครอบคลุมตั้งแต่พื้นฐานไปจนถึงแนวคิดขั้นสูง พร้อมตัวอย่างโค้ดที่ใช้งานได้จริง เพื่อให้คุณสามารถนำไปประยุกต์ใช้ในการทำงานได้ทันทีครับ
สารบัญ
- 1. ทำความเข้าใจ Infrastructure as Code (IaC)
- 2. Terraform คืออะไร?
- 3. ทำไมต้อง Terraform บน AWS?
- 4. เริ่มต้นใช้งาน Terraform สำหรับ AWS
- 5. สร้าง Infrastructure แรกบน AWS ด้วย Terraform
- 6. คุณสมบัติและแนวคิดขั้นสูงของ Terraform
- 7. แนวปฏิบัติที่ดีที่สุด (Best Practices) ในการใช้ Terraform บน AWS
- 8. Terraform Lifecycle และคำสั่งพื้นฐาน
- 9. กรณีศึกษา: การปรับใช้แอปพลิเคชัน N-Tier บน AWS ด้วย Terraform
- 10. คำถามที่พบบ่อย (FAQ)
- สรุปและ Call-to-Action
1. ทำความเข้าใจ Infrastructure as Code (IaC)
ก่อนที่เราจะเจาะลึกถึง Terraform เรามาทำความเข้าใจแนวคิดพื้นฐานที่อยู่เบื้องหลังความสามารถของมันกันก่อนครับ นั่นคือ Infrastructure as Code (IaC) ซึ่งเป็นเสาหลักสำคัญของการทำ DevOps และ Cloud Native Development ในปัจจุบัน
1.1. IaC คืออะไร?
Infrastructure as Code (IaC) คือการจัดการและจัดเตรียมโครงสร้างพื้นฐานด้านไอทีผ่านโค้ด แทนที่จะเป็นการตั้งค่าด้วยตนเองแบบเดิม ๆ ครับ แทนที่จะคลิกเมาส์ใน AWS Console เพื่อสร้างเซิร์ฟเวอร์, ฐานข้อมูล, เครือข่าย หรือ Load Balancer เราจะเขียนไฟล์กำหนดค่า (Configuration Files) ที่อธิบายถึงสถานะที่ต้องการของโครงสร้างพื้นฐานนั้น ๆ ครับ โค้ดเหล่านี้สามารถถูกจัดเก็บในระบบควบคุมเวอร์ชัน (Version Control System) เช่น Git ได้เหมือนกับโค้ดแอปพลิเคชันทั่วไปเลยครับ
หลักการสำคัญของ IaC คือ:
- Declarative vs. Imperative:
- Declarative: คุณระบุว่า “โครงสร้างพื้นฐานของฉันควรมีลักษณะอย่างไร” (What) เช่น ฉันต้องการ EC2 instance ที่มี RAM 8GB, CPU 2 Core, และใช้ Ubuntu 20.04 โดยไม่ต้องบอกว่า “ต้องทำอย่างไร” เพื่อให้ได้มา ซึ่ง Terraform ใช้แนวทางนี้ครับ
- Imperative: คุณระบุว่า “ต้องทำตามขั้นตอนเหล่านี้เพื่อสร้างโครงสร้างพื้นฐาน” (How) เช่น เข้าสู่ระบบ AWS console, คลิกที่ EC2, เลือก AMI, เลือก Instance Type, คลิก Launch ซึ่งเป็นแนวทางแบบ Manual หรือ Scripting แบบดั้งเดิมครับ
- Idempotency: การรันโค้ด IaC ซ้ำ ๆ ไม่ควรเปลี่ยนแปลงสถานะของระบบหลังจากครั้งแรกที่รันสำเร็จแล้ว กล่าวคือ ผลลัพธ์ที่ได้จะเหมือนเดิมเสมอ ไม่ว่าจะรันกี่ครั้งก็ตามครับ
1.2. ประโยชน์ของ IaC
การนำ IaC มาใช้มีประโยชน์มากมายที่ช่วยให้การจัดการโครงสร้างพื้นฐานมีประสิทธิภาพมากขึ้นครับ
- ความสอดคล้องกัน (Consistency): IaC ช่วยลด Human Error และทำให้มั่นใจว่าโครงสร้างพื้นฐานทั้งหมด ไม่ว่าจะเป็นสภาพแวดล้อม Dev, Staging หรือ Production จะถูกสร้างขึ้นมาในลักษณะที่เหมือนกันทุกประการครับ
- ความเร็วในการจัดเตรียม (Speed and Rapid Provisioning): การสร้างโครงสร้างพื้นฐานใหม่หรือปรับเปลี่ยนที่มีอยู่สามารถทำได้อย่างรวดเร็วและอัตโนมัติ ช่วยลดเวลาและแรงงานที่ต้องใช้ในการตั้งค่าด้วยตนเอง
- การควบคุมเวอร์ชันและการติดตามการเปลี่ยนแปลง (Version Control and Traceability): โค้ด IaC สามารถถูกเก็บไว้ใน Git ทำให้สามารถติดตามการเปลี่ยนแปลง, ย้อนกลับไปเวอร์ชันก่อนหน้า, และทำงานร่วมกันในทีมได้อย่างมีประสิทธิภาพครับ ใครแก้ไขอะไร เมื่อไหร่ สามารถตรวจสอบได้ทั้งหมด
- ลดต้นทุน (Cost Reduction): การลดข้อผิดพลาด, การทำให้กระบวนการเป็นอัตโนมัติ, และการจัดการทรัพยากรอย่างมีประสิทธิภาพ ช่วยลดต้นทุนการดำเนินงานในระยะยาวครับ
- ลดความเสี่ยง (Risk Mitigation): การทดสอบและทำซ้ำโครงสร้างพื้นฐานในสภาพแวดล้อมที่เหมือนจริงช่วยลดความเสี่ยงที่จะเกิดปัญหากับ Production ได้ครับ
- การทำซ้ำได้ (Reproducibility): คุณสามารถสร้างโครงสร้างพื้นฐานทั้งหมดขึ้นมาใหม่ได้ทุกเมื่อจากโค้ด ทำให้ง่ายต่อการกู้คืนระบบจากภัยพิบัติ (Disaster Recovery) หรือการสร้างสภาพแวดล้อมสำหรับทดสอบใหม่ ๆ ครับ
1.3. IaC กับการจัดการ Cloud
ในโลกของ Cloud Computing ที่ทรัพยากรสามารถถูกสร้าง, ปรับขนาด, และทำลายได้อย่างรวดเร็ว IaC ยิ่งทวีความสำคัญมากขึ้นครับ คลาวด์แพลตฟอร์มอย่าง AWS มี API ที่แข็งแกร่ง ทำให้เครื่องมือ IaC สามารถโต้ตอบและจัดการทรัพยากรได้อย่างราบรื่น IaC จึงเป็นกุญแจสำคัญในการปลดล็อกศักยภาพสูงสุดของ Cloud และช่วยให้องค์กรสามารถนำแนวคิด DevOps มาปรับใช้ได้อย่างเต็มรูปแบบครับ
2. Terraform คืออะไร?
2.1. แนะนำ HashiCorp Terraform
Terraform เป็นเครื่องมือ Infrastructure as Code (IaC) แบบ Open-source ที่พัฒนาโดย HashiCorp ครับ มันถูกออกแบบมาเพื่อช่วยให้คุณสามารถกำหนด (Define) และจัดเตรียม (Provision) โครงสร้างพื้นฐานของคลาวด์และ On-premise ได้อย่างปลอดภัยและมีประสิทธิภาพ โค้ด Terraform เขียนด้วยภาษา HCL (HashiCorp Configuration Language) ซึ่งเป็นภาษาที่อ่านง่ายและมีความยืดหยุ่นสูงครับ
หนึ่งในจุดเด่นที่สำคัญของ Terraform คือความสามารถในการจัดการโครงสร้างพื้นฐานได้หลากหลายแพลตฟอร์ม (Multi-Cloud) ไม่ว่าจะเป็น AWS, Azure, Google Cloud Platform (GCP), Alibaba Cloud, VMware, หรือแม้แต่ Kubernetes และ SaaS ต่าง ๆ ครับ ทำให้เป็นเครื่องมือที่ทรงพลังสำหรับองค์กรที่มีการใช้งานหลายคลาวด์ หรือต้องการความยืดหยุ่นในการเลือกใช้เทคโนโลยี
2.2. หลักการทำงานของ Terraform
Terraform ทำงานบนหลักการ Declarative ที่เราได้กล่าวถึงไปแล้ว โดยมีส่วนประกอบและขั้นตอนการทำงานหลัก ๆ ดังนี้ครับ
- Providers: Terraform ใช้ “Providers” เพื่อโต้ตอบกับ API ของแพลตฟอร์มต่าง ๆ ครับ เช่น
awsprovider จะจัดการทรัพยากร AWS,azurermสำหรับ Azure, หรือgoogleสำหรับ GCP Provider เหล่านี้รู้ว่าทรัพยากรแต่ละชนิดบนแพลตฟอร์มนั้น ๆ มีคุณสมบัติอะไรบ้างและจะสร้างหรือแก้ไขได้อย่างไร - Resources: ในไฟล์ Terraform เราจะกำหนด “Resources” ซึ่งเป็นส่วนประกอบของโครงสร้างพื้นฐานที่เราต้องการสร้างครับ เช่น
aws_instance(EC2),aws_vpc(Virtual Private Cloud),aws_s3_bucket(S3 Storage) เป็นต้น - State File: Terraform จะเก็บสถานะของโครงสร้างพื้นฐานที่มันได้สร้างขึ้นไว้ในไฟล์ที่เรียกว่า “Terraform State File” (โดยทั่วไปคือ
terraform.tfstate) ไฟล์นี้ทำหน้าที่เป็นตัวจับคู่ระหว่างทรัพยากรในโค้ด Terraform กับทรัพยากรจริง ๆ ที่อยู่บนคลาวด์ครับ การมี State File ทำให้ Terraform สามารถรู้ได้ว่าทรัพยากรใดถูกสร้างแล้ว, คุณสมบัติเป็นอย่างไร, และการเปลี่ยนแปลงในโค้ดจะส่งผลกระทบต่อทรัพยากรใดบ้าง - Execution Plan: เมื่อคุณรันคำสั่ง
terraform planTerraform จะเปรียบเทียบโค้ดที่คุณเขียนกับสถานะปัจจุบันของโครงสร้างพื้นฐาน (จาก State File และ API ของ Provider) และสร้าง “Execution Plan” ที่แสดงให้เห็นว่า Terraform จะต้องสร้าง, แก้ไข, หรือลบทรัพยากรใดบ้างเพื่อให้โครงสร้างพื้นฐานมีสถานะตามที่คุณต้องการครับ - Apply: หลังจากตรวจสอบ Execution Plan แล้ว หากคุณยืนยันด้วยคำสั่ง
terraform applyTerraform ก็จะดำเนินการตามแผนนั้นเพื่อปรับใช้โครงสร้างพื้นฐานจริง ๆ บนคลาวด์ครับ
2.3. Terraform กับ Cloud Platforms
Terraform มีความสามารถในการทำงานร่วมกับ Cloud Platforms ได้อย่างยอดเยี่ยมครับ โดยเฉพาะกับ AWS ซึ่งเป็นหนึ่งใน Providers ที่ได้รับความนิยมและมีการพัฒนาอย่างต่อเนื่อง ความสามารถในการกำหนดทรัพยากรจากหลาย Cloud ในไฟล์เดียวกันทำให้ Terraform เป็นเครื่องมือที่เหมาะสมอย่างยิ่งสำหรับกลยุทธ์ Multi-cloud ของหลาย ๆ องค์กรครับ
3. ทำไมต้อง Terraform บน AWS?
AWS มีเครื่องมือ IaC ของตัวเองอยู่แล้วคือ AWS CloudFormation แล้วทำไมเราถึงควรพิจารณาใช้ Terraform บน AWS ล่ะครับ? มาดูข้อดีและเปรียบเทียบกันครับ
3.1. ข้อดีของการใช้ Terraform ร่วมกับ AWS
- ความยืดหยุ่นแบบ Multi-Cloud: นี่คือข้อได้เปรียบที่ใหญ่ที่สุดครับ หากองค์กรของคุณมีการใช้งานหลายคลาวด์ (เช่น AWS สำหรับ Production, Azure สำหรับ Dev/Test) หรือมีแผนที่จะทำในอนาคต Terraform ช่วยให้คุณสามารถใช้ภาษาและเวิร์กโฟลว์เดียวกันในการจัดการโครงสร้างพื้นฐานบนคลาวด์ต่าง ๆ ได้อย่างราบรื่น ไม่ต้องเรียนรู้เครื่องมือเฉพาะของแต่ละคลาวด์ครับ
- AWS Provider ที่ครอบคลุมและอัปเดตอย่างรวดเร็ว: HashiCorp พัฒนา AWS Provider อย่างต่อเนื่องเพื่อให้รองรับบริการและคุณสมบัติใหม่ ๆ ของ AWS ได้อย่างรวดเร็วและครอบคลุม ทำให้คุณสามารถใช้ Terraform จัดการทรัพยากร AWS ได้เกือบทุกประเภทครับ
- State Management ที่ยืดหยุ่น: Terraform State File มีความสำคัญมาก และ Terraform มีความยืดหยุ่นในการจัดการ State ครับ คุณสามารถเก็บ State ได้ในหลากหลาย Backends เช่น S3, Azure Blob Storage, Google Cloud Storage, Terraform Cloud/Enterprise ซึ่งช่วยในการทำงานร่วมกันเป็นทีมและเพิ่มความปลอดภัย
- Modularity และ Reusability: Terraform มีแนวคิดของ “Modules” ที่ช่วยให้คุณสามารถสร้างบล็อกโครงสร้างพื้นฐานที่นำกลับมาใช้ใหม่ได้ (Reusable Modules) เช่น สร้าง VPC Module, EC2 Module ที่สามารถปรับแต่งได้ ทำให้โค้ดของคุณเป็นระเบียบ อ่านง่าย และนำไปใช้ซ้ำกับโปรเจกต์อื่น ๆ ได้อย่างง่ายดายครับ
- Execution Plan ที่โปร่งใส: คำสั่ง
terraform planช่วยให้คุณเห็นภาพรวมของการเปลี่ยนแปลงที่จะเกิดขึ้นอย่างชัดเจน ก่อนที่จะทำการ Apply จริง ๆ ซึ่งช่วยลดความผิดพลาดและเพิ่มความมั่นใจในการปรับใช้ครับ - เครื่องมือและ Ecosystem ที่แข็งแกร่ง: Terraform มี Ecosystem ที่ใหญ่โต มีเครื่องมือเสริมมากมาย (เช่น Terragrunt, TFLint) และชุมชนผู้ใช้งานที่แข็งแกร่ง ช่วยให้การเรียนรู้และแก้ไขปัญหาเป็นไปได้ง่ายครับ
3.2. เปรียบเทียบ Terraform กับ AWS CloudFormation
เพื่อช่วยให้เห็นภาพชัดเจนขึ้น มาดูตารางเปรียบเทียบระหว่าง Terraform กับ AWS CloudFormation กันครับ
| คุณสมบัติ | Terraform | AWS CloudFormation |
|---|---|---|
| แพลตฟอร์มที่รองรับ | Multi-Cloud (AWS, Azure, GCP, VMware, Kubernetes, SaaS, etc.) | AWS เท่านั้น |
| ภาษาที่ใช้ | HCL (HashiCorp Configuration Language) | YAML หรือ JSON |
| State Management | จัดการ State File ภายใน (Local) หรือ External Backend (S3, GCS, Azure Blob, Terraform Cloud) | จัดการ State ภายใน AWS (Stack) |
| การนำกลับมาใช้ใหม่ (Reusability) | Modules ที่ยืดหยุ่นและนำกลับมาใช้ใหม่ได้ง่ายในหลายโปรเจกต์และหลายคลาวด์ | Nested Stacks และ Macros (สำหรับบางกรณี) แต่โดยรวมยืดหยุ่นน้อยกว่า |
| การตรวจสอบการเปลี่ยนแปลง | terraform plan แสดงการเปลี่ยนแปลงทั้งหมดอย่างชัดเจน |
Change Sets แสดงการเปลี่ยนแปลง (บางครั้งอาจไม่ละเอียดเท่า Terraform) |
| การจัดการนอก AWS | สามารถจัดการทรัพยากรนอก AWS ได้ (เช่น DNS, Monitoring Tools) | จัดการทรัพยากร AWS และบางบริการของบุคคลที่สามผ่าน Custom Resources |
| การเรียนรู้ | HCL เรียนรู้ง่าย แต่ต้องเข้าใจแนวคิดของ Providers และ State | YAML/JSON มาตรฐาน แต่ต้องเข้าใจโครงสร้างของ CloudFormation และ Resource Types ของ AWS |
| การ Rollback | ทำได้ด้วยการย้อนกลับโค้ดและ terraform apply หรือ terraform destroy |
สามารถ Rollback Stack ได้อัตโนมัติหากมีการปรับใช้ไม่สำเร็จ |
สรุปคือ หากคุณต้องการโซลูชัน IaC ที่เป็นมาตรฐานอุตสาหกรรม, มีความยืดหยุ่นสูง, รองรับ Multi-Cloud, และมี Ecosystem ที่แข็งแกร่ง Terraform คือตัวเลือกที่ยอดเยี่ยมครับ อ่านเพิ่มเติมเกี่ยวกับ CloudFormation หากคุณสนใจเครื่องมือ IaC ของ AWS โดยเฉพาะ
4. เริ่มต้นใช้งาน Terraform สำหรับ AWS
ได้เวลาลงมือปฏิบัติจริงกันแล้วครับ เราจะมาดูขั้นตอนพื้นฐานในการติดตั้ง Terraform และเตรียมพร้อมสำหรับการจัดการ AWS Infrastructure กันครับ
4.1. การติดตั้ง Terraform
Terraform เป็นโปรแกรม Single Binary ที่ติดตั้งง่ายมากครับ คุณสามารถดาวน์โหลดได้จากเว็บไซต์ทางการของ HashiCorp
- ไปที่ Terraform Downloads Page
- เลือกเวอร์ชันที่เหมาะสมกับระบบปฏิบัติการของคุณ (Windows, macOS, Linux)
- ดาวน์โหลดไฟล์ Zip และแตกไฟล์
- ย้ายไฟล์
terraform(หรือterraform.exeสำหรับ Windows) ไปยัง Directory ที่อยู่ใน PATH ของระบบของคุณ เช่น/usr/local/binบน Linux/macOS หรือในโฟลเดอร์ที่ถูกเพิ่มใน Path ของ Windows - ตรวจสอบการติดตั้งโดยเปิด Terminal/Command Prompt แล้วพิมพ์:
terraform --versionคุณควรเห็นเวอร์ชันของ Terraform ที่ติดตั้งไว้ครับ
4.2. การตั้งค่า AWS Credentials
เพื่อให้ Terraform สามารถโต้ตอบกับบัญชี AWS ของคุณได้ คุณจะต้องตั้งค่าข้อมูลรับรอง (Credentials) ครับ มีหลายวิธีในการทำเช่นนี้ แต่ที่นิยมและแนะนำคือ:
- AWS CLI Configuration:
หากคุณติดตั้ง AWS CLI อยู่แล้ว สามารถตั้งค่าได้ง่าย ๆ ครับ
aws configureจากนั้นป้อน
AWS Access Key ID,AWS Secret Access Key,Default region name(เช่นap-southeast-1สำหรับสิงคโปร์) และDefault output format(เช่นjson) ครับ Terraform จะอ่านข้อมูลจากไฟล์~/.aws/credentialsและ~/.aws/configโดยอัตโนมัติ - Environment Variables:
คุณสามารถตั้งค่า Key และ Secret ผ่าน Environment Variables ได้ แต่ไม่แนะนำสำหรับการใช้งานจริงใน Production เพราะอาจมีความเสี่ยงด้านความปลอดภัยครับ
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY" export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY" export AWS_DEFAULT_REGION="ap-southeast-1" - IAM Roles for EC2 Instances:
หากคุณรัน Terraform บน EC2 Instance ควรใช้ IAM Role ที่กำหนดสิทธิ์ที่จำเป็นให้กับ Instance นั้น ๆ ครับ นี่คือวิธีที่ปลอดภัยที่สุด
4.3. โครงสร้างโปรเจกต์ Terraform เบื้องต้น
โดยทั่วไปโปรเจกต์ Terraform จะจัดเรียงเป็นไฟล์ .tf หลายไฟล์ เพื่อให้ง่ายต่อการจัดการและอ่านครับ
main.tf: ไฟล์หลักที่เก็บ Resource definitions ส่วนใหญ่variables.tf: ไฟล์สำหรับประกาศ Input Variablesoutputs.tf: ไฟล์สำหรับประกาศ Output Valuesversions.tf(หรือproviders.tf): ไฟล์สำหรับกำหนดเวอร์ชันของ Terraform และ Providers
ตัวอย่างโครงสร้าง:
my-aws-infra/
├── main.tf
├── variables.tf
├── outputs.tf
└── versions.tf
5. สร้าง Infrastructure แรกบน AWS ด้วย Terraform
มาสร้างทรัพยากร AWS จริง ๆ ด้วย Terraform กันครับ เราจะเริ่มต้นด้วยทรัพยากรพื้นฐานที่สำคัญ
5.1. ตัวอย่างที่ 1: สร้าง VPC และ Subnet
Virtual Private Cloud (VPC) คือเครือข่ายเสมือนของคุณบน AWS ที่คุณสามารถกำหนดค่าได้เองครับ เราจะสร้าง VPC หนึ่งอันและ Public Subnet หนึ่งอัน
สร้างไฟล์ main.tf:
# versions.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # กำหนดเวอร์ชันของ AWS Provider
}
}
required_version = "~> 1.0" # กำหนดเวอร์ชันของ Terraform CLI
}
# กำหนด AWS Provider และ Region
provider "aws" {
region = "ap-southeast-1" # Region ที่ต้องการสร้างทรัพยากร
}
# สร้าง VPC
resource "aws_vpc" "my_vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "my-terraform-vpc"
Environment = "Development"
}
}
# สร้าง Internet Gateway สำหรับ VPC
resource "aws_internet_gateway" "my_igw" {
vpc_id = aws_vpc.my_vpc.id
tags = {
Name = "my-terraform-igw"
}
}
# สร้าง Public Subnet
resource "aws_subnet" "my_public_subnet" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-southeast-1a" # เลือก Availability Zone ที่เหมาะสม
map_public_ip_on_launch = true # ทำให้ EC2 ใน Subnet นี้ได้รับ Public IP อัตโนมัติ
tags = {
Name = "my-terraform-public-subnet"
}
}
# สร้าง Route Table สำหรับ Public Subnet
resource "aws_route_table" "my_public_rt" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0" # Traffic ทั้งหมดออกทาง Internet Gateway
gateway_id = aws_internet_gateway.my_igw.id
}
tags = {
Name = "my-terraform-public-rt"
}
}
# เชื่อม Route Table กับ Public Subnet
resource "aws_route_table_association" "my_public_rt_association" {
subnet_id = aws_subnet.my_public_subnet.id
route_table_id = aws_route_table.my_public_rt.id
}
คำอธิบายโค้ด:
terraform {}: บล็อกสำหรับกำหนดเวอร์ชันของ Terraform และ Providers ที่จำเป็นprovider "aws" {}: บล็อกสำหรับกำหนดค่า Provider ของ AWS รวมถึง Region ที่ต้องการใช้งานresource "aws_vpc" "my_vpc" {}: สร้าง VPC โดยใช้cidr_blockเป็น10.0.0.0/16และเปิดใช้งาน DNS hostnames/supportresource "aws_internet_gateway" "my_igw" {}: สร้าง Internet Gateway และผูกกับ VPC ที่สร้างไว้resource "aws_subnet" "my_public_subnet" {}: สร้าง Subnet ภายใน VPC ที่มีcidr_blockเป็น10.0.1.0/24และกำหนด Availability Zonemap_public_ip_on_launch = true: สำคัญสำหรับ Public Subnet เพื่อให้ EC2 ที่สร้างใน Subnet นี้ได้รับ Public IP โดยอัตโนมัติresource "aws_route_table" "my_public_rt" {}: สร้าง Route Table และกำหนด Route สำหรับ Internet Gatewayresource "aws_route_table_association" "my_public_rt_association" {}: ผูก Route Table เข้ากับ Public Subnettags = {}: ใช้สำหรับติด Tag ให้กับทรัพยากร เพื่อการจัดการและการติดตามที่ดีขึ้นครับ
ขั้นตอนการรัน:
- เปิด Terminal ในโฟลเดอร์ที่มีไฟล์
main.tf -
terraform initคำสั่งนี้จะดาวน์โหลด AWS Provider ที่จำเป็นและเตรียม Working Directory ครับ
-
terraform planคำสั่งนี้จะแสดง Execution Plan ที่บอกว่า Terraform จะสร้างทรัพยากรอะไรบ้าง (ในกรณีนี้คือ 6 อย่าง: VPC, Subnet, IGW, Route Table, Route Table Association)
-
terraform applyคำสั่งนี้จะปรับใช้โครงสร้างพื้นฐานจริง ๆ บน AWS ครับ Terraform จะขอให้คุณยืนยันด้วยการพิมพ์
yes
หลังจาก terraform apply สำเร็จ คุณสามารถเข้าไปตรวจสอบใน AWS Console ได้ว่า VPC, Subnet, Internet Gateway และ Route Table ได้ถูกสร้างขึ้นแล้วครับ
5.2. ตัวอย่างที่ 2: สร้าง EC2 Instance และ Security Group
ตอนนี้เรามี VPC และ Subnet แล้ว เรามาลองสร้าง EC2 Instance และ Security Group เพื่ออนุญาตการเข้าถึง SSH กันครับ
เพิ่มโค้ดด้านล่างลงในไฟล์ main.tf เดิมของคุณ (หรือจะแยกเป็นไฟล์ ec2.tf ก็ได้ครับ)
# สร้าง Security Group สำหรับ SSH และ HTTP
resource "aws_security_group" "web_sg" {
name = "web-server-sg"
description = "Allow SSH and HTTP inbound traffic"
vpc_id = aws_vpc.my_vpc.id
ingress {
description = "Allow SSH from anywhere"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # เปิดให้ SSH ได้จากทุกที่ (ไม่แนะนำใน Production)
}
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 หมายถึงทุก Protocol
cidr_blocks = ["0.0.0.0/0"] # อนุญาตการเข้าถึงขาออกทั้งหมด
}
tags = {
Name = "web-server-security-group"
}
}
# ค้นหา AMI ID ล่าสุดสำหรับ Ubuntu Server
data "aws_ami" "ubuntu_latest" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# สร้าง EC2 Instance
resource "aws_instance" "web_server" {
ami = data.aws_ami.ubuntu_latest.id # ใช้ AMI ID ที่ค้นหามา
instance_type = "t2.micro"
subnet_id = aws_subnet.my_public_subnet.id
security_groups = [aws_security_group.web_sg.id] # ผูกกับ Security Group ที่สร้างไว้
key_name = "your-ssh-key-name" # ต้องมี SSH Key คู่ที่สร้างไว้ใน AWS
tags = {
Name = "my-web-server"
Project = "Terraform-Demo"
}
}
# แสดง Public IP ของ EC2 Instance เป็น Output
output "web_server_public_ip" {
description = "The public IP address of the web server"
value = aws_instance.web_server.public_ip
}
คำอธิบายโค้ด:
resource "aws_security_group" "web_sg" {}: สร้าง Security Group ที่อนุญาตให้ SSH (Port 22) และ HTTP (Port 80) เข้าถึงจากทุกที่ (0.0.0.0/0) และอนุญาตการเข้าถึงขาออกทั้งหมดdata "aws_ami" "ubuntu_latest" {}: นี่คือ Data Source ครับ มันจะไป “ค้นหา” AMI ID ล่าสุดของ Ubuntu 22.04 LTS จาก AWS แทนที่เราจะต้องระบุ ID แบบ Hardcode ซึ่งอาจจะเก่าไปในอนาคต ทำให้โค้ดมีความยืดหยุ่นมากขึ้นครับresource "aws_instance" "web_server" {}: สร้าง EC2 Instance โดยใช้ AMI ID ที่ได้จาก Data Source, กำหนดinstance_typeเป็นt2.micro, ผูกกับ Public Subnet, และ Security Group ที่สร้างไว้key_name = "your-ssh-key-name": สำคัญมาก! คุณต้องเปลี่ยน"your-ssh-key-name"เป็นชื่อของ Key Pair ที่คุณสร้างไว้ใน AWS Console เพื่อให้สามารถ SSH เข้าถึง Instance ได้ครับoutput "web_server_public_ip" {}: เป็น Output Value ที่จะแสดง Public IP ของ EC2 Instance หลังจากterraform applyสำเร็จ ทำให้เราสามารถนำค่านี้ไปใช้งานต่อได้ครับ
ขั้นตอนการรัน:
- ตรวจสอบให้แน่ใจว่าคุณได้เปลี่ยน
"your-ssh-key-name"เป็นชื่อ Key Pair ที่ถูกต้องแล้ว -
terraform planตรวจสอบแผนการเปลี่ยนแปลงที่จะเกิดขึ้น (ควรมีการสร้าง Security Group, EC2 Instance, และ Output)
-
terraform applyยืนยันการสร้างทรัพยากรด้วย
yes
หลังจาก apply เสร็จ คุณจะเห็น Public IP ของ EC2 Instance แสดงขึ้นมาใน Terminal ครับ คุณสามารถใช้ IP นี้เพื่อ SSH เข้าสู่ Instance ได้ทันที
5.3. ตัวอย่างที่ 3: จัดการ S3 Bucket
Amazon S3 (Simple Storage Service) เป็นบริการจัดเก็บ Object Storage ที่ได้รับความนิยมอย่างมากครับ มาลองสร้าง S3 Bucket ด้วย Terraform กัน
เพิ่มโค้ดด้านล่างลงในไฟล์ main.tf (หรือ s3.tf)
# สร้าง S3 Bucket
resource "aws_s3_bucket" "my_website_bucket" {
bucket = "my-unique-static-website-bucket-123456789" # ต้องเป็นชื่อ Bucket ที่ไม่ซ้ำกันทั่วโลก
tags = {
Name = "MyStaticWebsiteBucket"
Environment = "Development"
}
}
# ปิดกั้นการเข้าถึง Public ทั้งหมดสำหรับ S3 Bucket
resource "aws_s3_bucket_public_access_block" "my_website_bucket_public_access_block" {
bucket = aws_s3_bucket.my_website_bucket.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# กำหนด Ownership Controls สำหรับ S3 Bucket (บังคับใช้ Object Ownership)
resource "aws_s3_bucket_ownership_controls" "my_website_bucket_ownership_controls" {
bucket = aws_s3_bucket.my_website_bucket.id
rule {
object_ownership = "BucketOwnerPreferred" # หรือ "BucketOwnerEnforced"
}
}
# กำหนด Policy สำหรับ S3 Bucket (ตัวอย่าง: อนุญาตให้ Object เป็น Public อ่านได้)
# ข้อควรระวัง: การเปิด Public Access อาจมีผลด้านความปลอดภัย ควรทำด้วยความเข้าใจ
resource "aws_s3_bucket_policy" "my_website_bucket_policy" {
bucket = aws_s3_bucket.my_website_bucket.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Sid = "PublicReadGetObject",
Effect = "Allow",
Principal = "*",
Action = "s3:GetObject",
Resource = "${aws_s3_bucket.my_website_bucket.arn}/*"
}
]
})
# ต้องยกเลิก block_public_acls และ block_public_policy ใน aws_s3_bucket_public_access_block
# หากต้องการให้ Policy นี้มีผลสำหรับการเข้าถึงแบบ Public
# และต้องตั้งค่า object_ownership = "ObjectWriter" หรือ "BucketOwnerPreferred"
}
# กำหนด Bucket เป็น Static Website Hosting (ถ้าต้องการ)
resource "aws_s3_bucket_website_configuration" "my_website_bucket_website_configuration" {
bucket = aws_s3_bucket.my_website_bucket.id
index_document {
suffix = "index.html"
}
error_document {
key = "error.html"
}
}
output "s3_website_endpoint" {
description = "The S3 static website endpoint"
value = aws_s3_bucket_website_configuration.my_website_bucket_website_configuration.website_endpoint
}
คำอธิบายโค้ด:
resource "aws_s3_bucket" "my_website_bucket" {}: สร้าง S3 Bucket โดยกำหนดชื่อ Bucket ที่ต้องไม่ซ้ำกันทั่วโลกครับresource "aws_s3_bucket_public_access_block" {}: เป็น Best Practice ด้านความปลอดภัยที่สำคัญมาก โดยค่าเริ่มต้นจะ Block Public Access ทั้งหมด หากคุณต้องการเปิด Bucket ให้เป็น Static Website Hosting คุณอาจจะต้องปรับเปลี่ยนค่าเหล่านี้อย่างระมัดระวังครับresource "aws_s3_bucket_ownership_controls" {}: กำหนดการควบคุมความเป็นเจ้าของ Object ใน Bucket เพื่อเสริมความปลอดภัยresource "aws_s3_bucket_policy" {}: กำหนด Policy ให้กับ Bucket ในตัวอย่างนี้คือการอนุญาตให้ทุกคนสามารถอ่าน Object ใน Bucket ได้ (s3:GetObject) ซึ่งจำเป็นสำหรับการทำ Static Website Hosting ครับ โปรดระมัดระวังในการใช้งานและทำความเข้าใจผลกระทบด้านความปลอดภัยresource "aws_s3_bucket_website_configuration" {}: กำหนด Bucket ให้เป็น Static Website Hosting โดยระบุไฟล์index_documentและerror_documentoutput "s3_website_endpoint" {}: แสดง Endpoint ของ Static Website หลังจาก Apply สำเร็จ
ขั้นตอนการรัน:
- สำคัญ: เปลี่ยนชื่อ Bucket
"my-unique-static-website-bucket-123456789"ให้เป็นชื่อที่ไม่ซ้ำกันทั่วโลกครับ - หากคุณต้องการให้ S3 Bucket ทำงานเป็น Static Website ได้จริง ๆ คุณอาจจะต้อง คอมเมนต์ (Comment out) บล็อก
aws_s3_bucket_public_access_blockหรือปรับค่าให้เหมาะสมกับการอนุญาต Public Access ครับ (แต่โปรดระวังเรื่องความปลอดภัย) -
terraform plan -
terraform apply
คุณจะเห็น S3 Bucket พร้อมการตั้งค่าที่ระบุถูกสร้างขึ้น และหากคุณเปิด Static Website Hosting ไว้ ก็จะมี Endpoint แสดงใน Output ครับ
คำเตือนด้านความปลอดภัย: การอนุญาตให้ Public Access กับ EC2 Instance (เปิด Port 22/80 จาก 0.0.0.0/0) และ S3 Bucket (Public Read) ในตัวอย่างข้างต้น เป็นเพียงเพื่อสาธิตเท่านั้นครับ ในสภาพแวดล้อม Production ควรจำกัดการเข้าถึงให้แคบที่สุดเท่าที่จะเป็นไปได้ เช่น กำหนด IP Source ที่เฉพาะเจาะจง หรือใช้ Private Subnet/VPC Endpoint ครับ
6. คุณสมบัติและแนวคิดขั้นสูงของ Terraform
เมื่อคุณคุ้นเคยกับพื้นฐานแล้ว มาสำรวจคุณสมบัติขั้นสูงของ Terraform ที่จะช่วยให้การจัดการ Infrastructure มีประสิทธิภาพและยืดหยุ่นมากยิ่งขึ้นครับ
6.1. Modules
Modules คือการรวมกลุ่มทรัพยากร Terraform เข้าด้วยกันในรูปแบบที่สามารถนำกลับมาใช้ใหม่ได้ครับ Imagine ว่าคุณมีโค้ด Terraform สำหรับสร้าง VPC, Subnets, Internet Gateway, และ Route Tables ที่ใช้บ่อย ๆ แทนที่จะคัดลอกโค้ดชุดนี้ซ้ำ ๆ คุณสามารถรวมทั้งหมดนี้เป็น “VPC Module” แล้วนำไปเรียกใช้ในโปรเจกต์ต่าง ๆ ได้ครับ
ประโยชน์ของ Modules:
- การนำกลับมาใช้ใหม่ (Reusability): ลดการเขียนโค้ดซ้ำ และส่งเสริมการใช้ Best Practices
- ความสอดคล้องกัน (Consistency): มั่นใจได้ว่าทุกทีมใช้โครงสร้างพื้นฐานที่มีมาตรฐานเดียวกัน
- การจัดระเบียบ (Organization): ทำให้โปรเจกต์ขนาดใหญ่เป็นระเบียบและจัดการได้ง่ายขึ้น
- ลดความซับซ้อน (Abstraction): ผู้ใช้ Module ไม่จำเป็นต้องรู้รายละเอียดภายในของ Module นั้น ๆ แค่รู้ Input/Output ก็พอ
การสร้างและใช้งาน Custom Modules:
สมมติว่าคุณต้องการสร้าง VPC Module:
modules/
├── vpc/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── ec2-webserver/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
main.tf # ไฟล์ root module ที่เรียกใช้ modules อื่นๆ
modules/vpc/main.tf (คล้ายกับตัวอย่าง VPC ด้านบน):
# modules/vpc/main.tf
resource "aws_vpc" "this" {
cidr_block = var.vpc_cidr_block
# ... ทรัพยากรอื่นๆ ที่เกี่ยวข้องกับ VPC
tags = var.tags
}
resource "aws_subnet" "public" {
count = length(var.public_subnet_cidrs)
vpc_id = aws_vpc.this.id
cidr_block = var.public_subnet_cidrs[count.index]
availability_zone = "${var.aws_region}${element(split("", "abcdefghijklmnopqrstuvwxyz"), count.index)}"
map_public_ip_on_launch = true
tags = merge(var.tags, { Name = "public-subnet-${count.index}" })
}
# ... Internet Gateway, Route Tables ฯลฯ
modules/vpc/variables.tf:
# modules/vpc/variables.tf
variable "vpc_cidr_block" {
description = "CIDR block for the VPC"
type = string
}
variable "public_subnet_cidrs" {
description = "List of CIDR blocks for public subnets"
type = list(string)
}
variable "aws_region" {
description = "AWS region"
type = string
}
variable "tags" {
description = "A map of tags to add to all 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 "public_subnet_ids" {
description = "IDs of the public subnets"
value = aws_subnet.public[*].id
}
การใช้งาน Module ใน Root Module (main.tf):
# main.tf
provider "aws" {
region = "ap-southeast-1"
}
module "my_network" {
source = "./modules/vpc" # อ้างอิงไปยัง path ของ module
vpc_cidr_block = "10.0.0.0/16"
public_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24"]
aws_region = "ap-southeast-1"
tags = {
Project = "Terraform-Demo-Module"
Environment = "Dev"
}
}
resource "aws_instance" "web_server_via_module" {
ami = "ami-0abcdef1234567890" # แทนด้วย AMI ID จริง
instance_type = "t2.micro"
subnet_id = module.my_network.public_subnet_ids[0] # ใช้ Output จาก module
# ...
}
นอกจากนี้ยังมี Public Modules จำนวนมากบน Terraform Registry ที่คุณสามารถนำมาใช้ได้ทันทีครับ
6.2. Variables และ Outputs
เราได้เห็นการใช้งาน Variables และ Outputs มาบ้างแล้วในตัวอย่างก่อนหน้านี้ครับ
- Variables (Input Variables): ช่วยให้คุณสามารถกำหนดค่าที่สามารถเปลี่ยนแปลงได้ในโค้ด Terraform โดยไม่ต้องแก้ไขโค้ดโดยตรง ทำให้โค้ดมีความยืดหยุ่นและนำไปใช้ซ้ำได้ง่ายขึ้นครับ เช่น
instance_type,region,tagsคุณสามารถกำหนดค่าให้กับ Variables ได้หลายวิธี:- ไฟล์
terraform.tfvarsหรือ.tfvars.json - ไฟล์
*.auto.tfvars - Environment Variables (
TF_VAR_name) - Command Line (
-var="name=value")
ตัวอย่างใน
variables.tf:variable "instance_type" { description = "The EC2 instance type" type = string default = "t2.micro" } variable "region" { description = "AWS region" type = string default = "ap-southeast-1" }และใช้งานใน
main.tf:provider "aws" { region = var.region } resource "aws_instance" "example" { instance_type = var.instance_type # ... } - ไฟล์
- Outputs (Output Values): ใช้เพื่อแสดงข้อมูลสำคัญเกี่ยวกับโครงสร้างพื้นฐานที่ถูกสร้างขึ้นหลังจาก
terraform applyสำเร็จครับ ข้อมูลเหล่านี้สามารถเป็น Public IP, DNS Name, ARN ของ Bucket หรือ ID ของทรัพยากรอื่น ๆ และยังสามารถนำไปใช้เป็น Input ให้กับ Terraform Configuration อื่น ๆ ได้อีกด้วยครับ
ตัวอย่างใน outputs.tf:
output "ec2_public_ip" {
description = "The public IP address of the EC2 instance"
value = aws_instance.example.public_ip
}
6.3. Terraform State Management
Terraform State File (terraform.tfstate) เป็นหัวใจสำคัญของ Terraform ครับ
- ความสำคัญ: State File ทำหน้าที่เป็นสะพานเชื่อมระหว่างโค้ด Terraform ของคุณกับทรัพยากรจริง ๆ บนคลาวด์ มันบันทึกว่า Terraform ได้สร้างทรัพยากรอะไรไปแล้วบ้างและมีคุณสมบัติอย่างไร เพื่อให้ Terraform สามารถวางแผนการเปลี่ยนแปลงได้อย่างถูกต้องในครั้งถัดไป
- ความท้าทาย:
- การทำงานร่วมกัน: หากหลายคนทำงานบนโค้ดเดียวกันพร้อมกัน อาจเกิด “State Lock” หรือ “State Corruption” ได้
- ความปลอดภัย: State File อาจมีข้อมูลที่ละเอียดอ่อน (แม้จะไม่ใช่ Secret โดยตรง) ต้องเก็บไว้ในที่ปลอดภัย
- ขนาด: State File อาจมีขนาดใหญ่ขึ้นเรื่อย ๆ ตามจำนวนทรัพยากร
- Remote State: เพื่อแก้ปัญหาเหล่านี้ Terraform แนะนำให้ใช้ “Remote State” ซึ่งเก็บ State File ไว้ในบริการจัดเก็บข้อมูลระยะไกลที่รองรับการ Locking และ Versioning ครับ
สำหรับ AWS นิยมใช้ S3 Bucket ในการเก็บ State File และ DynamoDB Table สำหรับการทำ State Locking
ตัวอย่างการตั้งค่า Remote State ในไฟล์
versions.tfหรือbackend.tf:terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } required_version = "~> 1.0" backend "s3" { bucket = "my-terraform-state-bucket-12345" # ต้องไม่ซ้ำกัน key = "dev/my-app/terraform.tfstate" # Path ภายใน Bucket region = "ap-southeast-1" encrypt = true # เข้ารหัส State File dynamodb_table = "my-terraform-state-lock" # DynamoDB Table สำหรับ Lock } }ขั้นตอนการตั้งค่า Remote State:
- สร้าง S3 Bucket (ต้องเปิด Versioning) และ DynamoDB Table (ใช้ Partition Key ชื่อ
LockIDเป็น String) ด้วยมือหรือด้วย Terraform แยกต่างหาก - ใส่โค้ด
backend "s3" {}ในไฟล์ Terraform ของคุณ - รัน
terraform initเพื่อย้าย Local State ไปยัง Remote State ครับ
- สร้าง S3 Bucket (ต้องเปิด Versioning) และ DynamoDB Table (ใช้ Partition Key ชื่อ
6.4. Workspaces
Terraform Workspaces ช่วยให้คุณสามารถจัดการโครงสร้างพื้นฐานที่แยกจากกันแต่ใช้โค้ดเดียวกันได้ครับ เหมาะสำหรับการจัดการสภาพแวดล้อมที่แตกต่างกัน เช่น Development, Staging, Production
terraform workspace new dev # สร้าง Workspace ใหม่ชื่อ dev
terraform workspace select dev # สลับไปใช้ Workspace dev
terraform apply # จะใช้ State File ของ dev
terraform workspace new prod # สร้าง Workspace ใหม่ชื่อ prod
terraform workspace select prod # สลับไปใช้ Workspace prod
terraform apply # จะใช้ State File ของ prod
แต่ละ Workspace จะมี State File ของตัวเอง (เมื่อใช้ Remote State, มันจะสร้าง Key แยกกัน เช่น dev/my-app/terraform.tfstate และ prod/my-app/terraform.tfstate) ทำให้คุณสามารถรันโค้ดเดียวกันแต่ปรับใช้กับสภาพแวดล้อมที่แตกต่างกันได้โดยการส่งค่า Variable ที่แตกต่างกันไปครับ
6.5. Data Sources
Data Sources ช่วยให้ Terraform สามารถ “อ่าน” ข้อมูลจากทรัพยากรที่มีอยู่แล้วบนคลาวด์ หรือข้อมูลจาก Provider ครับ เราได้เห็นตัวอย่าง data "aws_ami" "ubuntu_latest" {} ไปแล้วในส่วนการสร้าง EC2
ประโยชน์ของ Data Sources คือ:
- การอ้างอิงทรัพยากรที่ไม่ได้ถูกสร้างด้วย Terraform
- การดึงข้อมูลที่เปลี่ยนแปลงบ่อย (เช่น AMI ID ล่าสุด)
- การเชื่อมโยงทรัพยากรระหว่าง Terraform Configurations ที่แตกต่างกัน
ตัวอย่าง Data Source ที่เป็นประโยชน์อื่น ๆ:
# ดึงข้อมูล Availability Zones ทั้งหมดใน Region
data "aws_availability_zones" "available" {
state = "available"
}
# ดึงข้อมูล S3 Bucket ที่มีอยู่แล้ว
data "aws_s3_bucket" "existing_bucket" {
bucket = "my-pre-existing-bucket"
}
output "existing_bucket_arn" {
value = data.aws_s3_bucket.existing_bucket.arn
}
6.6. Provisioners (แนะนำให้ใช้อย่างระมัดระวัง)
Provisioners ใช้สำหรับรันสคริปต์หรือคำสั่งบนเครื่อง Local หรือบน Remote Instance (เช่น EC2) หลังจากที่ทรัพยากรถูกสร้างขึ้นหรือก่อนที่จะถูกทำลายครับ
local-exec: รันคำสั่งบนเครื่องที่รัน Terraformremote-exec: รันคำสั่งบน Remote Instance (เช่น SSH เข้าไปรันสคริปต์บน EC2)
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t2.micro"
# ...
provisioner "remote-exec" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx",
"sudo systemctl start nginx"
]
}
connection {
type = "ssh"
user = "ubuntu"
private_key = file("~/.ssh/your-key.pem")
host = self.public_ip
}
}
ข้อควรระวัง: Provisioners ไม่ได้เป็นส่วนหนึ่งของ State File และอาจไม่ Idempotent ครับ โดยทั่วไปแล้ว การใช้ Configuration Management Tools เช่น Ansible, Chef, Puppet, หรือ User Data Script ใน EC2 Instance จะเป็นแนวทางที่ดีกว่าสำหรับการตั้งค่าภายใน Instance ครับ ควรใช้ Provisioners เฉพาะในกรณีที่จำเป็นจริง ๆ เท่านั้น
7. แนวปฏิบัติที่ดีที่สุด (Best Practices) ในการใช้ Terraform บน AWS
การใช้ Terraform อย่างมีประสิทธิภาพและปลอดภัยจำเป็นต้องมีแนวทางปฏิบัติที่ดีครับ
7.1. การจัดโครงสร้างโปรเจกต์
การจัดโครงสร้างโปรเจกต์ที่ดีช่วยให้โค้ดของคุณเป็นระเบียบและจัดการได้ง่าย:
- แยกตาม Environment: สร้างโฟลเดอร์แยกสำหรับแต่ละสภาพแวดล้อม (
dev,staging,prod) - แยกตามบริการ/Module: แบ่งโค้ดออกเป็น Modules เล็ก ๆ ที่จัดการทรัพยากรที่เกี่ยวข้องกัน (เช่น
vpc,ec2-app,rds) - Root Module: มี Root Module ที่เรียกใช้ Modules อื่น ๆ เพื่อสร้าง Infrastructure ที่สมบูรณ์
.
├── environments/
│ ├── dev/
│ │ └── main.tf
│ └── prod/
│ └── main.tf
└── modules/
├── vpc/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── ec2-webserver/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── rds/
├── main.tf
├── variables.tf
└── outputs.tf
7.2. การจัดการ Secret
ไม่ควร Hardcode หรือเก็บ Sensitive Data (เช่น รหัสผ่าน, API Keys) ไว้ในไฟล์ Terraform โดยตรงครับ ควรใช้เครื่องมือจัดการ Secret โดยเฉพาะ:
- AWS Secrets Manager: บริการของ AWS เองที่ใช้เก็บ จัดการ และหมุนเวียน Secret
- HashiCorp Vault: โซลูชัน Open-source ที่แข็งแกร่งสำหรับการจัดการ Secret
- Environment Variables: ใช้สำหรับ Non-sensitive data หรือในสภาพแวดล้อม Dev เท่านั้น
- KMS (Key Management Service): ใช้สำหรับเข้ารหัสข้อมูลที่เก็บใน State File หรือในไฟล์
.tfvars
ตัวอย่างการดึง Secret จาก AWS Secrets Manager ด้วย Data Source:
data "aws_secretsmanager_secret" "db_credentials" {
name = "my/database/credentials"
}
data "aws_secretsmanager_secret_version" "db_credentials_version" {
secret_id = data.aws_secretsmanager_secret.db_credentials.id
}
resource "aws_rds_cluster" "main" {
# ...
master_password = jsondecode(data.aws_secretsmanager_secret_version.db_credentials_version.secret_string)["password"]
# ...
}
7.3. การใช้ Git สำหรับ Version Control
เก็บโค้ด Terraform ของคุณไว้ใน Git Repository เสมอครับ เพื่อ:
- ติดตามการเปลี่ยนแปลง
- ทำงานร่วมกันในทีม
- ย้อนกลับไปยังเวอร์ชันก่อนหน้า
- ใช้ Git Flow (Feature Branches, Pull Requests)
7.4. การทำ Code Review
ก่อนที่จะ Merge โค้ด Terraform เข้าสู่ Main Branch ควรมีการทำ Code Review โดยเพื่อนร่วมทีมครับ เพื่อตรวจสอบ:
- ความถูกต้องของโค้ด
- การปฏิบัติตาม Best Practices
- ผลกระทบที่อาจเกิดขึ้นต่อ Infrastructure
- ความปลอดภัย
7.5. การทดสอบ Terraform Code
การทดสอบโค้ด IaC มีความสำคัญไม่แพ้โค้ดแอปพลิเคชัน:
- Static Analysis: ใช้เครื่องมือเช่น TFLint หรือ Checkov เพื่อตรวจสอบ Syntax, Best Practices, และ Security Issues
- Unit/Integration Tests: ใช้เครื่องมือเช่น Terratest (Go-based) หรือ Kitchen-Terraform (Ruby-based) เพื่อสร้าง Infrastructure ชั่วคราว, ทดสอบ, และทำลายทิ้ง
- Validation: ใช้
terraform validateเพื่อตรวจสอบ Syntax และ Configuration
7.6. การพิจารณาใช้ Terragrunt
Terragrunt เป็น Wrapper รอบ Terraform ที่ช่วยในการจัดการโค้ด Terraform ที่ซับซ้อน โดยเฉพาะอย่างยิ่งในโปรเจกต์ขนาดใหญ่ที่มีหลาย Environments และ Modules ครับ Terragrunt ช่วยเรื่อง:
- การจัดการ Remote State และ Backend Configuration ซ้ำ ๆ
- การกำหนดค่า Input Variables ที่แตกต่างกันในแต่ละ Environment
- การทำงานกับ Module dependencies
8. Terraform Lifecycle และคำสั่งพื้นฐาน
การจัดการโครงสร้างพื้นฐานด้วย Terraform จะวนเวียนอยู่กับคำสั่งพื้นฐานเหล่านี้ครับ
-
terraform initInitialization: เป็นคำสั่งแรกที่คุณต้องรันใน Directory ที่มีไฟล์ Terraform ครับ มันจะดาวน์โหลด Provider plugins ที่จำเป็น, กำหนดค่า Backend สำหรับ State File, และเตรียม Working Directory ให้พร้อม
-
terraform planPlanning: สร้าง “Execution Plan” ที่แสดงให้เห็นว่า Terraform จะต้องสร้าง, แก้ไข, หรือลบทรัพยากรใดบ้างเพื่อให้โครงสร้างพื้นฐานมีสถานะตามที่คุณต้องการ มันเป็นสิ่งสำคัญในการตรวจสอบการเปลี่ยนแปลงก่อนที่จะ Apply จริง ๆ ครับ
-
terraform applyApplying: ดำเนินการตาม Execution Plan ที่สร้างขึ้นจาก
terraform planเพื่อปรับใช้โครงสร้างพื้นฐานจริง ๆ บนคลาวด์ คุณจะต้องพิมพ์yesเพื่อยืนยันการดำเนินการครับ -
terraform destroyDestroying: ลบทรัพยากรทั้งหมดที่ถูกจัดการโดย Terraform Configuration ปัจจุบันครับ ใช้ด้วยความระมัดระวังเป็นอย่างยิ่ง! Terraform จะขอให้คุณยืนยันด้วยการพิมพ์
yes -
terraform fmtFormatting: จัดรูปแบบโค้ด Terraform ของคุณให้เป็นมาตรฐาน (Canonical Format) เพื่อความสอดคล้องและอ่านง่ายขึ้นครับ
-
terraform validateValidating: ตรวจสอบ Syntax และ Configuration ของไฟล์ Terraform เพื่อหาข้อผิดพลาดก่อนที่จะรัน
planหรือapplyครับ -
terraform stateState Management: คำสั่งย่อยสำหรับจัดการ State File โดยตรง เช่น
terraform state list,terraform state show,terraform state rm(ใช้ด้วยความระมัดระวัง) -
<