🚀 Chapter 2 — Automation: Phần B — Thiết lập CD với SSM Agent
Tại sao lại sử dụng SSM thay vì SSH ở production?
Đại khái thì:
- SSH = CodeBuild đăng nhập vào EC2 và chạy lệnh.
- SSM = CodeBuild yêu cầu AWS Systems Manager chạy lệnh trên EC2.
➠ Vì vậy, SSH đơn giản và dễ hiểu hơn để học, còn SSM an toàn và phù hợp hơn khi triển khai production, đặc biệt khi muốn tránh mở SSH port 22 và quản lý private key.
1. Kiến trúc ở chương này

Một số câu hỏi bạn sẽ thắc mắc ở kiến trúc trên:
- Tại sao lại có Docker Build trước khi vào EC2?
- SSM làm những gì?
- Ưu nhược điểm của kiến trúc trên?
Tôi sẽ trả lời ở cuối chương này!
2. Chuẩn bị tài nguyên
Lấy những gì đã setup ở Chapter 2 — Automation: Phần A — Thiết lập CD với AWS CodeBuild + SSH làm cơ sở.
Step 1 — Kiểm tra EC2
SSH vào EC2:
ssh -i ./chapter1-key.pem ubuntu@<EC2_PUBLIC_IP>
Kiểm tra project:
cd ./todo-list-app
docker compose ps
Đảm bảo app đang chạy.
Step 2 — Kiểm tra SSM Agent
Trên EC2:
sudo systemctl status snap.amazon-ssm-agent.amazon-ssm-agent
Nếu thấy:
Active: active (running)
thì OK.
Nếu chưa chạy:
sudo systemctl enable --now snap.amazon-ssm-agent.amazon-ssm-agent
Kiểm tra lại:
sudo systemctl status snap.amazon-ssm-agent.amazon-ssm-agent
Step 3 — Tạo IAM Role cho EC2
Tại sao lại cần tạo IAM Role cho EC2?
- Để SSM Agent chạy bên trong EC2 có thể "báo danh" và nhận lệnh từ dịch vụ AWS Systems Manager, EC2 cần được cấp quyền qua IAM Role.
- Có thể dùng IAM User thay cho IAM Role, nhưng sẽ có rủi ro lộ Access Key
AWS Console:
IAM
↓
Roles
↓
Create role
Chọn:
Trusted entity type:
AWS service
Use case:
EC2
Attach Inline Policy (JSON):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codestar-connections:GetConnectionToken",
"codestar-connections:GetConnection",
"codeconnections:GetConnectionToken",
"codeconnections:GetConnection",
"codeconnections:UseConnection"
],
"Resource": "*"
},
{
"Sid": "AllowSSMSendCommand",
"Effect": "Allow",
"Action": [
"ssm:SendCommand",
"ssm:GetCommandInvocation",
"ssm:ListCommandInvocations",
"ssm:ListCommands"
],
"Resource": "*"
}
]
}
Thiết lập 2 quyền là đọc truy cập Github và SSM
Role name:
chapter2-ec2-ssm-role
Create role.
Step 4 — Gắn Role vào EC2
AWS Console:
EC2
↓
Instances
↓
Chọn EC2 Chapter 1
↓
Actions
↓
Security
↓
Modify IAM role
Chọn:
chapter2-ec2-ssm-role
Save.
Step 5 — Kiểm tra EC2 đã xuất hiện trong Systems Manager
AWS Console:
Systems Manager
↓
Fleet Manager
↓
Managed nodes
EC2 của bạn phải xuất hiện như ảnh:

Nếu Online → tiếp tục.
3. Thực hiện sửa đổi workflow
Step 6 — Tạo IAM Role cho CodeBuild
Vào:
IAM
↓
Roles
↓
Create role
Chọn:
AWS service
↓
CodeBuild
Role name:
chapter2-codebuild-role-ssm
Ở bước này CodeBuild cần quyền để:
CodeBuild
↓
SSM
↓
EC2
Attach:
AmazonSSMFullAccess
Cho lab học tập có thể dùng policy này trước.
Sau khi hiểu flow, có thể chuyển sang IAM policy giới hạn hơn.
Step 7 — Lấy EC2 Instance ID
AWS Console:
EC2
↓
Instances
Copy:
Instance ID
Ví dụ:
i-0123456789abcdef0
Bạn sẽ dùng ID này trong CodeBuild.
Step 8 — Sửa buildspec.yml
Bây giờ buildspec sẽ có thêm bước Deploy.
Ví dụ:
version: 0.2
phases:
install:
commands:
- echo "Installing dependencies..."
build:
commands:
- echo "Running Docker build..."
- docker build -t todo-list-app .
post_build:
commands:
- echo "Deploying to EC2..."
- aws ssm send-command
--instance-ids "i-0123456789abcdef0"
--document-name "AWS-RunShellScript"
--parameters 'commands=["cd ~/todo-list-app","git pull origin main","docker compose build","docker compose up -d"]'
--comment "Deploy Todo App"
Thay:
i-0123456789abcdef0
bằng Instance ID EC2 của bạn.
Step 9 — Quan trọng: kiểm tra Git branch trên EC2
SSH vào EC2:
cd ~/todo-list-app
Kiểm tra:
git branch
Nếu EC2 đang deploy từ main:
* main
thì:
git pull origin main
là đúng.
Nếu EC2 đang dùng branch khác thì sửa lại command tương ứng.
Step 10 — Kiểm tra GitHub authentication trên EC2
Trên EC2:
cd ~/todo-list-app
git pull
Nếu pull được:
Already up to date.
hoặc pull được commit mới → OK.
Bước này quan trọng vì SSM sẽ chạy:
git pull
trên EC2.
Step 11 — Cập nhật CodeBuild project
AWS:
CodeBuild
↓
Build projects
↓
todo-list-ci
↓
Edit
Ở phần:
Environment
chọn service role:
chapter2-codebuild-role
Hãy tạm thời tắt webhook để test codebuild thủ công
Lưu lại.
Step 12 — Commit buildspec.yml
Trên Mac:
git add buildspec.yml
git commit -m "add EC2 deployment"
git push
Step 13 — Start Build thủ công
AWS:
CodeBuild
↓
todo-list-ci
↓
Start build
Flow bây giờ:
DOWNLOAD_SOURCE
↓
INSTALL
↓
BUILD
↓
docker build
↓
POST_BUILD
↓
SSM send-command
↓
EC2 Deploy
Step 14 — Kiểm tra CodeBuild
Trong log:
Deploying to EC2...
Sau đó CodeBuild gọi:
aws ssm send-command
Nếu thành công sẽ có:

Step 15 — Kiểm tra SSM Command
AWS Console:
Systems Manager
↓
Run Command
↓
Command history
Bạn sẽ thấy:

Step 16 — Kiểm tra EC2
SSH vào:
ssh -i ./chapter1-key.pem ubuntu@<EC2_PUBLIC_IP>
cd ~/todo-list-app
Kiểm tra commit:
git log -1
Kiểm tra container:
docker compose ps
Kết quả:
todo-list-app-app-1 Up
todo-list-app-mysql-1 Up
Step 17 — Test bằng thay đổi thật
Trên Mac sửa Todo App.
Ví dụ thay đổi một text trong source.
Sau đó:
git add .
git commit -m "update todo app"
git push
Không cần SSH vào EC2 để deploy nữa.
Step 18 — Kiểm tra website
Mở:
http://<EC2_PUBLIC_IP>
Bạn phải thấy version mới của Todo App.
4. Thiết lập auto deploy
Step 19 — Hoàn thiện Automation
Sau khi manual Start build hoạt động, bật GitHub webhook.
CodeBuild:
todo-list-ci
↓
Edit
↓
Source
↓
Webhook
Bật:
Rebuild every time a code change is pushed
Sau đó test:
git add .
git commit -m "test automatic deployment"
git push
Không cần nhấn Start build.
Chapter 2 sau khi hoàn thành

Điểm quan trọng:
Tại sao lại có Docker Build trước khi vào EC2?
- Ở version này, CodeBuild dùng Docker build để kiểm tra image có build được hay không
- Docker image được build trong CodeBuild không phải image được deploy trực tiếp lên EC2.
SSM làm những gì?
- SSM đóng vai trò là cầu nối thực thi lệnh từ xa an toàn giữa CodeBuild và EC2
- Thực thi trên EC2 qua SSM Agent
Ưu điểm của kiến trúc trên?
- Bảo mật cao hơn SSH
Nhược điểm của kiến trúc trên?
- Lãng phí tài nguyên & thời gian khi build image 2 lần (Thực ra bỏ lần build đầu đi cũng được, nhưng lúc đó tôi nghĩ nên thêm 1 bước kiểm tra tính đúng đắn của docker image nên đã thêm vào)
- Phụ thuộc vào EC2 Environment
Đây là cách đơn giản nhất để hoàn thành Chapter 2 mà chưa cần đưa ECR vào. Sang Chapter 4, khi học Artifact/Governance, ta mới chuyển thành:
CodeBuild
↓
Docker Build
↓
ECR
↓
EC2/ECS/EKS
để thực hiện đúng tư tưởng Build once → Deploy the same artifact.
All rights reserved