🔁 CodePipeline, CodeDeploy và SAM: luồng triển khai chuẩn

Mục tiêu bài học

Sau bài này, bạn sẽ:

  • Mô tả được luồng chuẩn của CodePipeline (source → build → test → deploy) và vai trò của artifact store, service role, stage, action.
  • Phân biệt các deployment type của CodeDeploy (in-place vs blue/green) và các deployment config (AllAtOnce, Canary, Linear).
  • Đọc hiểu file appspec.yml và thứ tự lifecycle hook trên từng compute platform (EC2/On-premises, Lambda, ECS).
  • Giải thích được SAM đóng gói và triển khai ứng dụng serverless như thế nào (sam build, sam package, sam deploy).
  • Tránh được các bẫy hay gặp trong đề thi về rollback, hook và quyền IAM của pipeline.

Ôn nhanh

Bài trước kết luận: IAM quyết định ai được gọi API gì (Deny luôn thắng), KMS quyết định ai được dùng key nào. Hai ý này quay lại ngay trong bài này: pipeline và CodeDeploy đều chạy bằng service role, còn artifact trong S3 bucket nếu mã hoá bằng KMS key thì role của CodePipeline, CodeBuild lẫn CodeDeploy đều phải được cấp quyền dùng key đó. Thiếu một trong hai là pipeline đứng giữa đường.

Lý thuyết

1. CodePipeline: bộ khung điều phối

CodePipeline không tự build, không tự deploy. Nó là orchestrator: mỗi stage chứa một hoặc nhiều action chạy song song, kết quả trung gian lưu vào artifact store (một S3 bucket), rồi chuyển sang stage kế tiếp.

flowchart LR
    Dev["💻<br/>Developer"] --> Src["📥<br/>Source<br/>CodeCommit/GitHub"]
    Src --> Build["🔨<br/>Build<br/>CodeBuild"]
    Build --> Test["🧪<br/>Test<br/>CodeBuild"]
    Test --> Approve["✅<br/>Manual approval"]
    Approve --> Deploy["🚀<br/>Deploy<br/>CodeDeploy / CloudFormation"]
    Deploy --> Prod["🌐<br/>Production"]

Vài chi tiết đề thi rất hay hỏi:

  • Action provider phổ biến: CodeCommit, CodeBuild, CodeDeploy, CloudFormation, S3, ECR, CodeStar Connections (GitHub).
  • Manual approval là một action, thường đặt trước stage deploy production.
  • Có thể disable transition giữa hai stage để chặn pipeline mà không xoá stage.
  • Mọi thay đổi trạng thái đều phát event qua EventBridge, dùng để gắn SNS alert.
  • Artifact phải cùng region với pipeline.

CodeBuild là nơi thực thi thật: buildspec.yml với các phase install, pre_build, build, post_build và mục artifacts, cache.

2. CodeDeploy: đưa code lên máy và kiểm soát traffic

CodeDeploy gồm ba khái niệm: application, deployment group (tập target + config + rollback), và revision (bundle code + appspec.yml).

Nền tảng Deployment type Lifecycle hook theo thứ tự
EC2/On-premises in-place BeforeInstall → Install → AfterInstall → ApplicationStart → ValidateService
EC2/On-premises blue/green BeforeBlockTraffic → BlockTraffic → AfterBlockTraffic → BeforeAllowTraffic → AllowTraffic → AfterAllowTraffic
Lambda blue/green (bắt buộc) BeforeAllowTraffic → AllowTraffic → AfterAllowTraffic
ECS blue/green BeforeInstall → Install → AfterInstall → AllowTestTraffic → AfterAllowTestTraffic → BeforeAllowTraffic → AllowTraffic → AfterAllowTraffic

Deployment config đáng nhớ:

  • EC2: AllAtOnce, HalfAtATime, OneAtATime.
  • Lambda/ECS: Canary10Percent5Minutes, Linear10PercentEvery1Minute, AllAtOnce.

Rollback: CodeDeploy tự rollback khi deployment fail, hoặc khi CloudWatch alarm gắn trong deployment group chuyển sang ALARM (nếu bật rollback configuration).

3. SAM: CloudFormation viết cho serverless

SAM là lớp viết tắt của CloudFormation cho Lambda, API Gateway, DynamoDB. Template SAM có dòng Transform: AWS::Serverless-2016-10-31, dùng resource kiểu AWS::Serverless::Function, và khối Globals để chia sẻ cấu hình chung.

Luồng chuẩn:

sam build          # build dependency, tạo .aws-sam/build
sam package \
  --s3-bucket my-artifact-bucket \
  --output-template-file packaged.yaml   # upload artifact, viết lại template
sam deploy \
  --template-file packaged.yaml \
  --stack-name my-app \
  --capabilities CAPABILITY_IAM          # tạo change set rồi execute

Điểm cần nhớ: sam package không deploy, nó chỉ đẩy artifact lên S3 và thay đường dẫn local bằng S3 URI. sam deploy mới tạo change set và thực thi. Vì vậy câu "zero downtime khi deploy Lambda" thường đi kèm DeploymentPreference trong template: SAM sẽ tự tạo CodeDeploy application và deployment group để dịch chuyển traffic.

Ví dụ minh hoạ

Ví dụ 1: đọc appspec.yml EC2 in-place

version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/html
hooks:
  BeforeInstall:
    - location: scripts/stop_server.sh
      timeout: 300
  AfterInstall:
    - location: scripts/install_deps.sh
  ApplicationStart:
    - location: scripts/start_server.sh
  ValidateService:
    - location: scripts/check_health.sh

Thứ tự chạy: BeforeInstall → (agent copy file vào /var/www/html) → AfterInstall → ApplicationStart → ValidateService. Nếu ValidateService trả exit code khác 0, deployment bị đánh dấu fail và rollback (nếu đã cấu hình). Lưu ý hook Install do agent tự chạy, mình không viết script cho nó.

Ví dụ 2: chọn config cho Lambda

Đề cho "chỉ 10% request vào version mới trong 5 phút đầu, sau đó 90% còn lại". Đáp án là Canary10Percent5Minutes, không phải Linear10PercentEvery1Minute (linear chia đều theo từng phút: 10, 20, 30...).

Ví dụ 3: pipeline cho serverless

Stage 1 Source (CodeCommit) → Stage 2 Build (sam build && sam package, output là packaged.yaml) → Stage 3 Deploy (CloudFormation action, chọn create change set rồi execute change set). Hai bước change set là điều kiện để CodeDeploy chen vào và chạy traffic shifting.

Thảo luận và suy ngẫm

  1. Ứng dụng của bạn chạy trên 4 EC2 sau ALB. Khi nào bạn chọn in-place, khi nào chọn blue/green, và chi phí khác nhau ra sao?
  2. Nếu ValidateService luôn pass dù app chưa sẵn sàng, hậu quả với người dùng là gì? Bạn sẽ thêm kiểm tra gì?
  3. Vì sao tách sam package và sam deploy lại có lợi trong pipeline nhiều môi trường (dev, staging, prod)?

Góc chuyên gia

  • Blue/green không có nghĩa là miễn phí: nó tạo môi trường thứ hai, chuẩn bị sẵn để trả lời câu hỏi "zero downtime" trong đề.
  • Agent là điểm chết người: EC2 phải cài CodeDeploy agent, agent phải chạy, và instance profile phải có quyền gọi CodeDeploy. Câu hỏi "deployment fail ngay ở bước đầu" thường là do thiếu một trong ba thứ này.
  • Script phải có shebang và quyền thực thi, đường dẫn trong hooks là tương đối so với thư mục app đã copy, không phải so với /.
  • Nhớ hook đặc trưng: Lambda chỉ có 3 hook quanh traffic (BeforeAllowTraffic, AllowTraffic, AfterAllowTraffic). EC2 in-place có ValidateService ở cuối. Đề rất thích hỏi "hook nào chạy sau khi traffic đã chuyển".
  • Rollback cần alarm: chỉ bật rollback thôi chưa đủ, phải gắn CloudWatch alarm vào deployment group thì mới rollback theo metric.
  • SAM DeploymentPreference chỉ có tác dụng khi deploy qua CodeDeploy, tức pipeline phải dùng change set hai bước. Dùng "deploy trực tiếp" là mất traffic shifting.
  • Câu thần chú khi làm bài: zero downtime → blue/green; chuyển dần từng phần → Canary; chia đều theo phút → Linear; đơn giản, chấp nhận downtime → in-place AllAtOnce.
  • Artifact bucket mã hoá bằng KMS thì cả ba role (pipeline, CodeBuild, CloudFormation/CodeDeploy) đều cần quyền kms:Decrypt và kms:GenerateDataKey.

Tóm tắt và bước tiếp theo

Bốn ý mang vào phòng thi:

  1. CodePipeline điều phối, CodeBuild thực thi build, CodeDeploy (hoặc CloudFormation) thực thi deploy.
  2. CodeDeploy có in-place (EC2) và blue/green (EC2, Lambda, ECS); mỗi nền tảng có bộ lifecycle hook riêng, học theo bảng ở trên.
  3. Deployment config quyết định tốc độ dịch chuyển traffic: AllAtOnce, Canary, Linear.
  4. SAM = CloudFormation + transform serverless; sam package đẩy artifact lên S3, sam deploy tạo và execute change set.

Kiểm tra nhanh bằng cloze:

  • CodeDeploy đọc file {{c1::appspec.yml}} để biết cách copy file và chạy hook.
  • Trên EC2 in-place, hook chạy cuối cùng là {{c2::ValidateService}}.
  • Lệnh {{c3::sam package}} upload artifact lên S3 và viết lại template.
  • Config {{c4::Canary10Percent5Minutes}} đẩy 10% traffic trong 5 phút rồi phần còn lại.
  • Dòng Transform: {{c5::AWS::Serverless-2016-10-31}} cho CloudFormation biết đây là template SAM.

Bài tiếp theo đi sâu vào CloudFormation: template, stack và change set, nơi bạn sẽ thấy chính xác change set mà sam deploy tạo ra hoạt động thế nào, cách viết template thuần, và cách CloudFormation xử lý update, rollback, drift.

[
  { "front": "Vai trò thật sự của CodePipeline là gì?", "back": "Orchestrator điều phối các stage/action, không tự build hay tự deploy." },
  { "front": "Artifact trung gian của CodePipeline được lưu ở đâu?", "back": "Trong artifact store, thường là một S3 bucket cùng region với pipeline." },
  { "front": "Hai deployment type của CodeDeploy trên EC2 là gì?", "back": "In-place và blue/green." },
  { "front": "Lifecycle hook cuối cùng của EC2 in-place deployment?", "back": "ValidateService." },
  { "front": "Ba lifecycle hook của CodeDeploy khi deploy Lambda?", "back": "BeforeAllowTraffic, AllowTraffic, AfterAllowTraffic." },
  { "front": "Hook nào của EC2 blue/green chặn traffic vào bộ instance cũ?", "back": "BlockTraffic (sau BeforeBlockTraffic, trước AfterBlockTraffic)." },
  { "front": "Deployment config nào chuyển 10% traffic trong 5 phút rồi phần còn lại?", "back": "Canary10Percent5Minutes." },
  { "front": "Deployment config nào chia traffic đều theo từng phút?", "back": "Linear10PercentEvery1Minute." },
  { "front": "Điều kiện để CodeDeploy tự rollback theo metric?", "back": "Deployment group phải gắn CloudWatch alarm và bật rollback configuration." },
  { "front": "sam package làm gì?", "back": "Upload artifact lên S3 và viết lại template với S3 URI, chưa deploy." },
  { "front": "sam deploy làm gì?", "back": "Tạo change set từ template đã đóng gói rồi execute change set đó." },
  { "front": "Dòng Transform nào đánh dấu template SAM?", "back": "AWS::Serverless-2016-10-31." },
  { "front": "DeploymentPreference trong SAM chỉ hoạt động khi nào?", "back": "Khi deploy qua CodeDeploy, tức pipeline dùng change set hai bước (create rồi execute)." },
  { "front": "Ba thứ phải có trên EC2 để CodeDeploy chạy được?", "back": "CodeDeploy agent đang chạy, instance profile có quyền CodeDeploy, và appspec.yml trong bundle." }
]