AWS CloudFormation
Infrastructure as Code
01IaC Concept และ CloudFormation Overview
AWS CloudFormation คือบริการ Infrastructure as Code (IaC) ที่ให้เราเขียน template (ไฟล์ YAML หรือ JSON) เพื่อประกาศว่าต้องการ AWS resources อะไรบ้าง แล้ว CloudFormation จะไป provision และจัดการให้ทั้งหมดแบบอัตโนมัติ แทนการกดสร้างทีละตัวใน Console (manual)
- No manual creation — ทุกอย่างถูก code ไว้ ลดความผิดพลาดและทำซ้ำได้ (reproducible)
- Version control — template เก็บใน Git ได้ ทำ code review ได้
- Cost tracking — แต่ละ resource มี stack ID ทำให้ tag และคำนวณค่าใช้จ่ายต่อ stack ได้ง่าย
- Declarative — เราบอก 'ปลายทาง' ที่ต้องการ ไม่ต้องเขียนลำดับการสร้างเอง CloudFormation จัดลำดับ dependency ให้
- CloudFormation ฟรี ไม่มีค่าบริการ จ่ายเฉพาะ resources ที่มันสร้าง
02Template Structure (โครงสร้าง Template)
Template ประกอบด้วยหลาย section แต่จำสำคัญ: มีแค่ Resources เท่านั้นที่บังคับ (mandatory) section อื่น ๆ เป็น optional ทั้งหมด
| Section | บังคับ? | หน้าที่ |
|---|---|---|
| Resources | ใช่ (จำเป็น) | ประกาศ AWS resources ที่จะสร้าง เช่น EC2, S3, RDS |
| Parameters | ไม่ | ค่า input แบบ dynamic ที่ส่งเข้ามาตอน deploy เพื่อให้ template reuse ได้ |
| Mappings | ไม่ | ค่าคงที่ (static) แบบ lookup table เช่น map ภูมิภาค -> AMI ID |
| Outputs | ไม่ | ค่าที่ export ออกจาก stack เพื่อให้ stack อื่นหรือผู้ใช้นำไปใช้ต่อ |
| Conditions | ไม่ | เงื่อนไข (true/false) ควบคุมว่าจะสร้าง resource หรือไม่ |
| Metadata | ไม่ | ข้อมูลเพิ่มเติมของ template รวมถึง config สำหรับ cfn-init (AWS::CloudFormation::Init) |
Section อื่นที่ optional แต่พบบ่อย: Transform (ใช้เรียก macros / SAM), Description, AWSTemplateFormatVersion และ Rules
AWSTemplateFormatVersion: "2010-09-09"
Description: Demo template
Parameters:
InstanceType:
Type: String
Default: t2.micro
AllowedValues: [t2.micro, t2.small]
Resources:
MyInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
ImageId: ami-0abcdef1234567890
Outputs:
InstanceId:
Value: !Ref MyInstance03Parameters และ Mappings
Parameters (ค่า input แบบ dynamic)
Parameters ใช้รับค่าจากภายนอกตอน deploy ทำให้ template ยืดหยุ่นและ reuse ได้ มี properties สำคัญเช่น Type, Default, AllowedValues, AllowedPattern, MinLength/MaxLength, NoEcho (ซ่อนค่า เช่น password)
- ใช้ Parameters เมื่อค่านั้น 'ไม่รู้ล่วงหน้า' หรือ 'จะเปลี่ยนได้' เช่น instance type, key pair name
- Type พิเศษ: AWS-Specific Parameter Types เช่น AWS::EC2::KeyPair::KeyName ช่วยให้ Console แสดง dropdown และ validate ค่าจริงในบัญชีได้
- SSM Parameter Types — ดึงค่าจาก Systems Manager Parameter Store เช่นล่าสุดของ AMI ID ได้
- อ้างถึงค่าด้วย Fn::Ref (หรือ !Ref ใน YAML)
Mappings (ค่าคงที่แบบ lookup)
Mappings เป็นค่า static hard-code ที่รู้ล่วงหน้าทั้งหมด เหมาะกับ lookup table เช่น mapping Region -> AMI ID หรือ environment -> instance size อ่านค่าด้วย Fn::FindInMap [ MapName, TopLevelKey, SecondLevelKey ]
Mappings:
RegionMap:
us-east-1:
AMI: ami-0ff8a91507f77f867
ap-southeast-1:
AMI: ami-08569b978cc4dfa10
Resources:
MyInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI]04Intrinsic Functions (ฟังก์ชันในตัว)
Intrinsic Functions คือฟังก์ชันที่ CloudFormation provide ให้ใช้อ้างอิงค่าระหว่าง resources/parameters ภายใน template เป็นหัวใจของข้อสอบ
- Condition Functions: Fn::And, Fn::Or, Fn::Not, Fn::Equals, Fn::If — ใช้สร้าง logic ใน Conditions section
- Fn::FindInMap — อ่านค่าจาก Mappings
- Fn::GetAZs — คืน list ของ Availability Zones ในภูมิภาคนั้น มักใช้คู่กับ Fn::Select
- UserData ต้อง wrap ด้วย Fn::Base64 เสมอ
# ตัวอย่างรวมหลายฟังก์ชัน
UserData:
Fn::Base64: !Sub |
#!/bin/bash
echo "Region is ${AWS::Region}"
SubnetAZ: !Select [0, !GetAZs ""]
Name: !Join ["-", ["app", !Ref "AWS::StackName"]]05Pseudo Parameters (ตัวแปรในตัว AWS)
Pseudo Parameters คือค่าที่ AWS ให้มาในทุก template โดยไม่ต้องประกาศ ใช้ผ่าน !Ref ได้เลย
| Pseudo Parameter | ค่าที่ได้ (ตัวอย่าง) |
|---|---|
| AWS::AccountId | 1234567890 (เลขบัญชี) |
| AWS::Region | us-east-1 (ภูมิภาคที่ deploy stack) |
| AWS::StackName | ชื่อ stack ปัจจุบัน |
| AWS::StackId | ARN เต็มของ stack |
| AWS::NotificationARNs | list ของ SNS ARN ที่ผูกกับ stack |
| AWS::NoValue | เมื่อคืนค่านี้ resource property จะถูกลบออก (มักใช้คู่ Fn::If) |
06Conditions (เงื่อนไขการสร้าง resource)
Conditions ใช้ควบคุมการสร้าง resource หรือกำหนดค่า property ตามเงื่อนไข เช่น สร้างต่างกันระหว่าง dev/prod หรือสร้างเฉพาะบาง Region เงื่อนไขประเมินจาก Parameters, Mappings หรือ condition อื่น
Parameters:
EnvType:
Type: String
AllowedValues: [dev, prod]
Conditions:
IsProduction: !Equals [!Ref EnvType, prod]
Resources:
ProdOnlyBucket:
Type: AWS::S3::Bucket
Condition: IsProduction- ผูกเงื่อนไขกับ resource ด้วย key Condition: ในตัว resource
- condition functions ใช้ได้: Fn::And, Fn::Or, Fn::Not, Fn::Equals
- ใช้ Fn::If เพื่อเลือกค่า property ตามเงื่อนไข (เลือกค่า ไม่ใช่สร้าง resource)
07Stacks, Nested Stacks และ Cross-Stack (Export/ImportValue)
Stack คือกลุ่ม resources ที่ถูกจัดการเป็นหน่วยเดียวจาก template เดียว เมื่อลบ stack resources ทั้งหมดจะถูกลบตามไปด้วย (ยกเว้นที่ตั้ง DeletionPolicy ไว้)
Cross-Stack (Export + Fn::ImportValue)
ใช้ Outputs + Export เพื่อแชร์ค่า (เช่น VPC ID, SecurityGroup ID) ข้าม stack แล้ว stack อื่นดึงด้วย Fn::ImportValue เหมาะเมื่อ stack มี lifecycle แยกกันแต่ต้องพึ่งพากัน
- ชื่อ Export ต้อง unique ภายใน Region/บัญชีเดียวกัน
- ห้ามลบ/แก้ค่าที่ถูก Export อยู่ ถ้ายังมี stack อื่น ImportValue อยู่ -> จะ update/delete ไม่ได้
- Cross-stack reference ทำงานภายใน Region เดียวกันและบัญชีเดียวกัน เท่านั้น
Nested Stacks
Nested Stacks คือ stack ที่เป็นส่วนหนึ่งของ stack อื่น (parent) ใช้ resource type AWS::CloudFormation::Stack เหมาะกับการ reuse component ที่ใช้ซ้ำบ่อย เช่น Load Balancer config, security group มาตรฐาน
| ประเด็น | Cross-Stack (Export/Import) | Nested Stacks |
|---|---|---|
| จุดประสงค์ | แชร์ค่า/ทรัพยากรที่ stack อื่นต้องพึ่งพา (มี lifecycle แยก) | Reuse component ซ้ำ ๆ ที่เป็นของ stack หลัก |
| ความเป็นเจ้าของ | แต่ละ stack มีเจ้าของ/ทีมต่างกันได้ | parent เป็นเจ้าของ nested ทั้งหมด |
| กลไก | Outputs Export + Fn::ImportValue | AWS::CloudFormation::Stack (TemplateURL ไป S3) |
| เมื่อไรเลือก | ค่าที่ใช้ร่วมหลาย stack เช่น VPC ID กลาง | อยากแยก template ใหญ่เป็นชิ้น reusable |
08StackSets
StackSets ใช้ deploy stack เดียวกันไปยัง หลายบัญชี (accounts) และหลาย Region พร้อมกัน จากจุดเดียว เมื่อ update template ตัว StackSet จะอัปเดต stack instances ทั้งหมดในทุก account/region ที่ผูกไว้
- เหมาะกับองค์กรที่ใช้ AWS Organizations ต้องการ baseline เหมือนกันทุกบัญชี เช่น IAM roles, security config
- มี administrator account (ที่สร้าง StackSet) และ target accounts (ที่ stack ไป deploy)
- รองรับ automatic deployment ไปยังบัญชีใหม่ที่เพิ่มเข้ามาใน Organization (ผ่าน service-managed permissions)
- เมื่อลบ stack instances จาก StackSet จะลบ resources ในทุก target ที่เลือก
09Change Sets, Drift Detection และ Rollback
Change Sets
Change Sets ให้เรา preview ว่าการ update stack จะกระทบ resources อย่างไรก่อนลงมือจริง โดยเฉพาะบอกว่า resource ไหนจะถูก replace (สร้างใหม่) เพราะการ replace อาจทำให้ข้อมูลหาย/downtime แต่ change set ไม่บอก ว่า update จะสำเร็จหรือไม่
Drift Detection
Drift Detection ตรวจว่า resource จริงถูกแก้ไข 'นอก CloudFormation' (เช่นกดแก้ใน Console / CLI) จนต่างจาก template หรือไม่ ถ้าต่างเรียกว่า drift ใช้หาว่าใครไปแก้ config มือเปล่า แต่ไม่ใช่ทุก resource ที่รองรับ drift detection
Rollback
- Create ล้มเหลว (default) -> rollback ลบทุกอย่างที่สร้าง สถานะกลับเป็นเหมือนไม่เคยสร้าง (ปิด rollback ได้เพื่อ debug)
- Update ล้มเหลว -> rollback กลับสู่สถานะก่อน update ที่ทำงานได้ (last known working state)
- Stack Policy ใช้ป้องกัน resource สำคัญไม่ให้ถูก update/replace โดยไม่ตั้งใจ — เมื่อมี stack policy แล้ว default คือ ทุก resource ถูกป้องกัน จนกว่าจะระบุ allow ชัดเจน
10DeletionPolicy, UpdateReplacePolicy และ DependsOn
DeletionPolicy ควบคุมว่าเกิดอะไรกับ resource เมื่อ ลบออกจาก stack / ลบ stack ส่วน UpdateReplacePolicy ควบคุมตอน resource ถูก replace ระหว่าง update
| DeletionPolicy | ผลลัพธ์ |
|---|---|
| Delete (default) | ลบ resource ทิ้ง (ยกเว้น S3 bucket ที่ยังมี object จะลบไม่ได้) |
| Retain | เก็บ resource ไว้ ไม่ลบ แม้ลบ stack — ใช้กับ resource ที่ห้ามหาย |
| Snapshot | ทำ snapshot ก่อนลบ (ใช้ได้กับ resource ที่ทำ snapshot ได้ เช่น RDS, EBS Volume, ElastiCache, Redshift) |
- RDS DBInstance default DeletionPolicy คือ Snapshot (ระวัง: ค่า default ของ RDS ไม่ใช่ Delete)
- ถ้าตั้ง DeletionPolicy: Retain ควรตั้ง UpdateReplacePolicy: Retain ด้วยเพื่อกันข้อมูลหายตอน replace
- DependsOn บังคับลำดับการสร้าง: resource A จะสร้างหลัง B เสร็จ — ใช้เมื่อ CloudFormation เดา dependency เองไม่ได้ (ไม่มี Ref/GetAtt เชื่อมกัน)
Resources:
MyDatabase:
Type: AWS::RDS::DBInstance
DeletionPolicy: Snapshot
UpdateReplacePolicy: Snapshot
Properties:
Engine: mysql
DBInstanceClass: db.t3.micro
AllocatedStorage: "20"
MasterUsername: admin
MasterUserPassword: !Ref DBPassword11cfn-init, cfn-signal, CreationPolicy, WaitCondition และ Custom Resources
กลุ่ม cfn helper scripts ใช้ตั้งค่า EC2 instance หลังบูตและรายงานสถานะกลับมายัง CloudFormation
Resources:
WebServer:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Count: 1
Timeout: PT10M # รอสูงสุด 10 นาที
Metadata:
AWS::CloudFormation::Init:
config:
packages:
yum:
httpd: []
Properties:
ImageId: ami-0abcdef1234567890
InstanceType: t2.micro
UserData:
Fn::Base64: !Sub |
#!/bin/bash
/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServer --region ${AWS::Region}
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServer --region ${AWS::Region}คำถามทบทวน
ทดสอบความเข้าใจหัวข้อ AWS CloudFormation
22 ข้อ · เลือกคำตอบเพื่อดูเฉลยและคำอธิบาย
1.ใน CloudFormation template section ใดที่เป็น 'บังคับ' (mandatory) ต้องมีเสมอ?
2.Developer ต้องการดึงค่า Public DNS name ของ EC2 instance ที่สร้างใน template เพื่อนำไปใช้ใน Outputs ควรใช้ intrinsic function ใด?
3.ทีมต้องการ deploy stack ที่เหมือนกันไปยังหลาย AWS accounts และหลาย Region พร้อมกันจากจุดเดียว ควรใช้อะไร?
4.ค่าใดต่อไปนี้รู้ล่วงหน้าทั้งหมดและเป็น lookup table แบบ static เช่น map Region ไปยัง AMI ID ควรเก็บใน section ใด?
5.เมื่อลบ CloudFormation stack ที่มี RDS DBInstance โดยไม่ได้กำหนด DeletionPolicy เอง จะเกิดอะไรขึ้นกับฐานข้อมูล?
6.Developer แก้ Security Group rule ผ่าน Console โดยตรง (นอก CloudFormation) ต้องการตรวจว่า resource ใน stack เบี่ยงเบนจาก template หรือไม่ ควรใช้ feature ใด?
7.EC2 instance ต้องรัน user data script ติดตั้งแอป และต้องการให้ CloudFormation 'รอ' จนแอปพร้อมจริงก่อนถือว่า stack สำเร็จ ควรใช้คู่ใด?
8.ต้องการเขียน script ใน UserData ของ EC2 ใน template ต้อง encode อย่างไรให้ CloudFormation ส่งให้ถูกต้อง?
9.Stack A export ค่า VPC ID ผ่าน Outputs และ Stack B ใช้ Fn::ImportValue ดึงค่านั้น เกิดอะไรขึ้นถ้าพยายามลบ Stack A?
10.ต้องการสร้าง resource บางตัวเฉพาะเมื่อ environment เป็น 'prod' โดยใช้ template เดียว ควรใช้อะไร?
11.Developer ต้องการรัน logic เองตอนสร้าง stack เพื่อ empty S3 bucket ก่อนที่ stack จะถูกลบ (ซึ่ง CloudFormation ทำเองไม่ได้) ควรใช้อะไร?
12.Change Set ใน CloudFormation ให้ข้อมูลอะไรก่อนทำการ update จริง?
13.ในตัวอย่าง !FindInMap [RegionMap, !Ref 'AWS::Region', AMI] ค่า AWS::Region คือสิ่งใด?
14.ต้องการให้ EBS Volume ถูกเก็บไว้ไม่ถูกลบเมื่อลบ stack และไม่หายเมื่อ resource ถูก replace ตอน update ควรตั้งค่าใด?
15.Resource A (EC2) ต้องถูกสร้างหลังจาก Resource B (เช่น VPC Gateway Attachment) เสร็จ แต่ไม่มี Ref/GetAtt เชื่อมกันโดยตรง ควรใช้อะไรบังคับลำดับ?
16.Parameter ใดควรตั้ง NoEcho: true?
17.ต้องการ reuse component (เช่น standard load balancer config) ที่ใช้ซ้ำในหลาย stack โดยให้ stack หลักเป็นเจ้าของและเรียกใช้ผ่าน TemplateURL ใน S3 ควรใช้อะไร?
18.เมื่อมีการ apply Stack Policy ให้กับ stack พฤติกรรม default ต่อ resource ทั้งหมดเป็นอย่างไร?
19.ฟังก์ชันใดเหมาะที่สุดสำหรับแทนค่าตัวแปรในสตริง เช่น สร้างข้อความ 'arn:aws:s3:::${BucketName}' ในที่เดียว?
20.Developer ต้องการเลือก Availability Zone แรกของ Region ปัจจุบันมาใช้กับ subnet โดยไม่ hard-code ควรเขียนอย่างไร?
21.การ create stack ล้มเหลวกลางคัน โดย default CloudFormation จะทำอย่างไร?
22.cfn-init อ่าน configuration จากที่ใดใน template?