Skip to content

บทที่ 6 — Cloud Platforms + IaC ​

← บทที่ 5 | สารบัญ | บทที่ 7 →

TL;DR: บทนี้ตอบ 2 คำถามหลัก — "เลือก cloud เจ้าไหน" และ "เขียนโครงสร้างพื้นฐานเป็นโค้ดยังไง"

  • เปรียบเทียบ AWS / GCP / Azure พร้อมหลักช่วยตัดสินใจ
  • รู้จักรูปแบบบริการ (IaaS → FaaS = ดูแลเองทั้งเครื่อง → ดูแลแค่ฟังก์ชัน)
  • ใช้ Terraform / OpenTofu ตั้งแต่ resource แรกจนถึง module
  • พื้นฐานเรื่องลดค่าใช้จ่ายและความปลอดภัย

ข้ามได้ถ้า: ใช้ Terraform คล่อง + รู้ข้อดี-ข้อเสียของ cloud แต่ละเจ้าแล้ว

หลังจบบท คุณจะ:

  • เปรียบเทียบ AWS / GCP / Azure / others — เลือกได้มีเหตุผล ไม่ใช่ตาม trend
  • เลือก service ตาม use case (มี decision rubric ให้)
  • ใช้ Terraform / OpenTofu เขียน infrastructure
  • เข้าใจ cost optimization
  • รู้ pattern ของ cloud architecture

📖 เส้นทางอ่านแนะนำ (บท 6 ยาว 1500+ บรรทัด)

🟢 เส้นทางเริ่มต้น (อ่านก่อน): 0 → 1 → 2 → 3 → 7 (Heroku/Render) → 8 (Free Tier) → 10 (Terraform Basics) → 27 (Checkpoint)

🟡 หลังจับหลักได้แล้ว: 4 (Core Services) → 5 (AWS CLI) → 9 (IaC) → 11–13 (Variables/Outputs/Modules) → 20 (Cost) → 21 (Security)

🔴 ขั้นสูง (ข้ามได้ก่อน): 14 (Full Stack Example) → 15–16 (Best Practices/Patterns) → 23 (Multi-Cloud) → 25 (Real-World Cost)


0. Prerequisites + Decision Framework ​

คุณควรรู้:

  • ✅ Linux + SSH (บทที่ 1)
  • ✅ Docker (บทที่ 3) — เพราะ deploy ส่วนใหญ่เป็น container
  • ❌ ไม่ต้องเคยมี cloud account — เริ่ม free tier ในบทนี้

ก่อนเลือก cloud — ถามตัวเอง 4 ข้อ ​

text
1. ทีมรู้ stack อะไรอยู่แล้ว?
   → ถ้าทีมใช้เทคโนโลยี Microsoft เป็นหลัก (.NET, Windows Server, AD)
       → Azure (เชื่อมต่อกันได้ดีกว่า)
   → ถ้าใช้ Google Workspace + งาน ML/Data → GCP

2. Project ขนาดไหน?
   → MVP / side project → Render, Railway, Fly.io ($5-25/เดือน)
   → Startup กำลังโต → ใช้ cloud หลักเจ้าเดียว (AWS/GCP)
   → Enterprise → ต้องคิดเรื่อง multi-region + compliance ด้วย

3. คุณ deploy แบบไหน?
   → Function/API → Lambda, Cloud Run (ถูกสุด, scale ลงเหลือ 0 ได้)
   → Container → ECS Fargate, Cloud Run (ไม่ต้องจัดการเครื่อง node เอง)
   → Kubernetes → EKS/GKE/AKS (ถ้ามีคนคอยดูแล cluster)

4. งบประมาณเท่าไหร่?
   → < $50/เดือน → DigitalOcean, Hetzner, Vercel free tier
   → $50-500/เดือน → AWS/GCP free tier + เครื่องเล็ก
   → $500+/เดือน → เริ่มจริงจังเรื่อง optimization (Reserved/Savings Plan)

1. Why Cloud ​

ก่อนจะเลือก cloud เจ้าไหน ต้องเข้าใจก่อนว่าทำไมโลกถึงย้ายจาก "ซื้อเซิร์ฟเวอร์ตั้งเอง" (on-premise) มาเป็น cloud หัวใจมี 4 ข้อ:

  • จ่ายตามใช้จริง
  • สร้างได้ในไม่กี่นาที
  • scale อัตโนมัติ
  • มี managed service (บริการที่ cloud ดูแลระบบหลังบ้านให้ เช่น patch, backup, scaling — เราไม่ต้องดูแลเอง) ให้ใช้

ลองเทียบสองโลกนี้:

text
On-premise (ซื้อเซิร์ฟเวอร์ตั้งเอง):    Cloud:
- ซื้อเซิร์ฟเวอร์ ($$$)               - จ่ายตามใช้จริง
- ตั้ง datacenter เอง                  - สร้างได้ในไม่กี่นาที
- scale ต้องทำมือ                       - scale อัตโนมัติ
- ต้องมีทีม IT ดูแล                     - มี managed service ให้
- ความจุตายตัว                          - ยืดหดได้ (elastic)

ปี 2026 — 95% startup ใช้ cloud


2. Big 3 + Others ​

ตลาด cloud มีเจ้าใหญ่ 3 ราย (AWS, GCP, Azure) ที่ครองส่วนแบ่งส่วนใหญ่ แต่ละเจ้าเด่นคนละด้าน บวกกับผู้เล่นเล็กที่เรียบง่าย/ถูกกว่าสำหรับงานบางแบบ (DigitalOcean, Hetzner, Vercel, Fly.io) มารู้จักจุดแข็งของแต่ละเจ้าเพื่อเลือกให้เหมาะกับงาน:

AWS (Amazon Web Services) ⭐ ผู้นำตลาด ​

  • มีบริการเยอะที่สุด (200+ services)
  • เอกสารเยอะที่สุด, ชุมชนใหญ่ที่สุด
  • navigate ยาก (เมนูเยอะ, ชื่อบริการเยอะ)

GCP (Google Cloud Platform) ​

  • เหมาะกับงาน data / ML ที่สุด
  • Kubernetes (GKE) ทำได้ดีที่สุด — Google คือคนสร้าง K8s
  • เป็นมิตรกับนักพัฒนา (developer-friendly)

Azure (Microsoft) ​

  • เหมาะกับ enterprise ที่ใช้ Windows / .NET
  • Identity แข็งแรง (AAD = Azure Active Directory — ระบบจัดการ user/สิทธิ์ขององค์กร)
  • เชื่อมกับ Office 365 / Microsoft 365 ได้ดี

Others ​

  • DigitalOcean — เรียบง่าย + ราคาถูก (เน้นนักพัฒนา)
  • Hetzner — ถูกที่สุด (เซิร์ฟเวอร์อยู่ในเยอรมัน, เหมาะกับ EU)
  • Linode (Akamai) — VPS แบบง่าย ๆ
  • Vercel — hosting สำหรับเว็บฝั่ง frontend
  • Render / Railway — แนวเดียวกับ Heroku, deploy ง่าย
  • Fly.io — deploy แบบ edge (กระจายไปหลายเมืองทั่วโลก)
  • Cloudflare — CDN + Workers (รันโค้ดที่ edge)

3. Cloud Service Models ​

cloud ให้บริการหลาย "ระดับ" ตามว่าคุณอยากดูแลเองแค่ไหน — IaaS (จัดการ OS+app เอง), PaaS (จัดการแค่ app), SaaS (ใช้บริการสำเร็จรูป), FaaS (อัปแค่ฟังก์ชัน) ยิ่งลงล่างยิ่งสบายแต่ยืดหยุ่นน้อยลง

อุปมา "pizza as a service" ช่วยให้เห็นภาพว่าแต่ละ model ดูแลอะไรเอง/ปล่อยให้ cloud จัดการ:

ทำพิซซ่ากินเอง (On-premise)ซื้อแป้ง+ส่วนผสมสำเร็จ (IaaS)สั่ง Delivery มาบ้าน (PaaS)ไปกินที่ร้าน (SaaS)
คุณดูแลทุกอย่าง — แป้ง, เตา, เสิร์ฟapp + OS (เช่าแค่ VM)แค่ app ของคุณเองแค่ใช้งาน
cloud ดูแล—hardware + networkhardware + OS + runtimeทุกอย่าง
ตัวอย่างServer ในออฟฟิศEC2, Compute EngineApp Engine, HerokuGmail, Notion

ลองดูสเปกตรัมนี้:

text
On-premise (ตั้งเอง):  ดูแลทุกอย่างเอง
        ↓
IaaS:         ดูแล app + OS (เช่าแค่ VM)         ← EC2, Compute Engine
        ↓
PaaS:         ดูแลแค่ app                        ← App Engine, Heroku
        ↓
SaaS:         ใช้บริการสำเร็จรูป                  ← Gmail, Notion
        ↓
Function/FaaS: อัปโหลดแค่ฟังก์ชัน                 ← Lambda, Cloud Functions

4. Core Services (AWS focus) ​

cloud แต่ละเจ้ามีบริการเป็นร้อย แต่จริง ๆ แล้วจัดกลุ่มได้ไม่กี่หมวด: compute (รันโค้ด), storage (เก็บไฟล์), database, network, identity/security และ messaging ตารางเทียบนี้ช่วยให้เห็นว่าบริการชื่อต่างกันของ AWS/GCP/Azure จริง ๆ คือของแบบเดียวกัน — รู้หมวดเดียวก็ย้าย cloud ได้

💡 คำย่อที่จะเจอบ่อยในตารางข้างล่าง

  • EC2 (Elastic Compute Cloud) = เครื่อง VM ของ AWS
  • ECS (Elastic Container Service) = service รัน Docker container ของ AWS (AWS เป็นคนจัดการ)
  • EKS (Elastic Kubernetes Service) = บริการ Kubernetes managed ของ AWS
  • GKE / AKS = ฝั่ง GCP / Azure ของ EKS
  • EBS (Elastic Block Store) = ดิสก์ผูกติด VM (เหมือน SSD ในเครื่อง)
  • EFS (Elastic File System) = ที่เก็บไฟล์ที่ mount แชร์หลายเครื่องได้
  • S3 (Simple Storage Service) = ที่เก็บไฟล์แบบ object (รูป, video, backup)
  • VPC (Virtual Private Cloud) = network ส่วนตัวของคุณใน cloud (เหมือน LAN ออฟฟิศ แต่อยู่บน cloud)
  • ALB / NLB = Application / Network Load Balancer — กระจาย traffic เข้าหลายเครื่อง (ALB เข้าใจ HTTP, NLB เร็วระดับ TCP)
  • KMS (Key Management Service) = ที่เก็บกุญแจเข้ารหัส
  • CDN (Content Delivery Network) = เครือข่าย cache เนื้อหาตามจุดต่าง ๆ ใกล้ผู้ใช้

Compute (รันโค้ด/แอปพลิเคชัน) ​

AWSGCPAzure
VM (เครื่องเสมือน)EC2Compute EngineVM
ContainerECS, EKSGKE, Cloud RunAKS, Container Apps
Serverless (ฟังก์ชัน)LambdaCloud Functions, Cloud RunFunctions
Static (เว็บนิ่ง)S3 + CloudFrontCloud Storage + CDNBlob + CDN

💡 2026 มาแรง: ARM Graviton (ของ AWS) — CPU แบบ ARM ของ AWS ราคาถูกกว่า x86 ราว 20-40% (instance ลงท้าย g เช่น t4g, m7g, c7g). EKS Auto Mode (เปิด 2024) — AWS ดูแลเรื่อง node ให้หมด, ใช้ Karpenter (CNCF graduated — ผ่านมาตรฐานความสำเร็จระดับสูงสุดของ Cloud Native Computing Foundation จึงเชื่อถือได้ว่าโปรเจกต์เสถียร) ขยาย node ตามภาระงานอัตโนมัติ

Storage (เก็บข้อมูล/ไฟล์) ​

AWSGCPAzure
Object storage (ไฟล์รวม metadata)S3Cloud StorageBlob
Block (ดิสก์ผูก VM)EBSPersistent DiskManaged Disk
File (mount แชร์ระหว่างเครื่อง)EFSFilestoreFiles
Archive (เก็บนาน, ดึงช้า, ถูกมาก)GlacierColdlineArchive

Database ​

AWSGCPAzureคำอธิบาย
Relational (SQL)RDS, AuroraCloud SQL, SpannerSQL DBDB แบบ SQL ปกติ — RDS/Cloud SQL = MySQL/Postgres managed; Aurora/Spanner = engine เร็วขึ้น/scale ได้ดีขึ้น
NoSQLDynamoDBFirestore, BigtableCosmos DBkey-value / document DB ที่ scale ใหญ่มาก ๆ ได้
CacheElastiCacheMemorystoreCache for RedisRedis/Memcached managed สำหรับ cache ในแอป
SearchOpenSearch(managed Elasticsearch)SearchElasticsearch managed สำหรับค้นหา full-text
Data Warehouse (analytics)RedshiftBigQuery ⭐Synapseฐานข้อมูลขนาดใหญ่สำหรับ analytics + BI

Network ​

AWSGCPAzureคำอธิบาย
Virtual NetworkVPCVPCVNetเครือข่ายส่วนตัวของคุณบน cloud (กั้นแยกจากคนอื่น)
Load BalancerALB / NLBCloud Load BalancingLBกระจาย traffic เข้าหลายเครื่อง (ALB ฝั่ง AWS เป็น HTTP, NLB เป็น TCP; Classic ELB เลิกใช้สำหรับโปรเจกต์ใหม่)
DNSRoute 53Cloud DNSDNSระบบจำเส้นทางจากชื่อเว็บไป IP
CDNCloudFrontCloud CDNCDNcache เนื้อหาที่ edge ใกล้ผู้ใช้ทั่วโลก

Identity + Security ​

AWSGCPAzureคำอธิบาย
IAM (ระบบสิทธิ์)IAMIAMAAD (Azure AD / Entra ID)กำหนดว่า user/service ทำอะไรได้บ้าง
Secrets (เก็บความลับ)Secrets ManagerSecret ManagerKey Vaultเก็บ password / API key / cert
KMS (Key Management Service)KMSCloud KMSKey Vaultจัดเก็บ + หมุนกุญแจเข้ารหัส

💡 เพิ่มเติม 2026 (AWS): GuardDuty = ระบบตรวจจับภัยอัตโนมัติจาก log; Security Hub = dashboard รวม finding ความปลอดภัย; IAM Access Analyzer = หา policy ที่เปิดสิทธิ์เกินจำเป็น; AWS Config = ตรวจสอบ config drift; Trusted Advisor = check best practices

Messaging (ส่งข้อความระหว่างระบบ) ​

AWSGCPAzureคำอธิบาย
QueueSQSCloud Tasks, Pub/SubQueue Storageคิวข้อความแบบเข้าก่อนออกก่อน
Pub/SubSNSPub/SubEvent Gridกระจายข้อความให้ subscriber หลายตัว
StreamKinesisPub/Sub, DataflowEvent Hubsสตรีมข้อมูลความเร็วสูง (เช่น log, IoT)

5. AWS Common Services — Brief ​

💡 AWS CLI Setup ใน 5 นาที (ถ้าจะลอง command ในข้อนี้):

Prerequisite: ต้องมี AWS account แล้ว (ผูกบัตรเครดิต + verify ตัวตนทาง SMS / โทรกลับ ตอนสมัคร — ใช้เวลาประมาณ 10-15 นาที)

สำคัญ: ตั้ง billing alert ที่ $10 ทันทีหลังเปิด account เพื่อไม่ให้ค่าใช้จ่ายระเบิด

bash
# 1. ติดตั้ง AWS CLI v2
# macOS:   brew install awscli
# Linux:   ทำตามคู่มืออัปเดตที่ https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
# Windows: winget install Amazon.AWSCLI

# 2. ⭐ แนะนำสำหรับปี 2026: ใช้ IAM Identity Center (SSO) แทน access key
#    aws configure sso  → login ผ่าน browser, credential หมดอายุอัตโนมัติ
#    AWS เลิกแนะนำ static access key สำหรับมนุษย์ใช้งานตั้งแต่ปี 2023
#
#    ถ้าจำเป็นต้องใช้ access key (เช่นในระบบ CI ที่ตั้ง SSO ไม่ได้):
#    IAM → Users → Security credentials → Create access key
#    ⚠️ ห้ามใช้ root account — สร้าง IAM user แยกที่มีสิทธิ์น้อยที่สุดที่จำเป็น

# 3. ตั้งค่า credential
aws configure
#   AWS Access Key ID:     AKIA...
#   AWS Secret Access Key: ...
#   Default region name:   ap-southeast-1   (Singapore — region ที่ใกล้ไทยสุดและใช้งานได้แน่นอน)
#                          ⚠️ AWS อาจเปิด region ใหม่ในไทย/ใกล้ไทยเพิ่มในอนาคต —
#                             เช็ค region code ล่าสุดที่ https://aws.amazon.com/about-aws/global-infrastructure/regions_az/
#                             ก่อนใช้จริงเสมอ (อย่าเชื่อ region code ที่เห็นในหนังสือ/บทความเก่าเพียงอย่างเดียว)
#   Default output format: json

# 4. ทดสอบ
aws sts get-caller-identity
#   → คืนค่า account id + arn ของ user → พร้อมใช้

สรุปวิธีปลอดภัย (2026): SSO > IAM role (กรณีรันบน EC2/ECS) >> static access key (หลีกเลี่ยง)

EC2 (VM) ​

bash
# สั่งสร้างเครื่อง
aws ec2 run-instances \
    --image-id ami-xxx \         # AMI ID — ไปเลือกจาก AWS Console > EC2 > AMI Catalog (เช่น Ubuntu/Amazon Linux)
    --instance-type t3.micro \
    --key-name my-key \          # SSH key ที่สร้างไว้แล้วใน EC2 > Key Pairs
    --security-group-ids sg-xxx  # security group (firewall) ที่สร้างไว้แล้ว

Instance types — cloud แบ่งขนาด VM เป็น "ตระกูล" (family) ที่ optimize ให้เหมาะกับงานต่างกัน (เน้น CPU / เน้น RAM / สมดุลทั้งคู่) ถ้ายังไม่รู้จะเลือกอะไร เริ่มจาก general-purpose หรือ burstable ก่อนได้เลย ค่อยเปลี่ยนทีหลังเมื่อรู้ว่างานหนักด้านไหน (กลุ่มแรกที่ควรรู้):

  • t3.micro — แบบ burstable (ปกติ CPU ต่ำ แต่พุ่งแรงได้ชั่วครู่เวลามีงานเข้า เหมาะเว็บทั่วไปที่ traffic ไม่สม่ำเสมอ), ราคาถูก, อยู่ใน free tier
  • t3.medium — general purpose ใช้ทั่วไป
  • m5.large — balanced (CPU/RAM สมดุล) สำหรับ workload กลาง
  • c5.large — compute optimized (CPU แรง) เหมาะกับงานคำนวณ
  • r5.large — memory optimized (RAM เยอะ) เหมาะกับ in-memory cache / DB

💡 ARM Graviton — ถูกกว่า 20-40%: instance ลงท้าย g (เช่น t4g.micro, m7g.large, c7g.large, r7g.large) ใช้ CPU แบบ ARM ของ AWS เอง ราคาประหยัดกว่า x86 มาก ปี 2026 software ส่วนใหญ่ (Java, Node, Go, Python, Postgres, Redis, Nginx) รองรับ ARM แล้ว — default ใหม่ของโปรเจกต์ใหม่ควรเป็น Graviton

S3 (Object Storage) ​

bash
# อัปโหลด
aws s3 cp file.txt s3://my-bucket/
aws s3 sync ./folder s3://my-bucket/folder   # sync ทั้ง folder

# ดาวน์โหลด
aws s3 cp s3://my-bucket/file.txt .

# เปิดเป็นเว็บ (static website hosting)
aws s3 website s3://my-bucket --index-document index.html

⚠️ เรื่องสำคัญเรื่องเว็บ static บน S3

  1. ตั้งแต่เมษายน 2023 AWS เปิด S3 Block Public Access ให้ทุก bucket ใหม่โดยอัตโนมัติ — ถ้าจะ host เว็บ public ต้องไป ปิด Block Public Access แค่บาง bit ที่จำเป็น + เพิ่ม bucket policy ที่อนุญาตเฉพาะ s3:GetObject
  2. อย่าปิดทั้งหมด — เพราะจะกลายเป็น bucket เปิดทั้ง bucket (ข่าว data leak ส่วนใหญ่มาจากตรงนี้)
  3. ทางที่ปลอดภัยกว่า = วาง CloudFront ทับและให้ S3 bucket เป็น private โดย access ผ่าน Origin Access Control (OAC — กลไกให้ CloudFront เข้าถึง S3 private ได้โดยไม่ต้องเปิด public)

ใช้สำหรับ:

  • ที่เก็บไฟล์ user upload (รูป, video, attachment)
  • โฮสต์เว็บแบบ static (HTML/CSS/JS)
  • backup ข้อมูล
  • Data lake (ที่เก็บข้อมูลดิบสำหรับ analytics)

RDS (Managed Database) ​

text
RDS PostgreSQL:
  - Multi-AZ (กระจายข้าม availability zone) เพื่อ HA (high availability — ระบบไม่ล่มเวลา zone หนึ่งมีปัญหา)
  - Backup อัตโนมัติทุกวัน
  - เข้ารหัสตอนเก็บ (encryption at rest) — ต้องเปิดตอนสร้าง เปลี่ยนทีหลังไม่ได้
  - Read replica — สร้างสำเนาอ่านอย่างเดียวกระจายภาระ query
  - Failover อัตโนมัติ — สลับไป AZ สำรองเมื่อ primary ล่ม

💡 AZ (Availability Zone) = data center ย่อยภายใน region เดียวกัน แยกตัวอาคาร/ระบบไฟ/network เพื่อกัน fault — region หนึ่งมัก มี 3 AZ ขึ้นไป

💡 2026 ทางเลือกใหม่: Aurora Serverless v2 — Postgres/MySQL compatible ที่ scale CPU/RAM อัตโนมัติเป็นวินาที จ่ายตามใช้จริง เหมาะกับ workload ที่ traffic ไม่สม่ำเสมอ

→ จ่ายแพงกว่ารัน DB เองนิดหน่อย แต่ไม่ต้องดูแล backup / patch / failover เอง

Lambda (Serverless Function) ​

python
# lambda_function.py
def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': 'Hello'
    }
bash
# Deploy
zip function.zip lambda_function.py
aws lambda create-function \
    --function-name hello \
    --runtime python3.13 \                # ปี 2026 รองรับถึง 3.13 (เลือก runtime ใหม่ล่าสุดที่ stable)
    --architectures arm64 \               # ⭐ ARM Graviton — ถูกกว่า x86 ~20%
    --handler lambda_function.lambda_handler \
    --zip-file fileb://function.zip \
    --role arn:aws:iam::<account-id>:role/lambda-execution-role
    # ⚠️ --role ต้องใส่เสมอ — เป็น IAM role ที่ Lambda ใช้รันฟังก์ชัน (สร้างล่วงหน้าไว้ก่อน
    #   คล้าย pattern IAM role ในหัวข้อ 21 ด้านล่าง) ถ้าไม่ใส่ AWS จะ error ทันที

Pricing:

  • Free tier: 1M req/เดือน (ไม่หมดอายุ — always free)
  • $0.20 / 1M req + ค่า compute ตามเวลารัน

ใช้สำหรับ:

  • API endpoint (ผ่าน API Gateway / Function URL)
  • Event handler — เช่น มีไฟล์อัปขึ้น S3 → trigger ฟังก์ชันมา process
  • Scheduled task — งาน cron ที่รันตามเวลา
  • Webhook — รับ event จาก external service

CloudFront (CDN) ​

text
ผู้ใช้ → CloudFront edge → S3 / EC2 / ALB (Application Load Balancer)
        (cache ไว้, อยู่ใกล้ผู้ใช้)

→ กระจาย static asset ทั่วโลก + ป้องกัน DDoS เบื้องต้น


6. Choosing Compute Service ​

มีบริการ compute เยอะจนเลือกไม่ถูก? ใช้คำถามไล่ทีละขั้น — มี container ไหม? ต้องการ Kubernetes เต็มรูปแบบไหม? อยากคุม config มากแค่ไหน? — flowchart นี้พาคุณไปยังตัวเลือกที่เหมาะ พร้อมเทียบราคาคร่าว ๆ ของแต่ละแบบ:

Pricing (ราคาคร่าว ๆ — ถูก → แพง) ​

text
$$$$  EC2 + EKS (control plane) + เครื่องมือเสริม — แพงสุด, ต้องดูแล cluster
$$$   ECS, ALB, NLB (Application/Network Load Balancer)
$$    Cloud Run, Azure App Service
$     Lambda, Cloud Functions (จ่ายต่อ request)

7. Heroku / Render / Railway — Easiest Path ​

ถ้าเพิ่งเริ่มหรือทำโปรเจกต์เล็ก/MVP ไม่ต้องปวดหัวกับ AWS — platform แบบ Heroku/Render/Railway ซ่อนความซับซ้อนทั้งหมดไว้ แค่ต่อ GitHub หรือ push code มันก็ deploy ให้เลย ค่าใช้จ่ายไม่กี่ดอลลาร์ต่อเดือน เหมาะกับการเริ่มต้นที่สุด:

สำหรับโปรเจกต์เล็ก:

bash
# Heroku (เลิก free tier ตั้งแต่ พ.ย. 2022 — เริ่มที่ ~$5/เดือน)
heroku create my-app
git push heroku main
# deploy เสร็จเรียบร้อย

# Render
# วิธีใช้: เชื่อม GitHub repo → push code → deploy อัตโนมัติ

# Railway
railway up

ราคา: $5-25/เดือนสำหรับแอปเล็ก

→ เหมาะกับมือใหม่ + MVP (Minimum Viable Product = เวอร์ชันแรกที่ใช้ได้)


8. AWS Free Tier ​

ข่าวดีสำหรับคนอยากลองของจริงโดยไม่เสียเงิน — AWS มี free tier ให้ลองของจริงโดยไม่เสียเงินตอนเริ่ม ⚠️ ตั้ง billing alert เสมอ เพราะถ้าเผลอใช้เกินโควต้าจะโดนเก็บเงินทันที

⚠️ AWS เปลี่ยนโครงสร้าง Free Tier เดือนกรกฎาคม 2024 ​

มี 2 โครงสร้างที่ต่างกัน — เช็คก่อนว่าบัญชีตัวเองอยู่ที่ไหน:

บัญชีก่อน Jul 2024 ("Legacy Free Tier") — 12 months free + always-free:

  • 750 hr/month EC2 t2.micro / t3.micro
  • 5 GB S3
  • 750 hr RDS db.t2.micro / db.t3.micro
  • 1M Lambda req (always-free)
  • 100k SNS, 750 hr ELB
  • ใช้ใหม่ทุกบริการได้ทั้ง 12 เดือน

บัญชีหลัง Jul 2024 ("Free Plan") — แบ่ง 2 ขั้น:

  • 6 เดือนแรก: $200 credit (free + ใช้กับบริการอะไรก็ได้)
  • หลัง 6 เดือน: ต้อง upgrade เป็น paid account (จ่ายตามใช้จริงตามราคาปกติ) — ถ้าไม่ upgrade บัญชีจะถูกปิด
  • กลไกป้องกัน: ถ้า credit หมดก่อนครบ 6 เดือน บัญชีจะถูก "paused" อัตโนมัติ — resource ทั้งหมดถูกหยุดและจะถูกลบหลังผ่านไป 90 วันถ้าไม่ upgrade (จึงควร backup ของสำคัญไว้ก่อน)
  • ดู AWS Free Plan announcement

⚠️ ข้อมูล Free Tier อ้างอิงจากประกาศ AWS เดือนกรกฎาคม 2024 — ตรวจสอบ terms ล่าสุดที่ https://aws.amazon.com/free/ ก่อนเสมอ เพราะ AWS เปลี่ยน free tier บ่อยและรายละเอียดอาจแตกต่างตาม region หรือช่วงเวลา

→ ปัจจุบัน (ปี 2026) บัญชีใหม่ทั้งหมดเข้า Free Plan — ลองเล่นได้ 6 เดือนเต็มที่ ไม่ต้องกังวล bill ระเบิด

⚠️ ทั้งสองโครงสร้าง: ตั้ง billing alert ($10/$100/$1000) — กันความเข้าใจผิดเรื่อง quota


9. Infrastructure as Code (IaC) ​

การคลิกสร้าง resource ใน console ทีละอันมีปัญหาหลายอย่าง เช่น ทำซ้ำไม่ได้ ไม่มี version control และแต่ละ environment เพี้ยนกัน (drift)

IaC แก้ปัญหานี้ด้วยการเขียน infrastructure เป็น "โค้ด" — โค้ดนี้ Git เก็บประวัติได้ รันแล้วได้ผลเหมือนเดิมทุกครั้ง และทำลาย/สร้างใหม่ได้ ลองเทียบสองวิธี:

text
คลิกสร้างใน console (manual):
- ทำซ้ำไม่ได้ (ไม่รู้กดอะไรไปบ้าง)
- ไม่มี version control
- แต่ละ environment เพี้ยนกัน (drift)
- คนใหม่ onboarding ลำบาก ต้องสอนปากต่อปาก

IaC (Terraform ฯลฯ):
- โค้ดคือ source of truth (แหล่งความจริงเดียว)
- เก็บประวัติใน Git ได้
- โค้ดเดียวกัน → infra เหมือนเดิมทุกครั้ง
- ทำลายและสร้างใหม่ได้ (disposable + recreatable)

9.5 Terraform vs OpenTofu — เรื่องที่ต้องรู้ปี 2026 ​

สิงหาคม 2023 — HashiCorp เปลี่ยน license ของ Terraform จาก open source (MPL) เป็น BSL (Business Source License) → ห้าม vendor อื่นเอาไปทำเป็น product แข่ง

💡 MPL (Mozilla Public License) = license แบบ open source ที่ให้ใช้/แก้/ขายต่อได้ค่อนข้างเสรี ส่วน BSL เข้มกว่า — ใช้ฟรีได้แต่ห้ามเอาไปทำบริการแข่งกับเจ้าของ

ผลที่เกิด: community fork ออกมาเป็น OpenTofu (อยู่ใต้ Linux Foundation, license MPL เดิม) — release v1.7 stable เดือนพฤษภาคม 2024, ตามด้วย v1.8 (สิงหาคม 2024), v1.9 (ม.ค. 2025), v1.10+ (เพิ่ม S3 native locking)

💡 HCL (HashiCorp Configuration Language) = ภาษาที่ใช้เขียน Terraform — มี syntax คล้าย JSON ผสม INI อ่านง่าย

TerraformOpenTofu
License (สัญญาอนุญาต)BSL (จำกัดการนำไปใช้เชิงพาณิชย์)MPL (open source แท้ ใช้ฟรี)
ความเข้ากันได้—ใช้แทน Terraform ได้ทันที (binary drop-in)
HCL syntaxเหมือนกันเหมือนกัน (อิง HCL v1.5)
State formatเหมือนกันเหมือนกัน
Provider ecosystemhashicorp registryOpenTofu registry + ใช้ของ Terraform ได้
คนหนุนหลังHashiCorp (ตอนนี้อยู่ใน IBM)Linux Foundation
การนำไปใช้ปี 2026ยังนิยมGruntwork, GitHub, Cisco และอีกหลายเจ้าหันมาใช้/แนะนำ

คำแนะนำปี 2026:

  • Project ใหม่ / personal → ใช้ OpenTofu (free, no vendor lock)
  • Project เดิม / enterprise มี HashiCorp Cloud → ใช้ Terraform ต่อได้
  • ทั้ง 2 = command tofu หรือ terraform แทนกันได้ (CLI compatible)

หนังสือเล่มนี้ใช้ command terraform แต่ทุกอย่าง work กับ tofu เช่นกัน


10. Terraform Basics ​

Terraform คือเครื่องมือ IaC ยอดนิยมที่สุด — เขียนภาษา HCL บอกว่าอยากได้ resource อะไร แล้วมันจัดการสร้างให้ตรงตามนั้น ตัวอย่างแรกนี้คือโครง main.tf ที่ประกาศ provider (AWS) และ backend สำหรับเก็บ state ซึ่งเป็นจุดเริ่มของทุกโปรเจกต์ Terraform:

📌 Prerequisite ของ backend "s3" (chicken-and-egg ที่งงบ่อย): bucket my-terraform-state และตาราง DynamoDB ที่ใช้ lock ต้องสร้างด้วยมือผ่าน AWS Console (หรือ CLI) ก่อน — เพราะ Terraform เองยังไม่ทำงานจนกว่าจะมี backend ที่ใช้ได้ พอสร้างเสร็จแล้วค่อย terraform init แล้วใช้ต่อไปได้เลย

⚠️ ต้องมีสิทธิ์ s3:CreateBucket / s3:PutBucketVersioning และ dynamodb:CreateTable บน IAM user/role ที่ใช้รันคำสั่งด้วย และชื่อ bucket ต้อง unique ทั่วโลก (ทุก AWS account รวมกัน) — ถ้าเจอ error BucketAlreadyExists ให้เปลี่ยนชื่อ เช่น ต่อท้ายด้วย account id หรือเลขสุ่ม (my-terraform-state-8823471)

bash
# สร้าง S3 bucket สำหรับเก็บ state (ทำครั้งเดียว)
aws s3 mb s3://my-terraform-state --region us-east-1
aws s3api put-bucket-versioning \
  --bucket my-terraform-state \
  --versioning-configuration Status=Enabled

# สร้าง DynamoDB table สำหรับ lock (ถ้าใช้ Terraform < 1.10 ที่ยังไม่มี S3 native locking)
aws dynamodb create-table \
  --table-name tf-locks \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --region us-east-1
# หมายเหตุ: Terraform 1.10+ / OpenTofu 1.10+ ใช้ use_lockfile = true แทน DynamoDB ได้เลย
hcl
# main.tf

terraform {
  required_version = ">= 1.6.0"   # pin version Terraform/OpenTofu — กัน state ถูก upgrade โดย dev ที่เครื่องเวอร์ชันใหม่ผิด

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true            # เข้ารหัส state ตอนเก็บ
    use_lockfile   = true            # ⭐ S3 native locking (Terraform 1.10+/OpenTofu 1.10+) — ไม่ต้องใช้ DynamoDB แล้ว
    # dynamodb_table = "tf-locks"    # วิธีเก่า (ยังใช้ได้) — ใช้ตาราง DynamoDB lock; ถ้า Terraform < 1.10 ต้องใช้ตัวนี้
  }
}

provider "aws" {
  region = "us-east-1"
}

# สร้าง resource — S3 bucket
resource "aws_s3_bucket" "uploads" {
  bucket = "my-app-uploads"

  tags = {
    Environment = "prod"
    ManagedBy   = "terraform"
  }
}

resource "aws_s3_bucket_versioning" "uploads" {
  bucket = aws_s3_bucket.uploads.id
  versioning_configuration {
    status = "Enabled"
  }
}

Commands ​

bash
terraform init              # ดาวน์โหลด provider (ทำครั้งแรก)
terraform plan              # ดูตัวอย่างว่าจะเปลี่ยนอะไรบ้าง (ยังไม่ลงมือ)
terraform apply             # ลงมือสร้างจริง (ถามยืนยันก่อน)
terraform apply -auto-approve   # โหมด CI (ไม่ถามยืนยัน) — ดูคำเตือนด้านล่าง
terraform destroy           # ลบทุกอย่างที่สร้างไว้
terraform show              # ดู state ปัจจุบัน
terraform output            # แสดงค่า output

⚠️ -auto-approve ใช้เฉพาะในสภาพแวดล้อม CI/CD ที่ผ่าน code review แล้วเท่านั้น — อย่าใช้บน production หรือตอนเรียนครั้งแรก เพราะถ้า plan ผิด resource จะถูกลบหรือสร้างใหม่ทันทีโดยไม่มีขั้นตอนยืนยัน

Workflow ​

text
1. Edit .tf file
2. terraform plan
3. Review changes
4. terraform apply
5. Commit to git

11. Terraform Variables ​

เพื่อไม่ให้ hardcode ค่าลงในโค้ด Terraform ใช้ "variable" — ทำให้ config เดียวกันใช้ได้หลาย environment (dev/staging/prod) โดยส่งค่าต่างกันตอน apply ยังใส่ validation กันค่าผิดได้ด้วย ตัวอย่างนี้แสดงการประกาศตัวแปร, validation และการส่งค่าผ่าน .tfvars:

hcl
# variables.tf
variable "region" {
  type    = string
  default = "us-east-1"
}

variable "environment" {
  type        = string
  description = "Environment (dev/staging/prod)"
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Must be dev, staging, or prod"
  }
}

variable "instance_count" {
  type    = number
  default = 2
}

# Use
provider "aws" {
  region = var.region
}

resource "aws_instance" "web" {
  count         = var.instance_count
  ami           = "ami-xxx"
  instance_type = "t3.micro"
  tags = {
    Environment = var.environment
  }
}
bash
# Pass values
terraform apply -var="environment=prod"
terraform apply -var-file="prod.tfvars"
hcl
# prod.tfvars
region         = "us-east-1"
environment    = "prod"
instance_count = 5

12. Terraform Outputs ​

หลัง apply เสร็จ เรามักอยากรู้ค่าที่ระบบสร้างให้ (เช่น IP ของ instance, ชื่อ bucket) — "output" คือวิธีดึงค่าเหล่านี้ออกมาแสดงหรือส่งต่อให้ module/เครื่องมืออื่น ค่าที่ลับ (password) ทำเครื่องหมาย sensitive เพื่อซ่อนจาก log ได้:

hcl
# outputs.tf
output "instance_ips" {
  value = aws_instance.web[*].public_ip
}

output "s3_bucket_name" {
  value     = aws_s3_bucket.uploads.id
  sensitive = false
}

output "db_password" {
  value     = aws_db_instance.main.password
  sensitive = true     # hide in console
}
bash
terraform output instance_ips
terraform output -json | jq

13. Modules (Reusable) ​

เมื่อ infrastructure ใหญ่ขึ้น การเขียนทุกอย่างในไฟล์เดียวจะรกและซ้ำ — "module" คือการจับ resource ที่ทำงานร่วมกัน (เช่น network, database) มัดเป็นชุดที่ reuse ได้ รับ input และคืน output ทำให้แยกความรับผิดชอบและ reuse ข้ามโปรเจกต์ได้เหมือนฟังก์ชัน:

text
project/
├── main.tf
├── variables.tf
├── modules/
│   ├── network/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── database/
│       ├── main.tf
│       └── ...
hcl
# main.tf
module "network" {
  source = "./modules/network"
  
  vpc_cidr    = "10.0.0.0/16"
  environment = var.environment
}

module "database" {
  source = "./modules/database"
  
  vpc_id      = module.network.vpc_id
  environment = var.environment
}

→ Reuse + parameterize


14. Real Example — Full Stack ​

มาดูตัวอย่างจริงที่ประกอบทุกอย่างเข้าด้วยกัน — Terraform ที่สร้าง stack ครบ: VPC, subnet (แยก public/private), NAT, security group, RDS Postgres ใน private subnet, ECS Fargate, ALB อ่านไล่ลงมาจะเห็นว่า infrastructure ทั้งก้อนถูกอธิบายเป็นโค้ดที่ apply ครั้งเดียวจบ และ destroy ทิ้งได้หมด

💡 CIDR notation (เช่น 10.0.0.0/16) = วิธีเขียน range ของ IP — เลขหลัง / บอกว่ามีกี่ bit คงที่ ที่เหลือใช้แจกได้ — /16 = 65,536 IP, /24 = 256 IP

hcl
# ---------- Network ----------
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true

  tags = { Name = "my-app-vpc" }
}

# data source — อ่าน list ของ availability zones (AZ = data center ย่อยใน region)
data "aws_availability_zones" "available" {
  state = "available"
}

# Public subnet — สำหรับ ALB และ NAT Gateway
resource "aws_subnet" "public" {
  count                   = 2
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.${count.index}.0/24"
  availability_zone       = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true

  tags = { Name = "public-${count.index}" }
}

# Private subnet — สำหรับ RDS และ ECS task (ไม่มี public IP)
resource "aws_subnet" "private" {
  count             = 2
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.${count.index + 10}.0/24"
  availability_zone = data.aws_availability_zones.available.names[count.index]

  tags = { Name = "private-${count.index}" }
}

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
}

# ⚠️ NAT Gateway = ตัวกลางที่ทำให้เครื่องใน private subnet ออกอินเทอร์เน็ตได้ (เช่น ดึง Docker image, OS update)
#   "NAT" = Network Address Translation — แปลงที่อยู่ระหว่าง private network กับ internet
#   ราคา ~$32/เดือนต่อตัว + ค่า data transfer — ตัว dev environment ใช้ 1 ตัวพอ, prod ค่อยใส่ตัวละ AZ
resource "aws_eip" "nat" {
  domain = "vpc"
}

resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public[0].id
}

# (ตัด route table ออกเพื่อความสั้น — ในงานจริงต้องมี route ของ public ไป IGW, private ไป NAT)

# ---------- Database (Private subnet + Secrets Manager + random password) ----------
resource "aws_db_subnet_group" "main" {
  name       = "main"
  subnet_ids = aws_subnet.private[*].id   # ✅ RDS อยู่ใน private subnet (ไม่มี IP สาธารณะ)
}

# สุ่ม password ครั้งเดียว — เก็บใน Secrets Manager, ไม่ต้องใส่ตรง .tf หรือ tfvars
resource "random_password" "db" {
  length  = 32
  special = true
}

resource "aws_secretsmanager_secret" "db" {
  name = "myapp/db/credentials"
}

resource "aws_secretsmanager_secret_version" "db" {
  secret_id = aws_secretsmanager_secret.db.id
  secret_string = jsonencode({
    username = "appuser"
    password = random_password.db.result
    host     = aws_db_instance.postgres.address
    port     = aws_db_instance.postgres.port   # ✅ อ้างจาก resource จริง ไม่ hardcode — กัน secret ผิดถ้าเปลี่ยน engine
    dbname   = "myapp"
  })
}

resource "aws_db_instance" "postgres" {
  identifier        = "my-app-db"
  engine            = "postgres"
  engine_version    = "16"               # pin แค่ major (เลขเวอร์ชันรูปแบบ major.minor.patch — "pin major"
                                          # แปลว่าล็อกแค่เลขตัวแรก เช่น 16.x.y เปลี่ยนได้อัตโนมัติ แต่ 16→17 ต้องสั่งเอง)
                                          # → รับ minor patch อัตโนมัติ (security fix)
  # ⚠️ minor patch อัตโนมัติจะติดตั้งใน maintenance window ที่ตั้งไว้ (อาจทำให้ DB restart สั้น ๆ)
  #   งาน prod จริงควรกำหนด maintenance_window เอง (เช่นดึกช่วง traffic น้อย) ไม่ปล่อย default
  instance_class    = "db.t3.medium"
  allocated_storage = 20
  storage_encrypted = true

  db_name  = "myapp"
  username = "appuser"
  password = random_password.db.result   # ดึงจาก random_password (อยู่ใน state ที่เข้ารหัสบน S3)

  db_subnet_group_name   = aws_db_subnet_group.main.name
  vpc_security_group_ids = [aws_security_group.db.id]
  publicly_accessible    = false         # ✅ ปิด public access ทั้ง subnet และ flag

  backup_retention_period = 7
  multi_az                = var.environment == "prod"   # prod = multi-AZ, dev/staging = single AZ (ประหยัด)
  skip_final_snapshot     = var.environment != "prod"   # dev = ลบทิ้งได้ทันที, prod = บังคับให้ snapshot ก่อนทำลาย
  deletion_protection     = var.environment == "prod"

  tags = { Environment = var.environment }
}

# ---------- ECS task role + execution role ----------
# execution role = ใช้ตอน ECS pull image + เขียน log + ดึง secret
resource "aws_iam_role" "ecs_execution" {
  name               = "ecs-execution"
  assume_role_policy = data.aws_iam_policy_document.ecs_assume.json
}

data "aws_iam_policy_document" "ecs_assume" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["ecs-tasks.amazonaws.com"]
    }
  }
}

resource "aws_iam_role_policy_attachment" "ecs_execution_default" {
  role       = aws_iam_role.ecs_execution.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

# ให้ execution role ดึง secret จาก Secrets Manager ได้
resource "aws_iam_role_policy" "ecs_execution_secrets" {
  role = aws_iam_role.ecs_execution.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = ["secretsmanager:GetSecretValue"]
      Resource = [aws_secretsmanager_secret.db.arn]
    }]
  })
}

# task role = สิทธิ์ของแอปเอง (เข้า S3, ฯลฯ) — แยกจาก execution role ตามหลัก least privilege
resource "aws_iam_role" "ecs_task" {
  name               = "ecs-task"
  assume_role_policy = data.aws_iam_policy_document.ecs_assume.json
}

# ---------- Compute (ECS Fargate) ----------
resource "aws_ecs_cluster" "main" {
  name = "my-app"
}

resource "aws_ecs_task_definition" "web" {
  family                   = "web"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = 256
  memory                   = 512
  execution_role_arn       = aws_iam_role.ecs_execution.arn  # ✅ ขาดไม่ได้
  task_role_arn            = aws_iam_role.ecs_task.arn       # ✅ ขาดไม่ได้

  runtime_platform {
    cpu_architecture        = "ARM64"   # ⭐ Graviton — ถูกกว่า ~20%
    operating_system_family = "LINUX"
  }

  container_definitions = jsonencode([{
    name  = "web"
    image = "ghcr.io/myorg/myapp:1.0"
    portMappings = [{ containerPort = 8080 }]

    # ✅ ใช้ secrets block ดึงจาก Secrets Manager (ไม่ใช่ environment plain text)
    secrets = [
      {
        name      = "DATABASE_URL"
        valueFrom = "${aws_secretsmanager_secret.db.arn}:url::"   # field "url" ภายใน secret
      }
    ]

    # environment สำหรับค่าที่ไม่ลับเท่านั้น
    environment = [
      { name = "APP_ENV", value = var.environment }
    ]
  }])
}

# ---------- Load Balancer (ใน public subnet) ----------
resource "aws_lb" "main" {
  name               = "my-app-lb"   # ≤ 32 ตัวอักษร
  load_balancer_type = "application"
  subnets            = aws_subnet.public[*].id   # ALB อยู่ public, app server อยู่ private — ✅ pattern ถูก
  security_groups    = [aws_security_group.lb.id]
}

resource "aws_lb_target_group" "web" {
  name        = "my-app-tg"
  port        = 8080
  protocol    = "HTTP"
  target_type = "ip"
  vpc_id      = aws_vpc.main.id

  health_check {
    path                = "/health"
    matcher             = "200"
    healthy_threshold   = 2
    unhealthy_threshold = 3
  }
}

# Listener — HTTPS (ต้องมี ACM cert)
# 💡 ACM (AWS Certificate Manager) = บริการออกใบรับรอง HTTPS ฟรีของ AWS
#    ต้องขอ + validate โดเมนก่อน (ทำผ่าน Console/CLI แยกต่างหาก ไม่ได้อยู่ในตัวอย่างนี้)
#    ถึงจะได้ ARN มาใส่ตัวแปร acm_certificate_arn ด้านล่างนี้
resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.main.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = var.acm_certificate_arn

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.web.arn
  }
}

# Listener — HTTP (port 80) → redirect ไป HTTPS ทันที (อย่าลืม — ไม่งั้น traffic ยังวิ่ง HTTP เปล่าได้)
resource "aws_lb_listener" "http_redirect" {
  load_balancer_arn = aws_lb.main.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    type = "redirect"
    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}

→ รัน terraform apply → infra ทั้งระบบสร้างเสร็จใน 5-10 นาที


15. Terraform Best Practices ​

State Management — สำคัญที่สุด ต้องเข้าใจ ​

💡 Solo dev / side project — ข้ามไป "Plan + Review" ส่วนล่างได้

ส่วน "Remote State + Locking + DynamoDB" ด้านล่างเป็น production concern สำหรับทีม — ถ้าคุณทำ project คนเดียว, terraform state อยู่ local (terraform.tfstate ในเครื่อง) ใช้ได้ปกติ — แค่ commit state file ลง git ห้ามทำ (มี secret) และ backup ไว้ที่ปลอดภัย. Remote state จำเป็นเมื่อ:

  • มีทีม 2+ คนทำ infra ร่วมกัน (ต้อง lock กัน apply ชน)
  • มี CI/CD ที่ apply อัตโนมัติ
  • production-grade เริ่มจริง

State คืออะไร ​

terraform.tfstate = JSON file ที่ Terraform จำว่า:

  • "resource ที่ฉันเคยสร้าง มี ID อะไรใน AWS"
  • "resource นี้มี attribute อะไรบ้าง"
json
{
  "resources": [{
    "type": "aws_s3_bucket",
    "name": "uploads",
    "instances": [{
      "attributes": {
        "id": "my-app-uploads",
        "arn": "arn:aws:s3:::my-app-uploads",
        "region": "us-east-1"
      }
    }]
  }]
}

ทำไม state สำคัญ ​

Terraform เป็น declarative (บอกปลายทางที่อยากได้ ไม่บอกขั้นตอน) — เราบอกว่า "อยากได้แบบนี้" → Terraform ดู state → คำนวณเองว่าต้องทำอะไรบ้างถึงจะไปถึงปลายทางนั้น

text
Desired state (your .tf files):    Current state (terraform.tfstate):
  S3 bucket "uploads" with             S3 bucket "uploads" exists
  versioning = enabled                 versioning = disabled

→ Terraform diff: ต้องเปิด versioning

ถ้าไม่มี state → Terraform คิดว่าไม่เคยสร้างอะไร → พยายาม create ทุกครั้ง → error "already exists"

Remote State + Locking — ทำไมต้องมี ​

Local state (terraform.tfstate ในเครื่อง) มีปัญหา:

text
❌ ทำงานคนเดียวเท่านั้น (ไม่มีใคร share state ด้วย)
❌ ถ้าเครื่องพัง → state หาย → สร้าง infra ใหม่ต้องเริ่มจากศูนย์ (Terraform จะคิดว่าทุกอย่างยังไม่เคยถูกสร้าง)
❌ ถ้า 2 คน apply พร้อมกัน → เกิด race condition (สองคนเขียน state พร้อมกันแล้วชนกัน ข้อมูลเพี้ยน) → infra พัง
❌ มี secrets ใน state (DB password, API key) → ไม่ควรอยู่ใน local เครื่องส่วนตัว

Remote state (S3 / Azure Blob / GCS) แก้ทุกข้อ:

hcl
# Backend = remote state (team collaboration = ทำงานเป็นทีมได้)
terraform {
  backend "s3" {
    bucket       = "my-tf-state"
    key          = "prod/terraform.tfstate"
    region       = "us-east-1"
    encrypt      = true            # เข้ารหัสตอนเก็บ (at-rest encryption)
    use_lockfile = true            # ⭐ state locking แบบ native ของ S3 (Terraform 1.10+/OpenTofu 1.10+)
    # dynamodb_table = "tf-locks"  # วิธีเก่า — ใช้ DynamoDB lock; Terraform < 1.10 ต้องใช้ตัวนี้
  }
}

💡 2024+ ข่าวดี: S3 รองรับ Conditional Writes แล้ว — Terraform 1.10+ / OpenTofu 1.10+ ใช้ S3 lock ตรง ๆ ได้ ไม่ต้องตั้ง DynamoDB table แยกอีก (ลดความซับซ้อน + ลดค่าใช้จ่าย) — แต่ถ้าใช้เวอร์ชันเก่ากว่าก็ยังต้องใช้ DynamoDB

state locking ทำงานยังไง (S3 lockfile หรือ DynamoDB ก็แนวคิดเดียวกัน — สมมติ Alice กับ Bob เป็น dev 2 คนในทีมเดียวกัน):

text
1. Alice รัน terraform apply
2. Terraform จองล็อก (เขียน lockfile บน S3 หรือ row ใน DynamoDB): "Alice กำลังใช้ state นี้อยู่"
3. Bob รัน terraform apply พร้อมกัน
   → Terraform เจอ lock → ปฏิเสธ: "Error acquiring the state lock"
4. Alice เสร็จ → ลบ lock → Bob ทำต่อได้

Best Practices ​

  • ⚠️ อย่า commit terraform.tfstate — มี secrets (DB password, private keys)
  • ⚠️ อย่า edit terraform.tfstate ด้วยมือ — corruption → infra ไม่ตรง
  • ✅ ใช้ remote backend + locking ตั้งแต่วันแรก — S3 native locking (use_lockfile, Terraform/OpenTofu 1.10+) หรือ S3 + DynamoDB สำหรับเวอร์ชันเก่ากว่า (ทั้งคู่ฟรีในระดับ free tier)
  • ✅ Encrypt state (S3 server-side encryption + KMS)
  • ✅ Backup state (S3 versioning + cross-region replication)
  • ✅ Separate state per environment (dev/terraform.tfstate, prod/terraform.tfstate)

Workspaces vs Directory-per-environment (ตั้งค่าหลาย env) ​

bash
# Workspaces — เร็วแต่ใช้ state file เดียวที่ key ต่างกัน
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod

terraform workspace select prod
terraform apply

⚠️ คำแนะนำปี 2026: หลีกเลี่ยง workspaces สำหรับ multi-env บน prod — เพราะใช้ state, backend, provider, version เดียวกัน → เผลอ apply ผิด env ได้ง่าย, dev/prod ต้อง pin version ตรงกัน, ไม่มี isolation ที่แท้จริง. Workspaces เหมาะกับ "temporary scratch env" (เช่น feature branch ทดลอง) เท่านั้น

ทางที่ดีกว่า: directory-per-environment (หรือใช้ state file แยกกัน):

text
environments/
├── dev/
│   ├── main.tf            # อาจ import module จาก ../../modules
│   └── terraform.tfvars
├── staging/
└── prod/

→ แต่ละ env มี state, backend, provider version แยกเด็ดขาด → ผิดที่ dev ไม่กระทบ prod

Locking — ป้องกัน apply ชนกัน ​

ใช้ S3 native lockfile (Terraform 1.10+) หรือตาราง DynamoDB (วิธีเก่า) ป้องกัน 2 คนรัน terraform apply พร้อมกัน

Plan + Review ​

bash
terraform plan -out=tfplan
# review ดูว่าจะเปลี่ยนอะไรบ้าง
terraform apply tfplan

ใน Pull Request — แสดงผลของ terraform plan ใน comment เพื่อให้คนรีวิวเห็น diff ของ infra ก่อน merge


16. Terraform Patterns ​

เมื่อใช้ Terraform คล่องแล้ว จะเจอ pattern ที่ช่วยให้โค้ดยืดหยุ่นขึ้น — สร้าง resource แบบมีเงื่อนไข (count), วนสร้างหลายอันจาก list (for_each) และอ่านข้อมูล resource ที่มีอยู่แล้วโดยไม่สร้างใหม่ (data source) สาม pattern นี้ใช้บ่อยมากในงานจริง:

Conditional resource ​

hcl
resource "aws_instance" "monitoring" {
  count = var.environment == "prod" ? 1 : 0
  # ...
}

For each ​

hcl
variable "users" {
  default = ["alice", "bob", "carol"]
}

resource "aws_iam_user" "user" {
  for_each = toset(var.users)
  name     = each.key
}

Data source (อ่าน resource ที่มีอยู่แล้วโดยไม่สร้างใหม่) ​

hcl
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]   # เลข AWS account ID ของ Canonical (บริษัทเจ้าของ Ubuntu) — ใส่ไว้กรอง
                                    # ไม่ให้ดึง AMI ปลอมจาก account อื่นที่ตั้งชื่อคล้ายกัน

  filter {
    name   = "name"
    # ปี 2026 ใช้ Ubuntu 24.04 LTS (noble) — รองรับยาวถึง 2029
    # สำหรับ ARM Graviton ใช้ ssd-arm64 แทน amd64
    values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
  }
}

resource "aws_instance" "web" {
  ami = data.aws_ami.ubuntu.id
}

17. Alternatives to Terraform ​

Toolจุดเด่นเลือกเมื่อ
OpenTofu ⭐open source แท้ (MPL), เป็น fork ของ Terraformปี 2026 = default ของ project ใหม่
Terraformนิยมสุด, ecosystem ใหญ่ที่สุดมี HashiCorp Cloud หรือ policy องค์กรกำหนด
Pulumiเขียนด้วย Python/TS/Go ได้จริงทีมเป็น dev ที่ไม่ชอบ HCL
AWS CDKใช้ได้บน AWS เท่านั้น, เขียนด้วยภาษาโปรแกรมจริงAll-in กับ AWS, อยากใช้ภาษาเดียวกับ app
CDK for Terraform (CDKTF)เขียน CDK style แต่ output เป็น Terraform — ใช้ provider Terraform ทั้งหมดได้ชอบ CDK แต่ไม่อยาก lock AWS
CloudFormationYAML/JSON ของ AWS เองenterprise ที่ไม่อยากใช้ 3rd party
Crossplaneจัดการ infra ผ่าน K8s CRDทีมใช้ K8s เป็น control plane
Pkl (Apple)typed config language ใหม่ของ Appleใช้ generate config หลายรูปแบบ
Ansibleconfiguration managementconfigure ของข้างใน VM (ไม่ใช่สร้างตัวเครื่อง)

→ มือใหม่ปี 2026: OpenTofu (หรือ Terraform — syntax เหมือนกัน)


18. Configuration Management ​

Terraform สร้าง "ตัวเครื่อง" (VM, DB) ให้ แต่ใครจะติดตั้งซอฟต์แวร์และตั้งค่า "ข้างใน" เครื่อง? นั่นคือหน้าที่ของ configuration management (Ansible/Chef/Puppet) — แม้ปี 2026 จะใช้น้อยลงเพราะ container + immutable infrastructure เข้ามาแทนในงาน cloud-native, แต่ Ansible ยังเป็นมาตรฐานสำหรับงาน bare-metal, edge, network device, OS hardening และ legacy server ที่ container ลงไม่ได้:

text
Terraform: provision infrastructure (VM, DB)
Ansible / Chef / Puppet: configure inside (install packages, config files)
yaml
# Ansible playbook
- hosts: webservers
  tasks:
    - name: Install nginx
      apt:
        name: nginx
        state: present
    
    - name: Copy config
      copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf
    
    - name: Start nginx
      service:
        name: nginx
        state: started

ปี 2026 — ในงาน cloud-native ใช้น้อยลงเพราะแทนด้วย container + immutable infrastructure (สร้างเครื่องใหม่ทุกครั้งแทนการแก้เครื่องเดิม) แต่ยังเป็นเครื่องมือหลักสำหรับ bare-metal, network device, และระบบ legacy


19. Cloud Architecture Patterns ​

มี "แบบแปลน" สถาปัตยกรรมมาตรฐานที่ใช้กันบ่อยบน cloud — 3-tier แบบคลาสสิก, serverless (ไม่มีเซิร์ฟเวอร์ให้ดูแล), microservices บน Kubernetes และ multi-region สำหรับความทนทานสูง รู้จักแต่ละแบบแล้วจะออกแบบระบบให้เหมาะกับความต้องการได้:

A. 3-Tier (Classic) ​

B. Serverless ​

✅ ไม่ต้องจัดการ server ✅ scale ลงถึง 0 ได้ (ไม่ใช้ก็ไม่จ่าย) ✅ จ่ายต่อ request

C. Microservices (K8s) ​

D. Multi-Region (HA = High Availability) ​


20. Cost Optimization ​

บิล cloud พุ่งโดยไม่รู้ตัวเป็นเรื่องที่เกิดบ่อยมาก — การคุมค่าใช้จ่ายจึงเป็นทักษะ DevOps สำคัญ หัวข้อนี้รวมทั้งวิธีประหยัด (right-size, reserved/spot, ลบของไม่ใช้), เครื่องมือดู cost และ "กับดักค่าใช้จ่าย" ที่คนลืมบ่อย (เช่น NAT Gateway ที่เปิดทิ้งไว้):

Tips ทั่วไป ​

  • ✅ Right-size — เลือกขนาดเครื่องให้พอดี ไม่ใช่จัด m5.xlarge ทั้งที่ traffic น้อย
  • ✅ Reserved Instance / Savings Plans — จ่ายล่วงหน้า 1-3 ปี ลดได้ 30-70% (เหมาะ workload คงที่)
  • ✅ Spot instances — ลดสูงสุด 70-90% แต่ AWS เรียกคืนได้ทุกเมื่อ (เหมาะ batch job ที่ทนถูกหยุดได้)
  • ✅ Auto-scale ลง เมื่อไม่ใช้ (เช่นกลางคืน, วันหยุด)
  • ✅ ลบของที่ไม่ใช้ — snapshot เก่า, ดิสก์ที่ไม่ผูกกับเครื่อง, AMI เก่า
  • ✅ CloudFront ช่วยลด traffic จาก EC2 (cache + ราคาต่อ GB ถูกกว่า)
  • ✅ S3 Lifecycle — ตั้งให้ย้ายไฟล์เก่าไปชั้น archive (Glacier) อัตโนมัติ
  • ✅ Billing alerts — ตั้งเตือนที่ $10, $100, $1000
  • ✅ ใช้ free tier สำหรับ dev / test
  • ✅ ARM Graviton — เปลี่ยน instance / Lambda มาเป็น ARM ลดได้ ~20-40%

เครื่องมือ ​

  • AWS Cost Explorer — dashboard ดู cost ในตัว
  • Cloud Custodian — เครื่องมือเปิด rule clean up resource อัตโนมัติ
  • Infracost — แสดงประมาณการ cost ใน Terraform PR ก่อน apply
  • CloudHealth / Spot.io — ระดับ enterprise

กับดักค่าใช้จ่ายที่เจอบ่อย ​

  • ❌ NAT Gateway เปิดทิ้งไว้ (~$32/เดือนต่อตัว + ค่า data transfer)
    • 💡 NAT Gateway = อุปกรณ์ที่ทำให้ VM ใน private subnet ออก internet ได้ (เช่น ดึง Docker image, OS update) — ปกติเปิดอย่างน้อย 1 ตัวต่อ environment, prod ใส่ตัวละ AZ; dev/staging ใช้ตัวเดียวพอ; ถ้าไม่ต้องการให้ออก internet เลย ปิดทิ้งได้
  • ❌ EBS snapshot ค้างเยอะ (เก็บไว้ปีกว่าโดยลืม)
  • ❌ Elastic IP ที่ไม่ได้ผูกกับเครื่อง (AWS เก็บ $3.6/เดือนต่ออันสำหรับ EIP ที่ idle)
  • ❌ Data transfer ข้าม region (แพง — ปกติ $0.02/GB)
  • ❌ CloudWatch logs เก็บตลอดชาติ (ตั้ง retention 7-30 วันสำหรับ log ทั่วไป)
  • ❌ ลืม resource ตอน test (ตั้ง tag ทุกอย่าง เช่น env=test, owner=alice แล้วตามล้างตาม tag ได้)

21. Security Basics ​

ความปลอดภัยบน cloud วางอยู่บนเสาหลักไม่กี่ต้น — identity (IAM: ใครทำอะไรได้), network (VPC/security group/firewall), encryption (เข้ารหัสทั้งตอนส่งและตอนเก็บ) และ compliance หัวข้อนี้สรุป best practice ของแต่ละด้านที่ควรทำตั้งแต่วันแรก:

Identity (IAM) — ใครทำอะไรได้ ​

text
✅ ใช้ IAM role (ผูกกับ EC2/ECS/Lambda) แทน static access key
✅ Least privilege — ให้สิทธิ์เท่าที่จำเป็นเท่านั้น
✅ เปิด MFA (Multi-Factor Authentication = ยืนยันตัวตน 2 ชั้น)
✅ หมุน credential สม่ำเสมอ (rotate)
✅ เปิด audit log (CloudTrail) เพื่อย้อนดูใครทำอะไร
✅ ห้ามใช้ root account ทำงานประจำ — ใช้แค่ตอนตั้งบัญชีครั้งแรก
hcl
# IAM Role สำหรับ EC2 — เครื่องเอา role นี้ไปสวมเพื่อเข้า S3 โดยไม่ต้องมี access key
resource "aws_iam_role" "app" {
  name = "app-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action    = "sts:AssumeRole"
      Principal = { Service = "ec2.amazonaws.com" }
      Effect    = "Allow"
    }]
  })
}

resource "aws_iam_role_policy" "app_s3" {
  role = aws_iam_role.app.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action   = ["s3:GetObject", "s3:PutObject"]
      Effect   = "Allow"
      Resource = "${aws_s3_bucket.uploads.arn}/*"
      # ✅ บังคับให้เรียกผ่าน HTTPS เท่านั้น (best practice ปี 2026)
      Condition = {
        Bool = {
          "aws:SecureTransport" = "true"
        }
      }
    }]
  })
}

Network ​

  • VPC แบ่ง public + private subnet (ของสำคัญเช่น DB อยู่ private เท่านั้น)
  • Security Group = firewall แบบ stateful (จำ connection ที่ออกไป → packet ตอบกลับเข้าเองได้)
  • WAF (Web Application Firewall) = firewall ระดับ HTTP สำหรับ endpoint สาธารณะ — กัน SQL injection / XSS
  • VPN (Virtual Private Network) / PrivateLink สำหรับเชื่อม network ข้าม account หรือ on-prem โดยไม่ผ่าน internet

Encryption (เข้ารหัส) ​

  • ✅ TLS in transit (HTTPS) — เข้ารหัสตอนส่งข้าม network
  • ✅ Encryption at rest (เข้ารหัสตอนเก็บ):
    • S3 = เข้ารหัสโดย default ตั้งแต่มกราคม 2023 (server-side encryption)
    • EBS = ต้องไปกด "EBS encryption by default" ที่ระดับ region — ถ้าไม่เปิด, volume ใหม่จะไม่เข้ารหัสจนกว่าจะระบุเอง
    • RDS = ต้องเปิด storage_encrypted = true ตอนสร้างเท่านั้น — เปิดทีหลังไม่ได้ ต้อง restore จาก snapshot ที่เข้ารหัสไปสร้างใหม่
  • ✅ KMS (Key Management Service) เก็บ key + ตั้งให้หมุนอัตโนมัติ
  • ✅ Secrets Manager / Parameter Store / Vault — ไม่ฝัง secret ใน code หรือ env plain text
  • ✅ External Secrets Operator (ESO) — มาตรฐาน de-facto ปี 2026 สำหรับ sync secret จาก cloud (Secrets Manager / Vault) มาเป็น K8s Secret ให้ pod ใช้
  • ✅ SOPS (Mozilla) — เข้ารหัสไฟล์ YAML/JSON ของ secret ใน Git ได้

2026 Baselines (AWS) — เปิดทุกอันได้เลย ​

  • GuardDuty = ตรวจจับภัยอัตโนมัติจาก log (เปิดเป็น account-level)
  • Security Hub = dashboard รวม security finding จากทุก service
  • IAM Access Analyzer = สแกน policy หา resource ที่เปิดสิทธิ์เกิน
  • AWS Config = ตรวจ drift ของ config (เช่น S3 bucket เผลอเปิด public)
  • AWS Inspector = สแกน vulnerability ของ EC2/ECR/Lambda

Compliance ​

  • SOC 2, ISO 27001, HIPAA, GDPR (มาตรฐานที่ระบบ enterprise มักต้องผ่าน)
  • เช็คเอกสารของ cloud provider ว่ารองรับ compliance ไหนบ้างในแต่ละ region

22. Edge + CDN ​

ยิ่งเซิร์ฟเวอร์อยู่ไกล user ยิ่งช้า — CDN แก้ด้วยการ cache เนื้อหา static ไว้ที่ "edge" ใกล้ user ทั่วโลก ทำให้โหลดเร็วระดับ ~10ms และยังลดภาระเซิร์ฟเวอร์ต้นทาง ปัจจุบันยังรันโค้ดเล็ก ๆ ที่ edge ได้ด้วย (edge compute) สำหรับงานอย่าง auth หรือ A/B test:

CDN = cache เนื้อหา static ไว้ใกล้ผู้ใช้:

text
User (Bangkok) → CloudFront Bangkok edge → S3 (us-east-1)
                 (cache ไฟล์ HTML/JS/CSS/รูป ไว้แล้ว)

→ เว็บ static = latency ~10ms จากที่ไหนก็ได้ในโลก

Edge Compute ​

text
Cloudflare Workers, AWS Lambda@Edge, Vercel Edge:
- รันโค้ดที่ edge ของ CDN (ใกล้ผู้ใช้)
- ใช้สำหรับ: A/B test, ตรวจ auth, ดู geolocation, logic เบา ๆ
- cold start เร็ว — แต่ "เร็วแค่ไหน" ขึ้นกับ platform:
   • Cloudflare Workers, Vercel Edge = V8 isolate, cold start ~5ms
   • AWS Lambda@Edge = ใช้ Lambda จริง ๆ ใต้ฐาน, cold start 100-500ms (ไม่ใช่ edge ที่เร็วจริง)

23. Multi-Cloud + Hybrid ​

🚀 โซนขั้นสูง — ข้ามได้ Multi-cloud / hybrid เป็นเรื่องขององค์กรใหญ่ที่มีข้อจำกัดพิเศษ มือใหม่และโปรเจกต์ส่วนใหญ่ ควรใช้ cloud เจ้าเดียว ให้คล่องก่อน อ่านหัวข้อนี้แค่พอรู้ว่ามีอยู่และทำไมส่วนใหญ่ถึงไม่ทำก็พอ

ใช้ cloud หลายเจ้าพร้อมกัน (multi-cloud) หรือผสม on-premise กับ cloud (hybrid) ฟังดูดีแต่แลกมากับความซับซ้อนที่ทวีคูณ — หัวข้อนี้ชั่งน้ำหนักว่าเมื่อไหร่ควรทำจริง ๆ (ส่วนใหญ่คำตอบคือ "ใช้ cloud เจ้าเดียว + เตรียมแผนย้ายไว้" โดยใช้ Terraform เป็นชั้นกลางที่ช่วยให้ย้ายง่ายขึ้น):

text
ทำไมจะ multi-cloud:
- ไม่อยาก vendor lock-in (ผูกตัวกับเจ้าเดียว)
- เลือก service ที่เก่งที่สุดของแต่ละเจ้า (best-of-breed)
- ข้อบังคับเรื่อง compliance ในแต่ละประเทศ/region

ทำไมส่วนใหญ่ ไม่ ควรทำ:
- ความซับซ้อนเพิ่มเป็น N เท่า (ต้องเรียนรู้ทุกเจ้า)
- ค่าใช้จ่ายซ้ำซ้อน (ทำ network, monitoring, IAM 2 ระบบ)
- ทีมต้องเรียนแต่ละเจ้า

→ บริษัทส่วนใหญ่ = ใช้ cloud เจ้าเดียว + มีแผนย้าย (เขียน infra ผ่าน Terraform เพื่อให้ย้ายง่ายในวันที่จำเป็น)

Hybrid (on-prem + cloud) ​

text
ระบบเดิม on-prem → เชื่อมผ่าน AWS Direct Connect / VPN → cloud

เจอบ่อยในองค์กรใหญ่ที่กำลังทยอยย้ายขึ้น cloud (migration)


24. Common Pitfalls ​

รวมความผิดพลาดที่ทำให้ระบบ cloud ทั้งเปลือง ทั้งเสี่ยง และดูแลยาก — ส่วนใหญ่มาจากการทำมือใน console, ไม่ tag resource, hardcode secret หรือเผลอเปิด S3 เป็น public ตารางนี้จับคู่ปัญหากับวิธีแก้ที่ควรทำตั้งแต่ต้น:

ปัญหา (Pitfall)วิธีแก้
คลิกสร้างใน console (click-ops)ใช้ IaC (Terraform) แทน
แก้มือทำให้ infra เพี้ยน (drift)บังคับผ่าน CI/CD pipeline เท่านั้น
ไม่ติด tagtag ทุก resource (cost center, env, owner)
Hardcode secret ในโค้ดใช้ Secrets Manager / Vault
IAM user admin คนเดียวทำทุกอย่างแยก role ต่อ service ตามหลัก least privilege
S3 bucket เปิด publicprivate + ใช้ presigned URL ดึงไฟล์
ลืมลบ dev envตั้ง scheduled cleanup (ลบทุกคืน/วันหยุด)
ไม่ดู costตั้ง billing alert + เปิด Cost Explorer
ติด vendor lock-in ลึกเขียน infra ผ่าน Terraform เป็นชั้นกลาง

25. Cloud Cost — Real World ​

ตัวเลขจริงช่วยให้เห็นภาพดีกว่าทฤษฎี — หัวข้อนี้ยกตัวอย่างค่าใช้จ่ายต่อเดือนของระบบจริงสามขนาด: SaaS เล็ก (~$200), SaaS กลาง (~$1,400) และโปรเจกต์ที่อยู่บน free tier (~$1) ให้พอเดาได้ว่าระบบของคุณจะอยู่ราคาประมาณไหน:

SaaS เล็ก (~10k users) ​

text
EC2 (2x t3.medium):           $60     # เครื่องรันแอป
RDS (db.t3.medium):           $80     # database
S3 + CloudFront:              $20     # storage + CDN
ALB (Application LB):         $20     # load balancer
CloudWatch + logs:            $20     # monitoring
EBS (ดิสก์ผูก EC2):           $10     # มักลืมนับ
Data transfer ออก internet:   $10-30  # ขึ้นกับ traffic — มักโตเร็วสุด
รวม:                         ~$220-250/เดือน

⚠️ มือใหม่มักประมาณค่าใช้จ่ายต่ำกว่าจริง เพราะลืมนับ EBS, CloudWatch detailed metrics, data egress (ค่า traffic ออก internet ที่มักโตเร็วที่สุดและเก็บ $0.09/GB)

SaaS กลาง (~100k users) ​

text
EKS + 10 nodes:        $500    # Kubernetes cluster
RDS (Multi-AZ):        $300    # database สำรอง 2 ตัว
ElastiCache (Redis):   $100    # cache
S3 + CDN:              $200
อื่น ๆ:                $300    # monitoring, log, NAT, secret, etc.
รวม:                  ~$1,400/เดือน

โปรเจกต์ Free Tier ​

text
EC2 t3.micro (free 1 ปี):     $0
S3 5GB free:                  $0
Route 53 (DNS, ~$1):          $1
รวม:                          ~$1/เดือน

26. Choosing Cloud ​

สรุปสุดท้าย — เลือก cloud เจ้าไหนดี? คำตอบขึ้นกับบริบทของคุณ ตารางตัดสินใจแบบเร็วนี้แมตช์สถานการณ์ที่พบบ่อยกับตัวเลือกที่เหมาะ (เริ่มใหม่, สาย Microsoft, เน้น data/ML, อยากถูกและง่าย ฯลฯ):

text
เริ่มจากศูนย์ ไม่มี constraint?     → AWS (เอกสารเยอะที่สุด)
ทีมใช้เทคโนโลยี Microsoft เป็นหลัก?  → Azure
เน้น data / ML?                      → GCP (BigQuery, Vertex AI)
อยากถูก + เรียบง่าย?                  → Hetzner, DigitalOcean
มีแต่ frontend?                       → Vercel, Netlify, Cloudflare
หาตัวแทน Heroku?                      → Render, Railway, Fly.io

27. Checkpoint ​

ลงมือทำเองเพื่อให้ความรู้ติดตัว — แบบฝึกหัดต่อไปนี้ไล่จากตั้ง free tier + billing alert, สร้าง resource แรกด้วย Terraform, deploy full stack, audit ค่าใช้จ่าย ไปจนถึงทำ multi-environment ครบ 5 ข้อแล้วจะใช้ cloud + IaC ได้จริง:

🛠️ Checkpoint 6.1 — เปิด Free Tier

  • สร้าง AWS / GCP account
  • ตั้ง billing alert ที่ $10
  • Deploy hello-world บน EC2 / Compute Engine

🛠️ Checkpoint 6.2 — Terraform Resource แรก

  • ติดตั้ง Terraform (หรือ OpenTofu)
  • สร้าง S3 bucket ผ่าน Terraform
  • เพิ่ม versioning + encryption
  • รัน terraform plan แล้ว terraform apply

🛠️ Checkpoint 6.3 — Full Stack Deploy แอป Spring Boot + React:

  • VPC + subnets (public/private) ผ่าน Terraform
  • RDS PostgreSQL ใน private subnet + รหัสจาก Secrets Manager
  • ECS Fargate + execution role + task role
  • ALB ที่มี HTTPS listener
  • S3 + CloudFront สำหรับ static frontend

🛠️ Checkpoint 6.4 — Cost Audit

  • เปิด AWS Cost Explorer
  • หา 3 รายการที่กิน cost สูงสุด
  • ทำ 1 optimization (right-size / reserved / spot / Graviton)

🛠️ Checkpoint 6.5 — Multi-env

  • เขียน Terraform module ของแอป
  • ทำ environment dev / staging / prod (directory-per-env)
  • ตั้งขนาดต่างกันในแต่ละ env (เช่น dev = t4g.micro, prod = t4g.medium)

28. สรุปบท ​

ทบทวนสาระทั้งบท — ตั้งแต่ทำไมต้อง cloud, ผู้ให้บริการเจ้าหลัก, service model, การเลือก compute, Infrastructure as Code ด้วย Terraform ไปจนถึงเรื่อง cost และ security เช็กลิสต์นี้คือแก่นที่ควรเข้าใจก่อนนำไปใช้จริง:

✅ Cloud = ยืดหดได้ (elastic), มี managed service, จ่ายตามใช้จริง ✅ AWS (นิยมสุด), GCP (data/ML), Azure (enterprise), DigitalOcean (เรียบง่าย) ✅ Service models: IaaS → PaaS → SaaS → Function (ดูแลมาก → ดูแลน้อย) ✅ เลือก compute: Lambda → Cloud Run / ECS → EKS / GKE (ตามความซับซ้อน) ✅ Heroku/Render/Railway = ทางเลือกง่ายสุดสำหรับโปรเจกต์เล็ก ✅ IaC (Terraform/OpenTofu) = infrastructure เป็นโค้ด — มี version, reproducible ✅ Terraform: provider, resource, variable, output, module ✅ Remote state + lock (S3 native lockfile ตั้งแต่ Terraform 1.10+, หรือ DynamoDB ในเวอร์ชันเก่า) ✅ Workflow: plan → review → apply ✅ Cost optimization: right-size, Reserved/Savings, spot, Graviton, billing alert, tag ✅ Security: ใช้ IAM role (ไม่ใช้ static key), least privilege, encryption, Secrets Manager, MFA, เปิด GuardDuty/Security Hub ✅ เริ่มจาก cloud เจ้าเดียว — ใช้ Terraform เป็นชั้นกลาง เผื่อย้ายในอนาคต


← บทที่ 5 | บทที่ 7 → Monitoring + Observability