CloudFormation: template, stack và change set
Mục tiêu bài học
Sau bài này, bạn sẽ:
- Đọc hiểu cấu trúc một template CloudFormation và biết section nào dùng để làm gì.
- Phân biệt rõ template, stack, change set và khi nào phải dùng change set.
- Xử lý được các tình huống rollback,
UPDATE_ROLLBACK_COMPLETEvà drift. - Chọn đúng cơ chế truyền tham số và secret (parameter,
NoEcho, SSM, Secrets Manager) theo câu hỏi thi.
Ôn nhanh bài trước
Bài trước bạn đã đi qua luồng CodePipeline, CodeDeploy và SAM. Điểm cần nhớ: SAM chính là một lớp chuyển đổi (transform) của CloudFormation, nghĩa là file template.yaml của SAM khi deploy vẫn biến thành một stack CloudFormation bên dưới. Vì vậy hiểu CloudFormation là điều kiện để hiểu luôn cả SAM.
Lý thuyết
Template, stack và change set là gì?
Ba khái niệm này hay bị hỏi lẫn lộn, hãy tách rõ:
| Khái niệm | Bản chất | Ví dụ |
|---|---|---|
| Template | File JSON/YAML mô tả tài nguyên mong muốn | template.yaml trong repo |
| Stack | Một tập tài nguyên được tạo và quản lý như một đơn vị từ template | prod-api-stack |
| Change set | Bản xem trước (preview) những gì sẽ thay đổi trước khi apply | Xem trước khi thêm một Lambda |
Nói ngắn: template là bản thiết kế, stack là ngôi nhà đã xây, change set là bản dự toán sửa nhà trước khi cho thợ đập tường.
flowchart LR
T["📄<br/>Template YAML"] --> CS["👁️<br/>Change set"]
CS --> S["🏗️<br/>Stack"]
S --> R["🧱<br/>Resources"]
R --> D["🚨<br/>Drift detection"]
Các section trong template
Một template có các section sau, thứ tự này cũng là thứ tự ưu tiên khi ôn thi:
AWSTemplateFormatVersion: phiên bản template, hiện chỉ có2010-09-09.Description: mô tả ngắn.Parameters: giá trị truyền vào lúc deploy, cóType,Default,AllowedValues.Mappings: bảng tra cứu tĩnh, ví dụ map Region sang AMI ID.Conditions: điều kiện boolean, dùng vớiFn::Ifđể bật/tắt tài nguyên theo môi trường.Transform: khai báoAWS::Serverless-2016-10-31khi dùng SAM.Resources: section duy nhất bắt buộc, mọi thứ khác đều tùy chọn.Outputs: xuất giá trị, có thể dùngExportđể stack khácFn::ImportValue.
[!IMPORTANT] Câu hỏi kinh điển: section nào bắt buộc trong template? Chỉ có
Resources. Nếu đề cho một template chỉ cóParametersvàOutputs, template đó invalid.
Pseudo parameters và intrinsic functions cần nhớ
Pseudo parameters có sẵn, không cần khai báo: AWS::Region, AWS::AccountId, AWS::StackName, AWS::NoValue.
Vài hàm hay gặp:
Reflấy giá trị tham số hoặc ID tài nguyên; với resource thì trả về physical ID.Fn::GetAttlấy attribute cụ thể, ví dụ!GetAtt MyBucket.Arn.Fn::Subthay biến trong chuỗi, gọn hơn nối chuỗi.Fn::ImportValuelấy giá trịOutputđượcExporttừ stack khác.Fn::Ifkết hợp vớiConditions, dùngAWS::NoValueđể bỏ hẳn thuộc tính.
Truyền tham số và secret
Đây là vùng dễ mất điểm nhất. Nguyên tắc:
- Không hard-code secret trong template.
NoEcho: truechỉ che giá trị trong log/console, không mã hoá gì cả. Đừng nhầm nó với bảo mật thật.- Với secret thật, dùng SSM Parameter Store (SecureString) hoặc Secrets Manager, rồi tham chiếu động:
{{resolve:ssm:/myapp/db-password}}hoặc{{resolve:secretsmanager:myapp/db:SecretString:password}}. - Tham chiếu
resolve:được giải quyết tại thời điểm deploy, nên giá trị secret không nằm trong template. - Trên EC2/ECS/Lambda, nên dùng IAM role + Secrets Manager thay vì nhét secret vào environment variable dạng plaintext.
Section duy nhất bắt buộc trong một CloudFormation template là {{c1::Resources}}.
Để che giá trị tham số trong console và log, ta đặt thuộc tính {{c2::NoEcho}} bằng true, nhưng nó không mã hoá giá trị.
Cơ chế trả về giá trị secret tại thời điểm deploy là tham chiếu động {{c3::resolve}} (ví dụ `resolve:ssm` hoặc `resolve:secretsmanager`).
Khi CloudFormation phát hiện tài nguyên bị thay đổi ngoài stack, ta gọi đó là {{c4::drift}}.
Rollback, failure và drift
Khi tạo mới thất bại, CloudFormation rollback và tài nguyên bị xoá (trừ khi bạn bật DisableRollback hoặc OnFailure=DO_NOTHING).
Khi update thất bại:
- Stack quay về trạng thái cũ với
UPDATE_ROLLBACK_COMPLETE. - Nếu chính bước rollback cũng fail, stack kẹt ở
UPDATE_ROLLBACK_FAILED. Khi đó dùng ContinueUpdateRollback vớiResourcesToSkipđể gỡ kẹt.
Drift là khi tài nguyên thực tế khác với template (ai đó sửa tay trên console). Drift detection chỉ báo cáo, không tự sửa. Bạn phải cập nhật lại template hoặc revert thủ công.
DeletionPolicy và UpdateReplacePolicy quyết định chuyện gì xảy ra khi tài nguyên bị xoá/thay thế: Retain giữ lại, Snapshot chụp bản sao (dùng cho RDS, EBS), Delete là mặc định.
Ví dụ minh hoạ
Ví dụ 1: Tạo stack từ template đơn giản.
AWSTemplateFormatVersion: "2010-09-09"
Description: Demo stack
Parameters:
Env:
Type: String
AllowedValues: [dev, prod]
Conditions:
IsProd: !Equals [!Ref Env, prod]
Resources:
DataBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub "demo-${Env}-data-${AWS::AccountId}"
Outputs:
BucketName:
Value: !Ref DataBucket
Export:
Name: DataBucketName
Đọc từ trên xuống: Parameters cho phép chọn môi trường, Conditions tạo IsProd (ở đây chưa dùng nhưng để thấy pattern), Resources tạo bucket với tên dựng bằng Fn::Sub, DeletionPolicy: Retain nghĩa là xoá stack vẫn giữ bucket. Outputs export tên bucket để stack khác dùng Fn::ImportValue.
Ví dụ 2: Deploy có change set.
1. Tạo change set: `aws cloudformation create-change-set --stack-name prod-api --template-body file://template.yaml --change-set-name v2 --capabilities CAPABILITY_IAM`
2. Xem thay đổi: `aws cloudformation describe-change-set --change-set-name v2 --stack-name prod-api`
3. Nếu thấy resource bị Replace mà không mong muốn, sửa template rồi tạo lại change set
4. Apply: `aws cloudformation execute-change-set --change-set-name v2 --stack-name prod-api`
Lưu ý bước 1: nếu template có tạo IAM resource, bắt buộc --capabilities CAPABILITY_IAM hoặc CAPABILITY_NAMED_IAM, nếu không sẽ báo lỗi InsufficientCapabilities.
Ví dụ 3: Tình huống thi.
Đề: một stack đang ở
UPDATE_ROLLBACK_FAILEDdo một resource bị xoá tay. Cách xử lý?Đáp án: dùng
ContinueUpdateRollbackvà chỉ địnhResourcesToSkipcho tài nguyên lỗi, sau đó sửa lại template cho khớp thực tế.
Thảo luận và suy ngẫm
- Trong team bạn, ai được phép sửa tay trên console? Nếu có người sửa, bạn sẽ phát hiện drift bằng cách nào?
- Với secret trong pipeline, bạn chọn SSM Parameter Store hay Secrets Manager? Tiêu chí nào quyết định (chi phí, rotation, cross-account)?
- Nếu một thay đổi template khiến RDS bị Replace, bạn sẽ chặn nó ở bước nào trong quy trình?
Góc chuyên gia
Vài bẫy mình thấy nhiều người thi trượt vì nó:
- NoEcho không phải mã hoá. Đề rất thích câu "làm sao bảo mật password trong template" và đáp án đúng thường là Secrets Manager hoặc SSM SecureString, không phải
NoEcho. - Change set không bắt buộc. Bạn vẫn update trực tiếp được. Nhưng câu hỏi kiểu "cần xem trước thay đổi trước khi apply" thì đáp án là change set.
- Drift detection không tự fix. Nó chỉ báo. Đọc kỹ đề để không chọn nhầm "CloudFormation tự động đồng bộ".
Resourceslà bắt buộc, mọi section khác optional.- Export không xoá được khi còn stack khác import. Nếu cố xoá, bạn nhận lỗi và phải gỡ
ImportValuetrước. - Nested stack dùng
AWS::CloudFormation::StackvớiTemplateURLphải nằm trên S3, không phải đường dẫn local. CAPABILITY_IAMlà lỗi hay gặp khi deploy qua CLI/pipeline mà quên.- Mẹo thi: khi đề nhắc "hạ tầng như code", "lặp lại được", "rollback tự động" thì nghĩ ngay CloudFormation; khi nhắc "xem trước thay đổi" thì nghĩ change set.
[
{ "front": "Section nào là bắt buộc trong CloudFormation template?", "back": "Resources. Mọi section khác đều tùy chọn." },
{ "front": "Template khác stack ở điểm nào?", "back": "Template là file mô tả tài nguyên; stack là tập tài nguyên đã được tạo và quản lý từ template đó." },
{ "front": "Change set dùng để làm gì?", "back": "Xem trước những thay đổi sẽ áp dụng lên stack trước khi execute." },
{ "front": "NoEcho: true có mã hoá giá trị tham số không?", "back": "Không. Nó chỉ che giá trị trong log/console, không mã hoá." },
{ "front": "Cách an toàn để đưa secret vào template là gì?", "back": "Tham chiếu động resolve:ssm hoặc resolve:secretsmanager, được giải quyết tại thời điểm deploy." },
{ "front": "Stack ở trạng thái UPDATE_ROLLBACK_FAILED thì xử lý thế nào?", "back": "Dùng ContinueUpdateRollback, có thể chỉ định ResourcesToSkip cho tài nguyên lỗi." },
{ "front": "Drift là gì?", "back": "Tài nguyên thực tế khác với định nghĩa trong template, thường do sửa tay ngoài stack." },
{ "front": "Drift detection có tự động sửa tài nguyên không?", "back": "Không. Nó chỉ phát hiện và báo cáo." },
{ "front": "DeletionPolicy: Retain làm gì?", "back": "Giữ lại tài nguyên khi stack bị xoá hoặc tài nguyên bị thay thế." },
{ "front": "Fn::ImportValue dùng để lấy gì?", "back": "Giá trị Output đã được Export từ một stack khác." },
{ "front": "Lỗi InsufficientCapabilities khi deploy thường do thiếu gì?", "back": "Thiếu CAPABILITY_IAM hoặc CAPABILITY_NAMED_IAM khi template tạo tài nguyên IAM." },
{ "front": "Nested stack khai báo bằng resource type nào và TemplateURL lấy từ đâu?", "back": "AWS::CloudFormation::Stack, TemplateURL phải trỏ tới một object trên S3." },
{ "front": "Transform AWS::Serverless-2016-10-31 dùng cho cái gì?", "back": "Chuyển template SAM thành CloudFormation chuẩn khi deploy." }
]
Tóm tắt và bước tiếp theo
Bốn ý mang vào phòng thi:
Resourceslà section bắt buộc; template là bản thiết kế, stack là thực thể, change set là bản xem trước.- Secret phải đi qua SSM SecureString hoặc Secrets Manager bằng tham chiếu
resolve:, không hard-code, không tinNoEcho. - Update fail thì rollback về
UPDATE_ROLLBACK_COMPLETE; kẹt ởUPDATE_ROLLBACK_FAILEDthì dùng ContinueUpdateRollback. - Drift chỉ báo cáo, không tự sửa.
Bài tiếp theo chuyển sang nhóm dịch vụ tích hợp: SQS, SNS, EventBridge và Step Functions. Bạn sẽ học cách chọn đúng dịch vụ cho từng kiểu giao tiếp (queue, pub/sub, event bus, orchestration) và các bẫy hay gặp khi đề hỏi về decoupling.