Published on

[AWS] - Làm Sao Triển Khai `Realworld Spring Boot App` trên AWS ECS thông qua CodeBuild và CodePipeline?

Authors
  • avatar
    David Nguyen
Table of Contents

1. - Chúng ta sẽ làm gì?

=> Khi mình Google search thử các bài hướng dẫn cấu hình triển khai ứng dụng Spring trên môi trường AWS thì phần lớn các bài viết đều là những bài demo, tức là chỉ deploy một ứng dụng đơn thuần (không có kết nối tới database, không có cấu hình).

=> Câu hỏi là, trong thực tế các ứng dụng Spring nếu được triển khai lên môi trường AWS sẽ như thế nào? Có những cách thức nào? Làm sao đảm bảo kết nối từ ứng dụng tới database, hay làm sao bảo vệ được các thông tin cấu hình nhạy cảm?

Alt text

Flow đơn giản bên trên mô tả cách chạy một ứng dụng Spring dưới dạng Docker container trên môi trường AWS cloud thông qua ECS và ECR.

Thực tế, có nhiều cách để chạy một ứng Spring, ví dụ:

  • Chạy trưc tiếp lệnh java -jar <app-name>.jar.
  • Chạy thông qua các web server như Tomcat, Jetty, GlassFish.
  • Chạy dưới dạng Docker containers.

👉 Bài viết này, mình sẽ cùng anh em tập trung vào cách số 3 và cụ thể là làm sao để AUTOMATICALLY BUILDDEPLOY một ứng dụng Spring Boot thực tế lên môi trường AWS thông qua AWS RDS, CodeBuild, CodePipeline, Secret Manager, ECR, ECS

👉 Toàn bộ flow của hệ thống chúng ta sẽ triển khai trong bài viết này.

Alt text

2. - Setup ứng dụng Spring Boot

NOTE: Nếu bạn nào muốn tập trung vào mục 3 thì có thể tham khảo source code của mình tại đây

2.1 - Ứng dụng này làm gì?

👉 Về nghiệp vụ, đây một ứng dụng Spring Boot đơn giản, cung cấp các APIs cho một hệ thống bán khoá học trực tuyến -> mình tạm gọi là course-service.

  • Tạo khoá học mới: POST /courses
  • Lấy danh sách toàn bộ khoá học: GET /courses

2.2 - Làm sao cấu hình database?

Mình sử dụng Postgres database và dựng luôn trên AWS thông qua AWS RDS. Cụ thể các bước setup mình sẽ đề cập ở mục 3.1

Về phần cấu hình, có hai điểm cần lưu ý:

  • Các thông tin kết nối đến database được mình để dưới dạng tham số và truyền vào trong quá trình runtime để đảm bảo việc bảo mật.
# ========== Database Configuration ==========
spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
  • Sử dụng liquibase để quản lý version các update đối với database.
spring.liquibase.change-log=classpath:/db/liquibase-changelog.xml

2.3 - Làm sao build và run ứng dụng ở local?

Như mình đã đề cập, ứng dụng được triển khai ứng dụng dưới dạng Docker container -> mình có tạo một file Dockerfile cơ bản như sau:

FROM openjdk:17

WORKDIR /app

COPY ./target/course-service.jar /app

EXPOSE 8090

CMD ["java", "-jar", "course-service.jar"]
  • Build ứng dụng -> File .jar
mvn clean install -D DB_URL=<database URL> -D DB_USERNAME=<database name> -D DB_PASSWORD=<database password>
  • Build ứng dụng -> Docker image
docker build -t  course-service:latest .

3. - Setup AWS

3.1 - Dựng Postgres database (AWS RDS)

  • Aurora and RDS -> Databases -> Create database -> PostgresSQL

Alt text

Alt text

  • Free tier and Single-AZ DB instance deployment (1 instance) -> mình dùng free tier cho đỡ mất phí, con nhà nghèo mà =))

Alt text

  • anh em nhập các thông tin cấu hình DB instance identifier, master username, password -> nhớ lưu lại password anh em nhé.

Alt text

  • Check Yes nếu anh em muốn public DB để bên ngoài internet có thể connect được.

Alt text

  • Các thông tin khác anh em có thể để mặc định.

=> Vậy là setup xong database -> anh em có thể vào tab Configuration để xem lại các thông tin cấu hình.

Alt text

3.2 - Cấu hình Secret Manager

  • Ở mục 2.2, mình có đề cập đến việc các tham số cấu hình database sẽ được truyền dưới dạng tham số tại thời điểm runtime. Vậy các thông tin đó được lưu ở đâu?

=> Trong bài viết này, mình sử dụng AWS Secret Manager để lưu như sau:

Alt text

Alt text

Next đến step 4 (Review) -> Store

Alt text

Edit credentials -> thêm một biến là url trỏ đến database.

Alt text

3.3 - Dựng CodeBuild

  • CodeBuild -> Build projects -> Create build project

Alt text

  • Chọn Source provider -> mình chọn GitHub (vì code để trên GitHub). Lưu ý, nếu các bạn chưa kết nối tới GitHub bao giờ thì phải kết nối trước -> Chọn các option như bên dưới.

Alt text

  • buildspec.yaml là các bước để 'hướng dẫn' CodeBuild thực hiện: build project thành file .jar -> build ra Docker image -> đẩy Docker image lên ECR.

  • Các bạn có thể Insert build commands -> Switch to editor -> Paste nội dung file buildspec.yaml vào (LƯU Ý: Phải sửa lại các thông tin cho đúng với AWS account bạn cấu hình). Hoặc check tab Use a buildspec file -> sử dụng file buildpsec.yaml tại root folder của project luôn.

Alt text

  • Để CodeBuild có thể pull image từ ECR và đọc các thông tin cấu hình database trong file buildspec.yaml -> Chúng ta phải cấp quyền cho role được tạo như bên dưới.

Alt text

  • Add permissioins -> Attach policies -> Search AmazonEC2ContainerRegistryFullAccess, AmazonEC2ContainerRegistryPowerUser, SecretsManagerReadWrite

Alt text

Alt text

  • Bấm Start build -> Bắt đầu quá trình build -> Chờ

Alt text

3.4 - Dựng ECR (Elastic Container Registry)

  • ECR là nơi lưu trữ các images (tương tự như DockerHub). Để tạo một ECR:

Amazon ECR -> Private Registy -> Repository -> Create Repository

Alt text

Đặt tên -> Để mặc định các option -> Create

Alt text

3.5 - Dựng ECS (cluster, service, task definition)

=> Tạo Task Definition:

Amazon Elastic Container Service -> Task definition -> Create new task definition

Alt text

Chọn launch type: AWS Fargate

Alt text

Ở mục Task Role -> chọn ecsTaskExecutionRole

Alt text

Lưu Ý: Do chúng ta đọc thông tin cấu hình từ Secret Manager -> Các bạn attach thêm policies là SecretsManagerReadWrite để task có quyền đọc thông tin từ SM.

Alt text

Ở mục Container -> chọn registry -> chọn image -> mapping thêm port 8090 (vì service cấu hình chạy ở port 8090)

Alt text

Ở phần biến môi trường (Environment variables) -> cấu hình để đọc các thông tin database từ Secrets Manager ở mục 3.2

Alt text

Vậy là tạo xong Task definition.

Alt text

=> Tạo Cluster:

Alt text

Alt text

=> Tạo Service:

Alt text

Alt text

Alt text

Alt text

Alt text

3.6 - Dựng CodePipeline

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

Alt text

-> Pipeline build Thành Công

Alt text

-> Pipeline build lại khi có code update.

Alt text

4. - Testing

Sau khi deploy thành công, các bạn truy cập vào địa chỉ: http://<public IP>/swagger-ui/index.html. Trong đó, public IP chính là địa chỉ IP public được tạo ra sau khi chúng tạo task definition thành công.

Alt text

5. - Tổng Kết

Vậy là trong bài viết này mình đã cùng anh em tìm hiểu cách để deloy một ứng dụng Spring Boot thực tế có kết nối đến database lên môi trường Dcoker container thông qua AWS ECS, ECR. Đồng thời tự động hoá việc build và deploy code sử dụng AWS CodeBuild, CodePipeline

Hẹn gặp lại anh em trong các bài viết tiếp theo. Happy Coding!