Trong môi trường production, việc deploy trực tiếp mã nguồn lên hệ thống thật ngay sau mỗi thay đổi luôn tiềm ẩn nhiều rủi ro. Một lỗi chưa được kiểm thử kỹ có thể ảnh hưởng đến người dùng, gây gián đoạn dịch vụ hoặc khiến đội vận hành khó rollback.
Vì vậy, một pipeline CI/CD chuẩn thường cần có môi trường Staging để kiểm thử trước, kèm một bước phê duyệt thủ công trước khi phát hành lên Production.
Trong bài viết này, chúng ta sẽ xây dựng một pipeline CI/CD multi-environment trên AWS, bắt đầu từ GitHub, build bằng AWS CodeBuild, điều phối bằng AWS CodePipeline, deploy tự động lên Staging và chỉ deploy lên Production sau khi có Manual Approval.
Tổng quan kiến trúc hệ thống
Mô hình trong bài viết sẽ vận hành theo luồng end-to-end như sau:
Các stage chính trong pipeline:
Source Stage: Kỹ sư đẩy mã nguồn lên GitHub. AWS CodePipeline nhận sự kiện thay đổi thông qua GitHub connection/webhook.
Build Stage: AWS CodeBuild khởi tạo môi trường build, đọc file buildspec.yml, cài dependencies, chạy các lệnh cần thiết và đóng gói ứng dụng.
Staging Deployment: Artifact sau khi build được deploy tự động lên môi trường Staging trên Elastic Beanstalk.
Manual Approval: Pipeline tạm dừng để QA, Tech Lead hoặc người phụ trách release kiểm tra ứng dụng trên Staging. Nếu mọi thứ hoạt động đúng như kỳ vọng, người review sẽ bấm Approve.
Production Deployment: Ứng dụng được phát hành lên môi trường Production mà không cần SSH vào server hay thao tác thủ công trên máy chủ.
Chuẩn bị hạ tầng
Trước khi cấu hình pipeline, chúng ta cần chuẩn bị nơi triển khai ứng dụng và các IAM Role cần thiết để những dịch vụ AWS có thể làm việc với nhau an toàn.
1. Phân quyền hệ thống với IAM Roles
Một lỗi rất thường gặp khi làm lab CI/CD trên AWS là pipeline build thành công nhưng deploy thất bại vì thiếu quyền. Với Elastic Beanstalk, chúng ta cần chuẩn bị trước 2 role quan trọng.
A. Service Role cho Elastic Beanstalk
Role này cho phép dịch vụ Elastic Beanstalk quản lý và tương tác với các tài nguyên AWS liên quan như Auto Scaling, Load Balancer và health monitoring.
Khi Elastic Beanstalk khởi chạy các EC2 instance bên dưới, các instance này cũng cần quyền để giao tiếp với các dịch vụ AWS liên quan.
Tạo role với thông tin sau:
Service: Elastic Beanstalk
Use case: Elastic Beanstalk – Compute
Tên role: aws-elasticbeanstalk-ec2-role
Policies nên gắn:
AWSElasticBeanstalkWebTier
AWSElasticBeanstalkWorkerTier
AWSElasticBeanstalkMulticontainerDocker
2. Thiết lập môi trường Staging và Production trên Elastic Beanstalk
Trên AWS có nhiều cách để triển khai ứng dụng, tùy vào kiến trúc và mức độ kiểm soát mong muốn: EC2 kết hợp Auto Scaling Group, ECS/Fargate cho container, EKS cho Kubernetes, AWS App Runner cho web service/container đơn giản, Lambda cho serverless, hoặc Elastic Beanstalk cho các ứng dụng web truyền thống cần triển khai nhanh.
Trong phạm vi bài viết này, chúng ta chọn Elastic Beanstalk làm ví dụ triển khai. Lý do là Elastic Beanstalk tích hợp trực tiếp với CodePipeline, tự quản lý các thành phần nền như EC2, Load Balancer, Auto Scaling và Health Check, đồng thời hỗ trợ tạo nhiều environment như Staging và Production trong cùng một Application. Điều này giúp bài lab tập trung vào luồng CI/CD thay vì phải tự cấu hình toàn bộ hạ tầng bên dưới.
Thay vì tạo thủ công từng môi trường và dễ gặp sai lệch cấu hình, chúng ta sẽ tạo môi trường Staging trước, sau đó clone sang Production để hai môi trường có cấu hình nhất quán.
Khởi tạo môi trường Staging (stg-env):
Truy cập Elastic Beanstalk Console và tạo Application mới, ví dụ:
app-express-js-sample-app
Tạo environment đầu tiên bên trong application này:
Platform: Chọn nền tảng phù hợp với source code, ví dụ Node.js chạy trên Amazon Linux 2023.
Application code: Có thể chọn Sample application để environment khởi tạo nhanh trước khi deploy code thật.
Service Access: Chỉ định đúng 2 IAM Role đã tạo ở bước trước:
aws-elasticbeanstalk-service-role
aws-elasticbeanstalk-ec2-role
Nhấn Create và đợi khoảng 3-5 phút để AWS tạo các tài nguyên cần thiết như EC2, Security Group, Load Balancer và domain tạm.
Bước 2.2: Clone môi trường Production (prod-env)
Khi stg-env đã sẵn sàng:
Vào menu Actions ở góc trên bên phải.
Chọn Clone Environment.
Đổi tên môi trường mới thành prod-env.
Giữ nguyên các thông số kỹ thuật và nhấn Clone.
Sau bước này, chúng ta có 2 môi trường độc lập với 2 URL khác nhau:
stg-env: dùng để kiểm thử trước khi release.
prod-env: dùng cho bản production.
3. Tạo CodeBuild Project
AWS CodeBuild giúp chúng ta build ứng dụng trong một môi trường managed, không cần tự duy trì Jenkins server hoặc build server riêng. Dịch vụ này tính phí theo thời gian build thực tế, phù hợp cho các pipeline dạng lab hoặc production nhỏ đến vừa.
Branch: Chọn nhánh cần theo dõi, ví dụ master hoặc main.
Build Stage
Build provider: AWS CodeBuild.
Project name: Chọn CodeBuild project đã tạo ở mục 3.
Deploy Stage Staging
Deploy provider: AWS Elastic Beanstalk.
Application name: Chọn Elastic Beanstalk application đã tạo.
Environment name: Chọn stg-env.
Sau khi hoàn tất, pipeline sẽ tự động kích hoạt lượt chạy đầu tiên, bạn có thể kiểm tra log trực tiếp.
Troubleshooting: Deploy lên Elastic Beanstalk bị failed
Ở lần chạy đầu tiên, bước deploy lên Elastic Beanstalk có thể bị failed nếu role mặc định của CodePipeline chưa đủ quyền để thao tác với Elastic Beanstalk.
Với môi trường lab, cách xử lý nhanh là:
Vào IAM Console.
Tìm role của CodePipeline, thường có dạng AWSCodePipelineServiceRole-*.
Quay lại CodePipeline và nhấn Retry tại stage bị lỗi.
Lưu ý: Cách gắn policy ở trên phù hợp để đơn giản hóa bài lab. Với môi trường production thật, bạn nên giới hạn quyền theo nguyên tắc least privilege, chỉ cấp đúng các action mà pipeline cần.
Thêm Manual Approval và Deploy Production
Sau khi pipeline cơ bản đã chạy ổn đến Staging, chúng ta thêm bước review trước khi phát hành lên Production.
Trong giao diện Pipeline:
Nhấn Edit.
Bên dưới stage deploy Staging, chọn Add stage.
Đặt tên stage mới là Review.
Trong stage Review, chọn Add action group.
Cấu hình action:
Action name: ManualApproval
Action provider: Manual approval
SNS topic: Có thể cấu hình nếu muốn gửi email thông báo cho QA hoặc người phụ trách release.
Tiếp tục thêm stage deploy Production:
Chọn Add stage.
Đặt tên stage là DeployToProd.
Trong stage này, chọn Add action group.
Cấu hình action:
Action name: DeployToProd
Action provider: AWS Elastic Beanstalk
Input artifacts: BuildArtifact
Application name: Chọn application hiện tại.
Environment name: Chọn prod-env.
Nhấn Done và Save để lưu thay đổi.
Kiểm thử end-to-end
Để kiểm tra pipeline, chúng ta thực hiện một thay đổi nhỏ trong source code, ví dụ đổi màu nền giao diện sang màu cam.
Thay đổi trực tiếp code trên github:
Ngay khi push hoàn tất, quay lại AWS CodePipeline. Bạn sẽ thấy Source Stage chuyển sang trạng thái In progress. Sau đó code được đưa qua CodeBuild để đóng gói, rồi deploy tự động lên stg-env.
Khi deploy Staging xong, pipeline sẽ dừng lại ở stage Review và hiển thị trạng thái Waiting for approval.
Chèn hình ảnh: Pipeline dừng tại Manual Approval.
Kiểm tra thực tế:
Truy cập URL của Staging: giao diện đã đổi sang màu cam.
Truy cập URL của Production: giao diện vẫn giữ phiên bản cũ.
Điều này chứng minh thay đổi mới chỉ được triển khai lên Staging và chưa ảnh hưởng đến Production.
Khi đã kiểm tra xong:
Vào stage Manual Approval trong CodePipeline.
Nhấn Review.
Nhập nội dung phê duyệt, ví dụ:
Da kiem tra Staging dat yeu cau, tien hanh phat hanh len Production.
Nhấn Approve.
Pipeline sẽ tiếp tục chạy stage DeployToProd. Sau khoảng 1-2 phút, tải lại URL của Production để xác nhận thay đổi đã được phát hành thành công.
Dọn dẹp tài nguyên
Sau khi hoàn thành bài lab, nên dọn dẹp tài nguyên để tránh phát sinh chi phí ngoài ý muốn.
Thứ tự dọn dẹp đề xuất:
Elastic Beanstalk: Vào Application, chọn Actions, sau đó Delete application. Thao tác này sẽ xóa các environment và những tài nguyên liên quan như EC2, Load Balancer, Auto Scaling Group.
AWS CodePipeline và CodeBuild: Xóa pipeline và build project tương ứng.
S3 Artifact Bucket: CodePipeline thường tạo hoặc sử dụng S3 bucket để lưu artifacts giữa các stage. Vào S3 Console, tìm bucket có tên chứa codepipeline-*, empty bucket trước, sau đó delete bucket.
GitHub Connection: Vào Developer Tools -> Settings -> Connections để xóa connection nếu không còn sử dụng.
Tổng kết
Sau bài lab này, chúng ta đã xây dựng được một pipeline CI/CD cơ bản nhưng có đầy đủ các thành phần quan trọng:
Tự động nhận thay đổi từ GitHub.
Build và đóng gói ứng dụng bằng CodeBuild.
Deploy tự động lên môi trường Staging.
Dừng lại để review bằng Manual Approval.
Chỉ phát hành lên Production sau khi được phê duyệt.
Đây là một mô hình nền tảng rất hữu ích để mở rộng thêm các bước kiểm thử tự động, scan bảo mật, gửi thông báo qua SNS/Slack hoặc triển khai chiến lược release nâng cao hơn trong tương lai.