Logo
Featured Image

Terraform EKS CI/CD: Cloud-Native với AWS CodeBuild & ECR

Author
Tobi 21/04/2026 3 views

Bài trước chúng ta đã xây dựng Hệ Thống AWS EKS kết hợp RDS, S3, Lambda và CI/CD với Jenkins .

Trong bài lab này, chúng ta sẽ thực hiện một cuộc "đại tu" kiến trúc: Loại bỏ Jenkins server truyền thống và thay thế bằng hệ sinh thái CI/CD Cloud-Native của AWS (CodeBuild, ECR). Toàn bộ hạ tầng sẽ được quản lý bằng Terraform, đảm bảo tính tự động hóa 100%, bảo mật tuyệt đối và tiết kiệm chi phí (Pay-as-you-go).

Dự án mẫu được sử dụng là OriShop (Spring Boot), triển khai trên Amazon EKS, sử dụng Amazon RDS (MySQL) và Amazon S3 (lưu trữ ảnh) thông qua cơ chế IRSA.

Phần 1: Khai báo Hạ tầng bằng Terraform (Infrastructure as Code)

Để hệ thống hoạt động đồng bộ, chúng ta cần định nghĩa kho chứa Docker Image (ECR), Quyền truy cập (IAM) và Dây chuyền Build (CodeBuild).

1. Tạo kho lưu trữ ECR (ecr.tf)

Thay vì dùng Docker Hub, chúng ta dùng ECR để tối ưu tốc độ và bảo mật trong nội mạng AWS.

resource "aws_ecr_repository" "orishop_repo" {
  name                 = "orishop-repo"
  image_tag_mutability = "MUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }

  tags = {
    Environment = "Production"
    Project     = "com.quyenlt"
  }
}

output "ecr_repository_url" {
  value = aws_ecr_repository.orishop_repo.repository_url
}

2. Cấp "Lệnh bài" IAM cho CodeBuild (iam.tf)

CodeBuild cần quyền đẩy Image lên ECR và quyền gõ lệnh kubectl vào cụm EKS.

resource "aws_iam_role" "codebuild_role" {
  name = "quyenlt-codebuild-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = { Service = "codebuild.amazonaws.com" }
    }]
  })
}

resource "aws_iam_role_policy" "codebuild_policy" {
  role = aws_iam_role.codebuild_role.name
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = ["ecr:*", "eks:DescribeCluster", "eks:ListClusters", "logs:*", "s3:*"]
        Resource = "*"
      }
    ]
  })
}

3. Khai báo CodeBuild và Webhook (pipeline.tf)

Đoạn code này định nghĩa bộ máy CodeBuild và cấu hình Webhook để tự động trigger mỗi khi có code push lên nhánh main.

resource "aws_codebuild_project" "orishop_build" {
  name          = "orishop-build-project"
  service_role  = aws_iam_role.codebuild_role.arn

  artifacts { type = "NO_ARTIFACTS" }

  environment {
    compute_type    = "BUILD_GENERAL1_SMALL"
    image           = "aws/codebuild/amazonlinux2-x86_64-standard:5.0"
    type            = "LINUX_CONTAINER"
    privileged_mode = true # Bắt buộc để build Docker
  }

  source {
    type      = "GITHUB"
    location  = "https://github.com/tobi1008/orishop.git"
    buildspec = "buildspec.yml"
  }
}

# Tự động kích hoạt khi Push vào nhánh main
resource "aws_codebuild_webhook" "orishop_webhook" {
  project_name = aws_codebuild_project.orishop_build.name
  build_type   = "BUILD"
  filter_group {
    filter { type = "EVENT", pattern = "PUSH" }
    filter { type = "HEAD_REF", pattern = "^refs/heads/main$" }
  }
}

4. Nối quyền Admin EKS cho CodeBuild

Trong module EKS của Terraform, bổ sung access_entries để cho phép IAM Role của CodeBuild trở thành Admin của cluster.

  access_entries = {
    codebuild_admin = {
      kubernetes_groups = []
      principal_arn     = aws_iam_role.codebuild_role.arn
      policy_associations = {
        admin_policy = {
          policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy"
          access_scope = { type = "cluster" }
        }
      }
    }
  }


Phần 2: Cấu hình Source Code và Docker

1. Vượt Rate Limit của Docker Hub bằng AWS Public ECR

Khi build trên CodeBuild, IP của AWS dễ bị Docker Hub chặn do vượt quá 100 request/6 giờ (Lỗi 429). Giải pháp là dùng bản sao lưu trên kho AWS Public ECR.

Sửa file Dockerfile:

# Sử dụng kho Public ECR của AWS thay vì Docker Hub
FROM public.ecr.aws/docker/library/maven:3.9.4-eclipse-temurin-17 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests

# Image siêu nhẹ cho production
FROM public.ecr.aws/docker/library/eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8091
ENTRYPOINT ["java", "-jar", "app.jar"]

2. Trái tim của Pipeline: buildspec.yml

File này đặt ở thư mục gốc của project, chỉ thị cho CodeBuild các bước đóng gói và triển khai. Đặc biệt chú ý bước kubectl apply để khởi tạo App trước khi set image nhằm tránh lỗi Deployment NotFound.

version: 0.2
phases:
  install:
    commands:
      - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
      - chmod +x kubectl && mv kubectl /usr/local/bin/
  pre_build:
    commands:
      - aws ecr get-login-password --region ap-southeast-1 | docker login --username AWS --password-stdin 808999395759.dkr.ecr.ap-southeast-1.amazonaws.com
      - REPOSITORY_URI=808999395759.dkr.ecr.ap-southeast-1.amazonaws.com/orishop-repo
      - IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
  build:
    commands:
      - mvn clean package -DskipTests
      - docker build -t $REPOSITORY_URI:latest .
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - aws eks update-kubeconfig --name quyenlt-eks-cluster --region ap-southeast-1
      # Khởi tạo App nếu chưa có
      - kubectl apply -f orishop-eks.yaml 
      # Ghi đè phiên bản Image mới
      - kubectl set image deployment/orishop-app orishop=$REPOSITORY_URI:$IMAGE_TAG


Phần 3: Triển Khai Thực Tế

1. Nạp Token GitHub cho AWS

Nếu bạn chưa tạo Token trên GitHub, hãy vào GitHub > Settings > Developer settings > Personal access tokens (classic) > Tạo 1 cái Token có tick chọn quyền repoadmin:repo_hook (quyền để AWS tự động gắn Webhook).

Sau khi có cái chuỗi Token (ghp_xxxxxxxx...)

Để Terraform có thể tạo Webhook và CodeBuild có thể kéo code, bạn cần cấp Token của GitHub cho tài khoản AWS thông qua CLI:

aws codebuild import-source-credentials \
    --server-type GITHUB \
    --auth-type PERSONAL_ACCESS_TOKEN \
    --token <GITHUB_PAT_TOKEN> \
    --region ap-southeast-1

Tới đây sau này bạn push code sẽ áp dụng cấu hình trên terraform và tạo ra webhook tới codebuild của AWS luôn rồi :

2. Apply Hạ Tầng

Mở Terminal ở thư mục Terraform và chạy:

terraform init
terraform apply

3. Cấu trúc Database (RDS)

Vì RDS khởi tạo trống trơn, ta cần dùng một Pod tạm trên EKS để bơm cấu trúc database ban đầu (datalast1.sql).

🛠️ Bước 1: Cập nhật lại Kubeconfig
Bro mở Terminal trên Mac và gõ lệnh này để AWS nạp lại địa chỉ cụm EKS mới vào máy:

aws eks update-kubeconfig --region ap-southeast-1 --name quyenlt-eks-cluster

🛠️ Bước 2: Tạo lại con Pod "Đặc vụ"
Vì cụm EKS hiện tại là cụm mới tinh tình tình, chưa có cái Pod nào bên trong cả, nên bro phải thả con tmp-mysql-client vào lại:

kubectl run tmp-mysql-client --image=mysql:8.0 --command -- sleep 3600

Import dữ liệu :

kubectl exec -i tmp-mysql-client -- mysql -h orishop-db.ch8mw2wuqs14.ap-southeast-1.rds.amazonaws.com -u admin -pOriShop12345! orishop < datalast1.sql

Bước 3 : Xóa giải phóng pod

kubectl delete pod tmp-mysql-client

 

Đi xem "Nhà máy" hoạt động

Bạn khoan vội sửa code, hãy tận hưởng thành quả setup đã.

  1. Mở trình duyệt, đăng nhập vào AWS Console.

  2. Gõ vào thanh tìm kiếm: CodeBuild và chọn nó.

  3. Bạn sẽ thấy cái pipeline orishop-build-project đang ở trạng thái In Progress (Đang chạy).

  4. Bạn bấm vào nút Details (Chi tiết) ở giai đoạn Build để xem tận mắt anh thợ CodeBuild đang gõ lệnh Maven và build Docker Image trực tiếp trên Cloud như thế nào nhé. Phê hơn xem log Jenkins nhiều!

Nếu thành công sẽ có trạng thái như này :


Phần 4: Trải nghiệm GitOps hoàn chỉnh

Mọi thiết lập đã hoàn tất. Giờ đây, quy trình vận hành chỉ còn lại 1 thao tác duy nhất đối với Developer:

git add .
git commit -m "Feature: Awesome new updates"
git push origin main
 

Ngay lập tức, GitHub Webhook sẽ gọi sang AWS CodeBuild. Quá trình lấy code ➔ Maven Build ➔ Docker Build ➔ ECR Push ➔ EKS Deploy sẽ diễn ra hoàn toàn tự động và bảo mật thông qua IAM Roles.

Kết quả: Hệ thống CI/CD ổn định, không tốn phí duy trì Server (như Jenkins), dễ dàng tái tạo thông qua Terraform và loại bỏ hoàn toàn việc lưu trữ lộ liễu file kubeconfig.

Chạy lệnh kubectl get svc để lấy link truy cập kiểm tra thử nhé.

Bình luận (0)

+ =
Zalo