CodePipeline: Nối Source, Build, Deploy Thành Dây Chuyền
Bốn Part đầu xây từng mảnh: code trên CodeCommit, build bằng CodeBuild, deploy bằng CodeDeploy. Nhưng mỗi mảnh ta vẫn kích hoạt bằng tay — gõ start-build, gõ create-deployment. Đó chưa phải CI/CD; đó là các bước rời. CodePipeline là nhạc trưởng nối chúng thành một dây chuyền tự động: có commit mới là cả chuỗi Source → Build → Deploy tự chạy. Bài này dựng pipeline đầu tiên.
💰 Chi phí
Pipeline deploy lên một EC2 t3.micro (target in-place). CodePipeline tính theo pipeline hoạt động (có một mức free-tier). Giữ pipeline + target cho bài 13–14, dọn ở cuối Part V.
Mục tiêu
Hiểu cấu trúc CodePipeline (stage, action, artifact), dựng pipeline ghép ba dịch vụ đã học, và thấy artifact chảy giữa các stage ra sao.
Stage, action, artifact
CodePipeline mô hình hóa quy trình thành các stage chạy tuần tự, mỗi stage chứa các action. Mỗi action sinh ra output artifact (gói file) cất ở một artifact store (bucket S3), và stage sau nhận input artifact là output của stage trước. Đó là cách dữ liệu chảy: Source cho ra mã nguồn, Build nhận mã nguồn và cho ra gói đã build, Deploy nhận gói đã build và đưa lên server.
Ta dùng pipeline type V2 — bản hiện hành, hỗ trợ biến, trigger lọc, và tính theo lần chạy.
Service role và artifact store
Pipeline cần service role (trust codepipeline.amazonaws.com) với quyền: đọc/ghi bucket artifact, lấy code từ CodeCommit, gọi CodeBuild, gọi CodeDeploy. Đây là role điều phối — nó gọi các dịch vụ, còn mỗi dịch vụ vẫn chạy dưới role riêng của nó (CodeBuild dưới role bài 2, CodeDeploy dưới role bài 8). Artifact store là bucket S3 đã tạo ở bài 2 (đã bật versioning — chính vì pipeline).
Định nghĩa pipeline
Pipeline khai bằng JSON, ba stage nối nhau:
{
"pipeline": {
"name": "awscicd-pipeline",
"roleArn": "arn:aws:iam::111122223333:role/awscicd-codepipeline-role",
"artifactStore": {"type": "S3", "location": "awscicd-artifacts-111122223333-ap-southeast-1"},
"pipelineType": "V2",
"stages": [
{"name": "Source", "actions": [{
"name": "Source",
"actionTypeId": {"category": "Source", "owner": "AWS", "provider": "CodeCommit", "version": "1"},
"configuration": {"RepositoryName": "awscicd-demo-app", "BranchName": "main"},
"outputArtifacts": [{"name": "SourceOutput"}]
}]},
{"name": "Build", "actions": [{
"name": "Build",
"actionTypeId": {"category": "Build", "owner": "AWS", "provider": "CodeBuild", "version": "1"},
"configuration": {"ProjectName": "awscicd-demo-build"},
"inputArtifacts": [{"name": "SourceOutput"}],
"outputArtifacts": [{"name": "BuildOutput"}]
}]},
{"name": "Deploy", "actions": [{
"name": "Deploy",
"actionTypeId": {"category": "Deploy", "owner": "AWS", "provider": "CodeDeploy", "version": "1"},
"configuration": {"ApplicationName": "awscicd-demo", "DeploymentGroupName": "awscicd-demo-dg"},
"inputArtifacts": [{"name": "BuildOutput"}]
}]}
]
}
}
Để ý dây nối: Source outputArtifacts: SourceOutput → Build inputArtifacts: SourceOutput, rồi Build outputArtifacts: BuildOutput → Deploy inputArtifacts: BuildOutput. Tên artifact chính là cách các stage nối với nhau.
$ aws codepipeline create-pipeline --cli-input-json file://pipeline.json \
--query 'pipeline.[name,pipelineType]' --output text
awscicd-pipeline V2
Pipeline tự chạy
Tạo xong, pipeline tự khởi chạy ngay lần đầu. Poll trạng thái từng stage:
$ aws codepipeline get-pipeline-state --name awscicd-pipeline \
--query 'stageStates[].[stageName,latestExecution.status]' --output text
Source:InProgress Build:None Deploy:None
Source:Succeeded Build:InProgress Deploy:None
Source:Succeeded Build:Succeeded Deploy:InProgress
Source:Succeeded Build:Succeeded Deploy:Succeeded
Cả ba stage chạy lần lượt và Succeeded. Toàn bộ chuỗi — kéo code, build, test, deploy lên EC2 — chạy mà không gõ một lệnh nào sau khi tạo pipeline. Kiểm chứng app lên server:
$ curl http://<ec2-public-ip>/
... awscicd demo app — v2 ...
Artifact chảy giữa các stage
Đây là cơ chế đáng mổ. Mỗi stage không tự lấy lại code từ đầu — nó nhận output của stage trước qua artifact store. Cụ thể:
- Source kéo code từ CodeCommit, đóng thành
SourceOutput(zip), đẩy lên bucket artifact. - Build lấy
SourceOutputlàm input (không tự clone CodeCommit nữa — CodeBuild trong pipeline dùng artifact đầu vào thay cho source khai trong project), chạybuildspec.yml, cho raBuildOutputchứaindex.html+appspec.yml+scripts/. - Deploy lấy
BuildOutputlàm revision; vì gói này cóappspec.ymlở gốc, CodeDeploy biết cách triển khai.
commit → CodeCommit (main)
│ trigger
┌──────────────── CodePipeline awscicd-pipeline (V2) ────────────────┐
│ Source Build Deploy │
│ CodeCommit ──────▶ CodeBuild ────────▶ CodeDeploy │
│ out:SourceOutput in:SourceOutput in:BuildOutput │
│ out:BuildOutput (in-place EC2) │
└──────┬──────────────────┬──────────────────────┬───────────────────┘
└── artifact store S3 (mỗi stage đọc output stage trước) ──┘
▼
curl http://<ec2>/ → v2
Điểm mấu chốt: artifact là hợp đồng giữa các stage. Build không cần biết Source lấy code từ đâu, Deploy không cần biết Build làm gì — mỗi stage chỉ nhận một gói, làm việc của mình, đưa ra một gói. Nhờ vậy thay từng mảnh được: đổi nguồn từ CodeCommit sang khác chỉ sửa stage Source, phần còn lại không đụng.
Trigger: chạy khi có commit
Lần chạy đầu là do tạo pipeline. Từ đó về sau, pipeline tự chạy mỗi khi nhánh main của CodeCommit có commit mới — CodePipeline dựng sẵn một quy tắc EventBridge để bắt sự kiện đó (trigger type hiện là PollForSourceChanges hoặc qua EventBridge tùy cấu hình). Nghĩa là từ giờ, lập trình viên chỉ cần git push, và dây chuyền lo phần còn lại tới khi code chạy trên server.
🧹 Dọn dẹp
Pipeline và EC2 target dùng tiếp ở bài 13–14, nên giữ tới hết Part V. Khi dọn:
$ aws codepipeline delete-pipeline --name awscicd-pipeline
$ aws ec2 terminate-instances --instance-ids <target-iid>
Tổng kết
CodePipeline nối các chặng thành dây chuyền: stage chạy tuần tự, mỗi action sinh artifact, stage sau nhận artifact của stage trước qua artifact store S3. Ta dựng pipeline V2 ba stage — Source (CodeCommit) → Build (CodeBuild) → Deploy (CodeDeploy) — chạy dưới một service role điều phối, và nó tự chạy end-to-end ngay khi tạo, đưa app lên EC2 không cần thao tác tay. Artifact là hợp đồng giữa các stage (SourceOutput → BuildOutput), nên mỗi mảnh thay được độc lập. Từ đây, git push là đủ để kích hoạt cả chuỗi.
Bài tới làm pipeline thực dụng hơn cho production: thêm cổng phê duyệt thủ công trước khi deploy, chạy nhiều action song song, và lọc trigger theo nhánh — những thứ biến một pipeline "chạy được" thành một pipeline "dùng được ở công ty".