🚀 Chapter 5 — Platform: Phần J — Triển khai Google Online Boutique từ Amazon ECR qua GitOps lên Amazon EKS
Ở Chapter 5F, chúng ta đã sử dụng Helm và Argo CD để quản lý ba môi trường:
GitHub GitOps Repository
↓
Argo CD
↓
Amazon EKS
↓
Dev / Staging / Production
Tuy nhiên, image của các service vẫn chưa được kết nối hoàn chỉnh với quy trình CI/CD.
Trong phần này, chúng ta sẽ xây dựng flow:
Developer
↓
GitHub Application Repository
↓
GitHub Actions
↓
Docker Build
↓
Amazon ECR
↓
Update image tag trong GitOps Repository
↓
Argo CD
↓
Amazon EKS
↓
Google Online Boutique
Mục tiêu của phần này là:
- Build Docker image bằng GitHub Actions.
- Push image lên Amazon ECR.
- Sử dụng Git commit SHA làm image tag.
- Cập nhật image tag trong GitOps repository.
- Để Argo CD tự động triển khai image mới lên EKS.
- Không sử dụng
kubectl applytrực tiếp từ CI/CD. - Giữ GitOps repository là nguồn dữ liệu chính của deployment.
1. Kiến trúc triển khai
Sau khi hoàn thành Chapter 5J, flow sẽ như sau:
Application Repository
GitHub
│
▼
GitHub Actions
│
┌─────────┴─────────┐
▼ ▼
Test Docker Build
│
▼
Amazon ECR
│
▼
Update GitOps Repository
│
▼
Git commit image tag
│
▼
Argo CD detects change
│
▼
Amazon EKS
│
┌──────────────────────┼──────────────────────┐
▼ ▼ ▼
Dev Staging Production
Trong phần này:
- GitHub Actions chịu trách nhiệm build và push image.
- GitOps repository chịu trách nhiệm lưu image version cần deploy.
- Argo CD chịu trách nhiệm đồng bộ deployment vào EKS.
- EKS chỉ triển khai image version được khai báo trong GitOps repository.
2. Chuẩn bị repository
Chúng ta sử dụng hai repository:
Application repository
Repository chứa source code của Online Boutique:
microservices-demo/
Ví dụ service:
src/
├── frontend/
├── cartservice/
├── paymentservice/
├── checkoutservice/
└── ...
GitOps repository
Repository đã tạo ở Chapter 5F:
online-boutique-gitops/
Cấu trúc hiện tại có thể tương tự:
online-boutique-gitops/
├── helm-chart/
│ ├── Chart.yaml
│ ├── values.yaml
│ ├── values-dev.yaml
│ ├── values-staging.yaml
│ ├── values-production.yaml
│ └── templates/
│ ├── frontend.yaml
│ ├── cartservice.yaml
│ ├── paymentservice.yaml
│ └── ...
│
└── argocd/
├── online-boutique-dev.yaml
├── online-boutique-staging.yaml
└── online-boutique-production.yaml
3. Kiểm tra Amazon ECR
Đặt region sử dụng trong lab:
export AWS_REGION=ap-northeast-1
Kiểm tra AWS Identity:
aws sts get-caller-identity
Kiểm tra danh sách ECR repository:
aws ecr describe-repositories \
--region "$AWS_REGION" \
--query 'repositories[].repositoryName' \
--output table
Kết quả có thể tương tự:
--------------------------------
| DescribeRepositories |
+------------------------------+
| online-boutique/frontend |
| online-boutique/cartservice |
| online-boutique/paymentservice |
+------------------------------+
Nếu chưa có repository cho frontend, tạo repository:
aws ecr create-repository \
--repository-name online-boutique/frontend \
--region "$AWS_REGION"
Kiểm tra lại:
aws ecr describe-repositories \
--repository-names online-boutique/frontend \
--region "$AWS_REGION"
Lấy AWS Account ID:
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity \
--query Account \
--output text)
Tạo biến ECR registry:
export ECR_REGISTRY="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
Kiểm tra:
echo "$ECR_REGISTRY"
Ví dụ:
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com
4. Kiểm tra Docker image của frontend
Di chuyển đến Application repository:
cd microservices-demo
Kiểm tra thư mục frontend:
ls src/frontend
Kiểm tra Dockerfile:
find src/frontend -maxdepth 2 -name 'Dockerfile' -print
Kết quả mong đợi:
src/frontend/Dockerfile
Build thử image local:
docker build \
-t online-boutique-frontend:test \
./src/frontend
Kiểm tra image:
docker images | grep online-boutique-frontend
Nếu build thành công, tiếp tục bước tiếp theo.
5. Kiểm tra image repository trong Helm chart
Di chuyển đến GitOps repository:
cd ../online-boutique-gitops
Tìm cấu hình image hiện tại:
grep -Rni "image:" helm-chart
Hoặc:
grep -Rni "repository:" helm-chart
Mở file values của Dev:
nano helm-chart/values-dev.yaml
Thêm hoặc điều chỉnh cấu hình frontend:
frontend:
image:
repository: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/online-boutique/frontend
tag: test
replicaCount: 1
Thay:
123456789012
bằng AWS Account ID của bạn.
Tên field
image.repositoryvàimage.tagphải khớp với template Helm hiện tại. Nếu chart đang sử dụng tên field khác, cần sửa theo cấu trúc chart của bạn.
Kiểm tra template frontend:
grep -Rni "Values.frontend" helm-chart/templates
Ví dụ template cần có logic tương tự:
image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }}"
Render Helm chart:
helm template online-boutique-dev \
./helm-chart \
--namespace online-boutique-dev \
-f ./helm-chart/values.yaml \
-f ./helm-chart/values-dev.yaml
Nếu không có lỗi, tiếp tục.
6. Tạo cấu hình image cho ba môi trường
Mở file Dev:
nano helm-chart/values-dev.yaml
Ví dụ:
frontend:
replicaCount: 1
image:
repository: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/online-boutique/frontend
tag: test
Mở file Staging:
nano helm-chart/values-staging.yaml
Ví dụ:
frontend:
replicaCount: 2
image:
repository: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/online-boutique/frontend
tag: test
Mở file Production:
nano helm-chart/values-production.yaml
Ví dụ:
frontend:
replicaCount: 3
image:
repository: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/online-boutique/frontend
tag: test
Ở bước đầu, cả ba môi trường dùng tag test.
Sau này GitHub Actions sẽ thay test bằng commit SHA:
a81c92f
7. Kiểm tra Helm chart
Chạy:
helm lint ./helm-chart
Render môi trường Dev:
helm template online-boutique-dev \
./helm-chart \
--namespace online-boutique-dev \
-f ./helm-chart/values.yaml \
-f ./helm-chart/values-dev.yaml \
> /tmp/online-boutique-dev.yaml
Kiểm tra image:
grep -n "image:" /tmp/online-boutique-dev.yaml
Render Staging:
helm template online-boutique-staging \
./helm-chart \
--namespace online-boutique-staging \
-f ./helm-chart/values.yaml \
-f ./helm-chart/values-staging.yaml \
> /tmp/online-boutique-staging.yaml
Render Production:
helm template online-boutique-production \
./helm-chart \
--namespace online-boutique-production \
-f ./helm-chart/values.yaml \
-f ./helm-chart/values-production.yaml \
> /tmp/online-boutique-production.yaml
Kiểm tra image repository:
grep -n "online-boutique/frontend" \
/tmp/online-boutique-dev.yaml
8. Commit cấu hình ECR ban đầu
Kiểm tra thay đổi:
git status
Commit:
git add helm-chart
git commit -m "configure ECR image repository for frontend"
Push:
git push origin chapter-5f-multi-environment
Argo CD sẽ phát hiện thay đổi trong GitOps repository và đồng bộ lại cấu hình.
Kiểm tra Application:
argocd app get online-boutique-dev
Kiểm tra Deployment:
kubectl get deployment frontend \
-n online-boutique-dev
9. Tạo IAM policy cho GitHub Actions
GitHub Actions cần quyền:
- Đăng nhập vào Amazon ECR.
- Push Docker image.
- Ghi các layer của image.
- Kiểm tra image tồn tại.
Tạo file policy:
nano github-actions-ecr-policy.json
Thêm:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ECRAuthentication",
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": "*"
},
{
"Sid": "ECRPush",
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:CompleteLayerUpload",
"ecr:InitiateLayerUpload",
"ecr:PutImage",
"ecr:UploadLayerPart",
"ecr:BatchGetImage",
"ecr:DescribeRepositories"
],
"Resource": "arn:aws:ecr:ap-northeast-1:123456789012:repository/online-boutique/frontend"
}
]
}
Thay:
123456789012
bằng AWS Account ID của bạn.
Tạo IAM policy:
aws iam create-policy \
--policy-name GitHubActionsOnlineBoutiqueECRPush \
--policy-document file://github-actions-ecr-policy.json
Trong production, nên sử dụng GitHub OIDC thay vì lưu AWS Access Key dài hạn trong GitHub Secrets. Phần này có thể được triển khai thành một bài nâng cao riêng.
10. Tạo GitHub Secrets
Trong Application repository, mở:
GitHub
→ Repository
→ Settings
→ Secrets and variables
→ Actions
→ New repository secret
Tạo các secret sau:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_REGION
AWS_ACCOUNT_ID
GITOPS_REPO
GH_PAT
Ví dụ:
AWS_REGION=ap-northeast-1
AWS_ACCOUNT_ID=123456789012
GITOPS_REPO=Juu-dev/online-boutique-gitops
GH_PAT là GitHub Personal Access Token có quyền ghi vào GitOps repository.
Token cần có quyền phù hợp để:
- Clone GitOps repository.
- Sửa file values.
- Commit.
- Push branch.
Không đưa token trực tiếp vào file workflow.
11. Tạo GitHub Actions workflow
Trong Application repository:
mkdir -p .github/workflows
Tạo file:
nano .github/workflows/build-push-update-gitops.yml
Thêm nội dung:
name: Build, Push to ECR and Update GitOps
on:
push:
branches:
- main
paths:
- "src/frontend/**"
- ".github/workflows/build-push-update-gitops.yml"
permissions:
contents: read
env:
AWS_REGION: ${{ secrets.AWS_REGION }}
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
ECR_REPOSITORY: online-boutique/frontend
SERVICE_NAME: frontend
GITOPS_REPOSITORY: ${{ secrets.GITOPS_REPO }}
GITOPS_BRANCH: chapter-5f-multi-environment
jobs:
build-push-update:
name: Build, Push and Update GitOps
runs-on: ubuntu-latest
steps:
- name: Checkout application repository
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Set image variables
id: image
shell: bash
run: |
IMAGE_TAG="${GITHUB_SHA::7}"
ECR_REGISTRY="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
IMAGE_URI="${ECR_REGISTRY}/${ECR_REPOSITORY}:${IMAGE_TAG}"
echo "IMAGE_TAG=${IMAGE_TAG}" >> "$GITHUB_OUTPUT"
echo "IMAGE_URI=${IMAGE_URI}" >> "$GITHUB_OUTPUT"
- name: Run frontend tests
working-directory: src/frontend
run: |
echo "Run frontend tests here"
# Thay bằng lệnh test thực tế của frontend nếu có
- name: Build Docker image
run: |
docker build \
-t "${{ steps.image.outputs.IMAGE_URI }}" \
./src/frontend
- name: Push Docker image to ECR
run: |
docker push "${{ steps.image.outputs.IMAGE_URI }}"
- name: Checkout GitOps repository
uses: actions/checkout@v4
with:
repository: ${{ env.GITOPS_REPOSITORY }}
ref: ${{ env.GITOPS_BRANCH }}
token: ${{ secrets.GH_PAT }}
path: gitops
- name: Update Dev image tag
working-directory: gitops
run: |
python3 - <<'PY'
from pathlib import Path
file_path = Path("helm-chart/values-dev.yaml")
content = file_path.read_text()
old_tag = "tag: test"
new_tag = "tag: ${{ steps.image.outputs.IMAGE_TAG }}"
if old_tag not in content:
raise SystemExit("Could not find the expected image tag in values-dev.yaml")
file_path.write_text(content.replace(old_tag, new_tag, 1))
PY
- name: Commit and push GitOps change
working-directory: gitops
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add helm-chart/values-dev.yaml
git diff --cached --quiet && {
echo "No GitOps changes detected"
exit 0
}
git commit -m "deploy frontend ${{ steps.image.outputs.IMAGE_TAG }} to dev"
git push origin "${{ env.GITOPS_BRANCH }}"
Lưu ý:
- Workflow trên chỉ cập nhật môi trường
dev. stagingvàproductionsẽ được cập nhật ở các bước promotion tiếp theo.- Phần thay thế
tag: testcần được điều chỉnh nếu file values của bạn đang dùng tag khác.
12. Kiểm tra workflow
Kiểm tra file:
cat .github/workflows/build-push-update-gitops.yml
Commit workflow:
git add .github/workflows/build-push-update-gitops.yml
git commit -m "add ECR build and GitOps update workflow"
Push lên branch main:
git push origin main
Mở GitHub:
Repository
→ Actions
→ Build, Push to ECR and Update GitOps
Theo dõi các bước:
Checkout application repository
↓
Configure AWS credentials
↓
Login to Amazon ECR
↓
Run frontend tests
↓
Build Docker image
↓
Push Docker image to ECR
↓
Checkout GitOps repository
↓
Update Dev image tag
↓
Commit and push GitOps change
13. Kiểm tra image trên ECR
Sau khi workflow thành công, chạy:
aws ecr list-images \
--repository-name online-boutique/frontend \
--region "$AWS_REGION"
Hoặc hiển thị image tag:
aws ecr describe-images \
--repository-name online-boutique/frontend \
--region "$AWS_REGION" \
--query 'imageDetails[].imageTags' \
--output table
Kết quả có thể tương tự:
----------------
| imageTags |
+--------------+
| a81c92f |
| test |
+--------------+
Lấy image digest:
aws ecr describe-images \
--repository-name online-boutique/frontend \
--region "$AWS_REGION" \
--query 'imageDetails[].{Tags:imageTags,Digest:imageDigest}' \
--output table
14. Kiểm tra GitOps repository
Clone hoặc cập nhật GitOps repository:
cd ../online-boutique-gitops
git pull origin chapter-5f-multi-environment
Mở file:
cat helm-chart/values-dev.yaml
Kiểm tra tag:
frontend:
image:
repository: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/online-boutique/frontend
tag: a81c92f
Tag a81c92f chính là 7 ký tự đầu của Git commit SHA.
Kiểm tra lịch sử commit:
git log --oneline -5
Kết quả có thể tương tự:
a123456 deploy frontend a81c92f to dev
15. Kiểm tra Argo CD
Xem trạng thái Application:
argocd app get online-boutique-dev
Theo dõi quá trình đồng bộ:
argocd app wait online-boutique-dev \
--sync \
--health
Kiểm tra Deployment:
kubectl get deployment frontend \
-n online-boutique-dev
Kiểm tra Pod:
kubectl get pods \
-n online-boutique-dev \
-l app=frontend
Kiểm tra image thực tế đang chạy:
kubectl get deployment frontend \
-n online-boutique-dev \
-o jsonpath='{.spec.template.spec.containers[*].image}'
Kết quả mong đợi:
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/online-boutique/frontend:a81c92f
Kiểm tra image của Pod:
kubectl get pod \
-n online-boutique-dev \
-l app=frontend \
-o jsonpath='{.items[0].status.containerStatuses[*].imageID}'
16. Kiểm tra toàn bộ flow
Thực hiện một thay đổi nhỏ trong frontend:
cd ../microservices-demo
Ví dụ chỉnh sửa một file frontend:
nano src/frontend/some-file
Commit:
git add src/frontend
git commit -m "update frontend"
Push:
git push origin main
Kiểm tra flow:
Git push
↓
GitHub Actions
↓
Docker Build
↓
Push image lên ECR
↓
Cập nhật values-dev.yaml
↓
GitOps commit
↓
Argo CD sync
↓
EKS rollout
Theo dõi rollout:
kubectl rollout status deployment/frontend \
-n online-boutique-dev
Kiểm tra ReplicaSet:
kubectl get replicasets \
-n online-boutique-dev
Kiểm tra thời gian deploy:
kubectl rollout history deployment/frontend \
-n online-boutique-dev
17. Kiểm tra GitOps drift
Thử thay đổi image trực tiếp trong cluster:
kubectl set image deployment/frontend \
frontend=nginx:latest \
-n online-boutique-dev
Kiểm tra image:
kubectl get deployment frontend \
-n online-boutique-dev \
-o jsonpath='{.spec.template.spec.containers[*].image}'
Argo CD sẽ phát hiện trạng thái thực tế khác với Git.
Kiểm tra:
argocd app get online-boutique-dev
Nếu selfHeal: true đang bật, Argo CD sẽ đưa Deployment về image được khai báo trong GitOps repository.
Kiểm tra lại:
kubectl get deployment frontend \
-n online-boutique-dev \
-o jsonpath='{.spec.template.spec.containers[*].image}'
Kết quả cần quay về:
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/online-boutique/frontend:a81c92f
18. Tách promotion Dev → Staging → Production
Ở bước trước, GitHub Actions chỉ cập nhật Dev.
Flow hiện tại:
Build image
↓
Push ECR
↓
Update Dev
↓
Argo CD deploy Dev
Sau khi Dev được kiểm tra thành công, chúng ta có thể promote cùng image tag sang Staging.
Ví dụ mở file:
nano helm-chart/values-staging.yaml
Thay:
frontend:
image:
tag: test
thành:
frontend:
image:
tag: a81c92f
Commit:
git add helm-chart/values-staging.yaml
git commit -m "promote frontend a81c92f to staging"
git push origin chapter-5f-multi-environment
Kiểm tra:
argocd app get online-boutique-staging
Sau khi Staging được kiểm tra, promote cùng tag sang Production:
nano helm-chart/values-production.yaml
Thay:
frontend:
image:
tag: test
thành:
frontend:
image:
tag: a81c92f
Commit:
git add helm-chart/values-production.yaml
git commit -m "promote frontend a81c92f to production"
git push origin chapter-5f-multi-environment
Điểm quan trọng:
Không build lại image cho từng môi trường.
Chúng ta sử dụng cùng một image:
frontend:a81c92f
cho:
Dev
↓
Staging
↓
Production
19. Kiểm tra rollback bằng Git
Giả sử image mới gây lỗi:
frontend:a81c92f
Tìm commit trước đó:
git log --oneline -- helm-chart/values-production.yaml
Rollback bằng Git revert:
git revert <COMMIT_ID>
Push:
git push origin chapter-5f-multi-environment
Argo CD sẽ phát hiện commit mới và triển khai lại image version cũ.
Kiểm tra:
argocd app get online-boutique-production
Kiểm tra image:
kubectl get deployment frontend \
-n online-boutique-production \
-o jsonpath='{.spec.template.spec.containers[*].image}'
20. Kiểm tra cuối cùng
Kiểm tra ECR
aws ecr describe-images \
--repository-name online-boutique/frontend \
--region "$AWS_REGION"
Kiểm tra GitOps
git log --oneline -5
Kiểm tra Argo CD
argocd app list
Kiểm tra EKS
kubectl get pods -n online-boutique-dev
kubectl get pods -n online-boutique-staging
kubectl get pods -n online-boutique-production
Kiểm tra image của từng môi trường
kubectl get deployment frontend \
-n online-boutique-dev \
-o jsonpath='{.spec.template.spec.containers[*].image}'
kubectl get deployment frontend \
-n online-boutique-staging \
-o jsonpath='{.spec.template.spec.containers[*].image}'
kubectl get deployment frontend \
-n online-boutique-production \
-o jsonpath='{.spec.template.spec.containers[*].image}'
Kết quả mong đợi:
Dev → frontend:a81c92f
Staging → frontend:a81c92f
Production → frontend:a81c92f
21. Kiến trúc cuối Chapter 5J
Developer
│
▼
GitHub Application Repo
│
▼
GitHub Actions
│
┌──────────┴──────────┐
▼ ▼
Test Docker Build
│
▼
Amazon ECR
│
▼
Image tag từ Git SHA
│
▼
GitOps Repository
│
▼
Argo CD
│
▼
Amazon EKS
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
Dev Staging Production
Kết quả đạt được
Sau Chapter 5J:
- GitHub Actions build Docker image.
- Docker image được lưu trong Amazon ECR.
- Image tag được tạo từ Git commit SHA.
- GitOps repository lưu image version cần triển khai.
- Argo CD tự động đồng bộ thay đổi từ Git.
- EKS triển khai image từ ECR.
- Dev, Staging và Production sử dụng cùng một artifact.
- Có thể rollback bằng
git revert. - Không cần chạy
kubectl applytrực tiếp từ GitHub Actions.
Đây là flow:
Build once
↓
Store in ECR
↓
Promote through Git
↓
Deploy with Argo CD
Lưu ý: Trong production thực tế, nên thay AWS Access Key bằng GitHub OIDC, sử dụng image digest thay vì chỉ image tag, bật ECR image scanning, và thiết lập approval trước khi promote Production.
All rights reserved