AWS

[AWS] Github Actions로 ECS 서비스에 배포 (Rolling Update)

KimJeongTae 2023. 12. 29. 20:04

오늘은 Github Actions를 이용하여 Github Repository에 새로운 코드가 push 되었을 때 ECS 서비스에 코드를 반영하는 워크플로를 만들어봅시다.

1. AWS 리소스 준비

Fargate를 사용하는 ECS Service와 ALB를 같이 준비합니다.

Go 애플리케이션은 /v1/color에 접속하면 Red, Green, Yellow를 랜덤으로 반환하게 합니다.

Docker Image를 생성하기 위해 Dockerfile을 작성합니다.

이미지를 가볍게 하기 위해 Multi Stage Build를 사용합니다. 빌드 후 실행파일을 Alpine으로 보내 애플리케이션을 실행합니다.

FROM public.ecr.aws/docker/library/golang:alpine AS builder

WORKDIR /build

COPY go.mod main.go ./

RUN go build -o main .

FROM public.ecr.aws/docker/library/alpine

WORKDIR /app

COPY --from=builder /build/main .

RUN apk --no-cache add curl

CMD ["./main"]

2. Github Actions 설정

Github에서 새 Repository 하나를 생성합니다. 그 후 Settings > Secrets and variables > Actions를 누릅니다.

배포에 필요한 권한을 가지고 있는 IAM User에서 Access Key를 발급받은 후, Repository secrets에서 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY를 각각 등록합니다.

로컬로 Repository를 clone 하여 CI/CD에 필요한 파일들을 작성합니다.

  • .github/workflows/main.yml : CI/CD 워크플로가 진행되는 조건이나 과정 등을 명시합니다. 꼭 .github/workflows에 위치해야 하고, yml 파일 이름은 상관없습니다.
  • Dockerfile, main.go, go.mod : Golang 애플리케이션 빌드 및 실행에 필요한 파일들입니다.

main.yml의 코드는 다음과 같습니다.

  • .on : main 브랜치의 파일들이 push 되었을 때 워크플로가 진행되도록 합니다. workflow_dispatch도 추가하여 수동으로 워크플로를 실행할 수 있게 합니다.
  • .env : 워크플로에 사용되는 환경변수를 정의합니다. (배포 리전, ECR Repository 이름, ECS Service 이름, ECS Cluster 이름, Task Definition의 이름, ECS Service의 Container 이름)
  • .job.deploy.steps
    • Checkout release : Github Repository의 코드를 Github가 제공하는 CI 서버로 전달시킵니다.
    • AWS configure credentials : Secret으로 입력한 Access Key를 등록합니다.
    • Login to Amazon ECR : ECR Repository에 이미지를 저장할 수 있도록 로그인합니다.
    • Build, tag, and push image to Amazon ECR : SHA 해시를 태그로 사용하여 이미지를 빌드하고, ECR Repository로 보냅니다.
    • Download task definition : ECS Task Definition 정보를 다운로드하여 json 파일로 저장합니다.
    • Fill in the new image ID in the Amazon ECS task definition : 새로운 이미지를 사용하여 새로운 Task Definition을 생성합니다.
    • Deploy Amazon ECS task definition : ECS Service가 새로운 버전의 Task Definition을 사용하도록 합니다.
name: Deploy to Amazon ECS

on:
  push:
    branches:
      - main
  workflow_dispatch:

env:
  AWS_REGION: ap-northeast-2
  ECR_REPOSITORY: color
  ECS_SERVICE: color-svc
  ECS_CLUSTER: demo-cluster
  TD_NAME: color-td
  CONTAINER_NAME: color

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        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@v1

      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

      - name: Download task definition
        run: |
          aws ecs describe-task-definition --task-definition $TD_NAME --query taskDefinition > task-definition.json

      - name: Fill in the new image ID in the Amazon ECS task definition
        id: task-def
        uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          task-definition: task-definition.json
          container-name: ${{ env.CONTAINER_NAME }}
          image: ${{ steps.build-image.outputs.image }}

      - name: Deploy Amazon ECS task definition
        uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          task-definition: ${{ steps.task-def.outputs.task-definition }}
          service: ${{ env.ECS_SERVICE }}
          cluster: ${{ env.ECS_CLUSTER }}
          wait-for-service-stability: true

3. CI/CD 테스트

이번에는 Red, Green, Blue를 랜덤으로 반환하도록 코드를 수정해 보겠습니다.

이제 코드를 commit & push 하여 애플리케이션에 반영됐는지 확인해 봅시다.
Github Repository의 Actions 탭에 가보면 CI/CD가 성공적으로 진행된 것을 확인할 수 있습니다.

웹사이트를 새로고침 하면 Red, Green, Blue가 랜덤으로 반환되는 것을 볼 수 있습니다.

오늘의 글은 여기까지입니다. 감사합니다!