Terraform Infrastructure as Code สำหรับ Cloud AWS

ในโลกของการพัฒนาซอฟต์แวร์และการจัดการโครงสร้างพื้นฐานยุคใหม่ การสร้างและดูแลสภาพแวดล้อมคลาวด์แบบ Manual เป็นเรื่องที่ทั้งเสียเวลา เกิดข้อผิดพลาดได้ง่าย และยังไม่สามารถขยายขนาดได้อย่างรวดเร็วครับ แต่ไม่ต้องกังวลไปครับ! วันนี้ SiamLancard.com จะพาคุณดำดิ่งสู่โลกของ Infrastructure as Code (IaC) ด้วยเครื่องมืออันทรงพลังอย่าง Terraform เพื่อพลิกโฉมการจัดการ Cloud AWS ของคุณให้เป็นไปโดยอัตโนมัติ มีประสิทธิภาพ และทำซ้ำได้ บทความนี้จะเจาะลึกทุกแง่มุมของการใช้ 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 คำสั่งหลักๆ ดังนี้ครับ

  1. terraform init:

    คำสั่งนี้ใช้สำหรับเริ่มต้นไดเรกทอรีการทำงานของ Terraform ครับ มันจะดาวน์โหลด Provider ที่จำเป็นทั้งหมดตามที่ระบุไว้ใน Configuration ของคุณ รวมถึงตั้งค่า Backend สำหรับ State Management ด้วยครับ คุณต้องรันคำสั่งนี้เสมอเมื่อเริ่มต้นโปรเจกต์ใหม่ หรือเมื่อมีการเพิ่ม/เปลี่ยนแปลง Provider หรือ Module ครับ

  2. terraform plan:

    นี่คือคำสั่งที่สำคัญที่สุดคำสั่งหนึ่งครับ terraform plan จะวิเคราะห์ Configuration ของคุณ เปรียบเทียบกับ State File และสถานะปัจจุบันของโครงสร้างพื้นฐานใน Cloud AWS จริงๆ (ถ้ามี) จากนั้นจะสร้าง "Execution Plan" ขึ้นมา ซึ่งจะแสดงให้คุณเห็นอย่างละเอียดว่า Terraform จะทำอะไรบ้าง เช่น จะสร้าง (+), แก้ไข (~), หรือลบ (-) Resource ใดบ้างครับ การตรวจสอบ Plan อย่างละเอียดช่วยป้องกันการเปลี่ยนแปลงที่ไม่คาดคิดได้เป็นอย่างดีครับ

  3. terraform apply:

    เมื่อคุณตรวจสอบ Execution Plan แล้วและพอใจกับสิ่งที่จะเกิดขึ้น ก็ถึงเวลาใช้คำสั่ง terraform apply ครับ คำสั่งนี้จะดำเนินการตามแผนที่ Terraform สร้างไว้จริง โดยจะเรียก API ของ AWS เพื่อสร้าง แก้ไข หรือลบ Resource ต่างๆ ตาม Configuration ของคุณครับ หลังจากที่ Terraform ทำงานเสร็จ มันจะอัปเดต State File ให้เป็นปัจจุบันครับ

  4. terraform destroy:

    คำสั่งนี้ใช้สำหรับลบ Resource ทั้งหมดที่ถูกสร้างขึ้นโดย Configuration ของ Terraform ในไดเรกทอรีนั้นๆ ครับ ควรใช้ด้วยความระมัดระวังอย่างยิ่ง โดยเฉพาะในสภาพแวดล้อม Production เพราะมันจะลบทุกอย่างที่ Terraform รู้จักใน State File ออกไปครับ เช่นเดียวกับ apply, คุณจะต้องยืนยันก่อนการดำเนินการครับ

ติดตั้งและเริ่มต้นใช้งาน Terraform สำหรับ AWS ครับ

ตอนนี้เรามาลงมือติดตั้ง Terraform และเตรียมพร้อมสำหรับการสร้างโครงสร้างพื้นฐานบน AWS ด้วยโค้ดกันเลยครับ

การติดตั้ง Terraform

Terraform เป็น Single Binary ครับ การติดตั้งจึงค่อนข้างง่าย คุณสามารถดาวน์โหลดได้จากเว็บไซต์ทางการของ HashiCorp

ดาวน์โหลด Terraform

สำหรับ 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 ครับ มีหลายวิธีในการทำเช่นนี้:

  1. 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 โดยตรงครับ!

  2. 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
    
  3. 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:

  1. Initialize Terraform (ถ้ายังไม่ได้ทำ):
    terraform init
    
  2. สร้าง Execution Plan:
    terraform plan
    

    Terraform จะแสดงให้คุณเห็นว่ากำลังจะสร้าง S3 Bucket 1 ตัว และ Resource อื่นๆ ที่เกี่ยวข้อง คุณจะเห็น + หน้า Resource ที่จะถูกสร้างใหม่ครับ

  3. Apply Configuration:
    terraform apply
    

    Terraform จะขอให้คุณพิมพ์ 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 Instance
    • ami: ระบุ Amazon Machine Image (AMI) ที่ต้องการ (เช่น Ubuntu Server)
    • instance_type: กำหนดขนาดของ Instance (เช่น t2.micro)
    • subnet_id: กำหนด Subnet ที่ Instance จะถูก Deploy
    • security_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_document
  • aws_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 Instance
    • allocated_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 สุดท้ายเมื่อลบ Instance
    • publicly_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 User
  • aws_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 Check
  • aws_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 Group
    • vpc_zone_identifier: กำหนด Subnet ที่ ASG จะ Deploy Instance
    • desired_capacity, max_size, min_size: กำหนดจำนวน Instance ที่ต้องการ, สูงสุด, และต่ำสุด
    • health_check_type: ตั้งค่า Health Check โดยใช้ ELB (Load Balancer)
    • target_group_arns: ผูก ASG เข้ากับ Target Group ของ ALB
    • launch_template: อ้างอิง Launch Template ที่สร้างไว้
  • aws_autoscaling_policy: สร้าง Scaling Policy สำหรับการเพิ่มจำนวน Instance
  • aws_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:

  1. สร้าง S3 Bucket:

    สร้าง S3 Bucket ที่จะใช้เก็บ State File และควรเปิด Versioning ให้กับ Bucket นี้เพื่อป้องกันการสูญหายของ State File ครับ

    resource "aws_s3_bucket" "terraform_state_bucket" {
    bucket = "siamlancard-tf-state-bucket-unique" # ชื่อ bucket

จัดส่งรวดเร็วส่งด่วนทั่วประเทศ
รับประกันสินค้าเคลมง่าย มีใบรับประกัน
ผ่อนชำระได้บัตรเครดิต 0% สูงสุด 10 เดือน
สะสมแต้ม รับส่วนลดส่วนลดและคะแนนสะสม

© 2026 SiamLancard — จำหน่ายการ์ดแลน อุปกรณ์ Server และเครื่องพิมพ์ใบเสร็จ

SiamLancard
Logo
Free Forex EA Download — XM Signal · EA Forex ฟรี
iCafeForex.com - สอนเทรด Forex | SiamCafe.net
Shopping cart