Github Action을 사용하여 ECR - ECS CI/CD 구축하기

Singsoong·2024년 3월 29일
0

AWS

목록 보기
14/14
post-thumbnail

사내에서 Github Action을 사용하여 프론트엔드 프로젝트의 배포를 자동화한 과정을 공유하려 한다.

📌 순서

dev 도메인
1. 로컬 환경에서 ECR에 푸쉬 후 ECS 수동 배포
2. Github Action 워크플로우 구문(YML)을 작성하여 ECR - ECS 배포 자동화

dev도메인에서의 배포 자동화를 성공적으로 실행했다면, prod 도메인에 대한 워크플로우 구문을 작성하고 prod 도메인에서의 배포를 진행하려 한다.

📌 전략

develop 브랜치에 푸쉬가 되면 Github action의 워크플로우가 실행된다.

📌 로컬환경: ECR - ECS 수동배포

📕 ECR 프라이빗 레지스트리 리포지토리 생성

ECR - 프라이빗 레지스트리 - 리포지토리에서 dev 환경에서 사용할 리포지토리를 생성한다.

📕 ECR 푸쉬

생성한 리포지토리를 체크하고 푸쉬 명령 보기를 클릭하여 해당 리포지토리에 푸쉬하는 명령어를 사용하여 푸쉬한다.

먼저, AWS-CLI가 설치되어야 하고, AWS CLI를 사용해 인증을 진행한다. 이후 도커 이미지를 빌드 한 후 빌드가 완료되면 이미지에 태그를 지정하여 ECR에 푸쉬한다.

정상적으로 푸쉬가 되었다면 위 사진과 같이 확인할 수 있다. 이미지 태그는 latest를 사용하여 관리하는게 좋다. latest로 지정하게 되면 새롭게 도커 이미지를 푸쉬할 때 마다 제일 최신 이미지가 latest로 변경되어 관리에 용이하다. 추후 tdf(task-definition에서 이 latest를 기준으로 ECS에 배포할 것이다)

📕 tdf 작성 (테스크 정의 작성)

tdf는 ECS를 실행시키는데 어떻게 실행시킬지 정의 하는 json 파일이다.
해당 파일에는 어떤 컨테이너의 이름으로 어떤 이미지를 사용할것인지를 정의하고 포트 설정, 환경변수 설정 등을 설정할 수 있다.
새 개정 생성을 눌러 마법사를 통해 JSON 파일을 자동생성할 수도 있고, 곧바로 JSON으로 작성할 수도 있다.

만약, 곧바로 JSON으로 작성한다면,
taskDefinitionArn, revision, requireAttributes, compatibilities와 같이 자동으로 생성되는 Attributes는 작성 안해도 된다. 작성한다면 github action에서 warning을 뱉을 것이지만, 큰 문제는 없다.


테스크 정의 패밀리는 고유한 테스크 패밀리 이름을 지정해야 하고, 개정은 버전이라고 생각하면 된다. 처음 테스크를 만들게 되면 개정은 1이 되고, 그 이후 테스크가 갱신 된다면 개정은 2, 3.. 이렇게 올라갈 것이다. 개정을 지정하여 ECS에 배포할 수 있다.

그 외 인프라 요구사항은 상황에 맞게 선택하면 될 것이다.

생성할 컨테이너 이름을 지정하고 이 컨테이너에 띄울 이미지를 입력하면 된다. 아까 ECR에 만들어둔 이미지 URI(xxxxxx.dkr.ecr.ap-northeast-2.amazonaws.com/dev:latest)를 넣으면 된다.

docker를 실행할 때 환경변수를 설정할 수 있다. ECS 에서는 docker run 명령어를 직접 입력할 수 없기 때문에 여기서 환경변수를 설정할 수도 있다. 환경 변수가 몇개 되지 않는다면 단순히 환경 변수 추가 버튼을 눌러서 추가하면 되고, 만약 환경변수가 많아서 파일로 관리하고 싶다면 환경 파일 추가 버튼을 누르면 된다.

환경 파일 추가를 통해 s3 버킷에서 환경변수 파일을 가져온다면, 위에서 설정한 ECS 테스크 실행 IAM 역할에 S3 객체에 대한 액세스 권한을 부여해야 한다.

📕 인프라 구축 (Route 53 - ELB)

ELB를 생성하기 전에 대상그룹을 정의한다. 대상은 등록하지 않아도 된다. 나중에 ECS를 실행할 때 대상이 동적으로 등록된다.

생성한 대상그룹을 가지고 ELB를 만들고 리스너 및 규칙을 저으이

Route 53에서 사용할 도메인을 선택하고 서브 도메인(dev)을 생성한다.

📕 ECS 생성

클러스터를 만든 후 ECS를 생성한다.

서비스를 선택하고, 만들어두었던 테스크 정의를 선택하여 배포를 진행한다.

📌 배포환경: ECR - ECS 자동화

📕 Github action workflow 작성

프로젝트 루트 경로에서 .github/workflows/타이틀.yml에 깃허브 액션을 통해 실행할 워크플로우를 작성한다.

# 워크플로우 이름
name: Deploy to xxx.com

# develop 브랜치에 푸쉬 되었을 때 워크플로우가 실행됩니다.
on:
  push:
    branches:
      - develop # 해당 브랜치에 머지되면 이 워크플로우가 트리거 된다.

jobs:
  deploy:
    runs-on: ubuntu-latest

    # 변수 설정
    env:
      AWS_REGION: ap-northeast-2
      ECR_REPOSITORY: ECR 레포지토리명
      ECS_SERVICE: ECS 서비스명
      ECS_CLUSTER: ECS 클러스터명
      ECS_TASK_DEFINITION: ./develop-tdf.json # 실행할 TDF, 본인은 프로젝트 안에 tdf를 작성해두어서 경로를 이렇게 설정
      CONTAINER_NAME: 컨테이너 이름

    permissions:
      contents: read

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

      # AWS Config
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        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
        
        # 프로젝트에 주입할 환경변수를 S3 버킷에서 가져와서 프로젝트에 주입
        # 가져와서 이름을 변경함
      - name: Download Environment File from S3 bucket
        run: |
          aws s3 cp s3://경로/프로덕트명-production.env .
          mv ./프로덕트명-production.env ./.env.production

      - 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: |
          # Build a docker container and
          # push it to ECR so that it can
          # be deployed to ECS.
          # 도커 빌드 명령어
          docker build --platform linux/amd64 -t ecr 레포지토리 위치/ecr 레포지토리명:latest -f Dockerfile.production .
          docker push ecr 레포지토리 위치/ecr 레포지토리명:latest
          echo "레포지토리 위치/레포지토리명:latest" >> $GITHUB_OUTPUT

      - 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: ${{ env.ECS_TASK_DEFINITION }}
          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

develop 브랜치에 머지되면,
1. 프로젝트에 주입할 환경변수를 S3 버킷에서 가져와서 프로젝트에 루트폴더에 위치시킨다.
2. 도커 빌드를 진행하고, 빌드된 이미지는 ECR에 latest태그를 붙힌 채로 푸쉬된다.
3. 작성한 tdf에 의해 ECS가 실행되고 배포된다.

develop 브랜치에 머지되면,
1. 프로젝트에 주입할 환경변수를 S3 버킷에서 가져와서 프로젝트에 루트폴더에 위치시킨다.
2. 도커 빌드를 진행하고, 빌드된 이미지는 ECR에 latest태그를 붙힌 채로 푸쉬된다.
3. 작성한 tdf에 의해 ECS가 실행되고 배포된다.

📌 참고

📕 ECR 이미지에 태그 다시 지정하기

// 변수 설정
MANIFEST=$(aws ecr batch-get-image --repository-name ${ecr 레포지토리 이름} --image-ids imageDigest=${변경 당하는 이미지의 다이제스트 (sha256:...)} --query 'images[0].imageManifest' --output text)
aws ecr put-image --repository-name  ${ecr 레포지 토리 이름} --image-tag latest --image-manifest "$MANIFEST"

이렇게 코드를 입력하면 이미지의 latest 태그를 변경한다. latest 태그를 돌리고 싶은 이미지로 지정하고 ECS에서 강제 수동 배포하면 원하는 이미지로 다시 배포할 수 있다.


해당 깃허브 레포지토리에서 Action 탭을 클릭하면 진행되는 워크플로우를 실시간으로 확인할 수 있다. 만약 문제가 생기면 로그도 이쪽에서 나오니 확인하면 된다.

📌 참고한 사이트

Github actions를 이용한 ECS 배포 자동화 - 현구막 기술블로그

이미지에 태그 다시 지정 - AWS

profile
Frontend Developer

0개의 댓글