EB → ECS 마이그레이션을 위한 Github Action 수정

status
publish
thumbnail
date
Nov 23, 2024
slug
migrate-from-eb-to-ecs-with-github-action
summary
AWS Elastic Beanstalk(EB)에서 AWS ECS로 인프라 구성을 수정하면서 Github Action으로 연결되어 있던 CI/CD 방식을 수정해야하는 상황이 발생했다.

변경 점

기존에는 EB에게 Dockerrun.aws.json 파일을 생성하여 ‘이런 식으로 task definition 만들어줘~’ 하는 느낌이었다면 이제는 직접 task definition을 작성하고 구성해야한다.
task definition의 메모리, CPU 등등 인프라 설정은 한번 설정하면 거의 바뀌지 않는다.
따라서 새로 배포되어야 할 기능이 반영된 Docker Image를 사용하도록 환경을 수정하면 되기 때문에 아래와 같은 단계를 거치도록 수정하였다.
  1. 현재 배포되어 있는 task definition 불러오기
  1. 새롭게 빌드된(배포할) Docker Image 사용하도록 task definition 수정
  1. 수정된 새로운 task definition 배포

task definition 불러오기

다행히 공식으로 제공되는 AWS CLI가 Github Action에서 task definition을 불러오게 해준다. 🥹
- name: Download task definition run: | aws ecs describe-task-definition \ --task-definition task-definition-name \ --query taskDefinition \ > task-definition.json
위 명령어를 통해 task-definition.json 이란 이름의 JSON으로 저장이 되게 된다.

주의 사항

위 방식을 이용하는 경우 task-definition-name 으로 지정된 task-definition이 1개 이상 AWS에 저장되어 있어야한다. 다시 말해 AWS 대시보드(홈페이지)를 통해 수동으로 task-definition을 한번 등록을 해줘야 한다.
만약 처음 등록부터 Github Action을 통하고 싶다면 register-task-definition 명령어를 이용해보자.
  • describe-task-definition 에서 오류 발생 (등록된 task-definition 없음) → register-task-definition 실행
이런 식으로 구성을 하면 되겠다. 필자는 첫 task-definition 구성은 AWS 대시보드를 통하는게 실수를 줄이고 명확한 것 같아서 사용하지 않았다.

task definition 수정

불러온 task-definition.json은 가장 최신(대부분 현재 배포되어 있는) task definition이기 때문에 배포를 위해서는 Docker Image 이름을 새롭게 작성해줘야 한다.
JSON에서 Docker Image 이름을 수정하기 위해 AWS에서 제공하는 Action을 사용한다.
이때 containerDefinitions에서 multi container를 이용하는 경우 Action에 반환 값을 이용하면 된다.

Multi Container 환경

- name: Render Amazon ECS task definition for first image id: render-first-image uses: aws-actions/amazon-ecs-render-task-definition@v1 with: task-definition: task-definition.json container-name: first-container image: first-image-name
위 처럼 첫번째 Action에서 반환되는 값은 첫번째 Docker Image 주소(ECR 주소)가 수정된 task definition이다. 이때 container-name 값은 task definition에 등록된 이름과 동일해야 한다.
- name: Modify Amazon ECS task definition with second image id: render-second-image uses: aws-actions/amazon-ecs-render-task-definition@v1 with: task-definition: ${{ steps.render-first-container.outputs.task-definition }} container-name: second-container image: second-image-name
따라서 이를 두번째 Action의 task-definition 의 값으로 사용하면 된다.

task definition 배포

- name: Deploy to Amazon ECS service uses: aws-actions/amazon-ecs-deploy-task-definition@v2 with: task-definition: 완성된 task definition service: my-service cluster: my-cluster
배포는 해당 Action을 통해 간단히 가능하다. 배포될 Docker Image 이름이 전부 수정된 task definition 파일을 전달하면 배포가 가능하다.

정리

# 0. Docker Image Build 및 Docker Image 이름 추출 - name: Create Docker Image Name id: create-image-name run: | echo "first-image" >> $GITHUB_OUTPUT echo "second-image" >> $GITHUB_OUTPUT # 1. Task Definition 불어오기 - name: Download task definition id: download-task-definition run: | aws ecs describe-task-definition \ --task-definition task-definition-name \ --query taskDefinition \ > task-definition.json result=task-definition.json echo "task-definition=$result" >> $GITHUB_OUTPUT # 2. Task Definition 수정 (Docker Image 수정) - name: Render Amazon ECS task definition for first image id: replace-first-image uses: aws-actions/amazon-ecs-render-task-definition@v1 with: task-definition: ${{ steps.download-task-definition.outputs.task-definition }} container-name: first-container image: ${{ steps.create-image-name.outputs.first-image }} - name: Modify Amazon ECS task definition with second image id: replace-second-image uses: aws-actions/amazon-ecs-render-task-definition@v1 with: task-definition: ${{ steps.render-first-image.outputs.task-definition }} container-name: second-container image: ${{ steps.create-image-name.outputs.second-image }} # 3. Task Definition 배포 - name: Deploy to Amazon ECS service uses: aws-actions/amazon-ecs-deploy-task-definition@v2 with: task-definition: ${{ steps.replace-second-container.outputs.task-definition }} service: my-service cluster: my-cluster
위에서 설명한 3단계를 순차적으로 구성했다. 0단계에 해당하는 Docker Image Build 단계는 자세히 다루지 않았지만, 결국 새로운 Docker Image의 이름만 outputs으로 알려주면 된다.
echo "추출할 변수" >> $GITHUB_OUTPUT을 통해 step에서 만들어진 값을 내보내고 이를 steps.*.outputs으로 사용하는 것에 유의하자.