ECS CI/CD 파이프라인 - github actions

문한성·2023년 6월 28일
1

부트캠프

목록 보기
121/123

CI/CD 파이프라인 아키텍쳐

GitHub Actions를 활용한 CI/CD 파이프라인을 통해 서비스의 배포 과정을 간소화하고자 하였습니다.
Github에 변경 사항이 발생되면 Github Actions는 자동으로 이벤트를 트리거하여 배포를 진행하게 됩니다.
이 파이프라인의 주요 단계 중 하나는 도커 이미지를 Amazon ECR에 업로드 하는 것으로, Actions 내에서 ECR에 접근하기 위해 AWS CLI를 활용하여 안전하게 인증을 수행하고 새로 빌드된 도커 이미지를 지정된 ECR 리포지토리에 푸시합니다.

또 다른 중요한 단계로는 업데이트 된 도커 이미지를 사용하도록 ECS 태스크를 업데이트 하는 것으로, workflow내에서 ECS API를 이용하여 기존 태스크 정의를 불러오고, 새로운 도커 이미지를 참조하도록 수정합니다.

이러한 CI/CD 파이프라인을 통하여 항상 최신 버전의 서비스가 배포 가능하도록 유지할 수 있습니다.

구현 과정

Github actions로 ECR에 이미지를 빌드하고 ECS자동 배포하기

위의 링크를 보고 ECR 레포지토리에 이미지를 업로드 하고 ECS 배포를 하는 방법을 학습 할 수 있습니다.

위의 링크와 다른점은 task-definition.json 파일을 따로 저장하지않고 github actions에서 지정한 task-definition aws에서 불러와서 값을 수정한후에 사용한다는 점입니다.

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

name: User source Deploy to Amazon ECR & ECS

on:
  push:
    branches:
      - release/ecs-race-user

env:
  AWS_REGION: ap-northeast-2
  ECR_REPOSITORY: users
  ECS_SERVICE: race-user-sv
  ECS_CLUSTER: race-user-cluster
  CONTAINER_NAME: private-user
  
jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment: production

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

    - 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: Set short git commit SHA
      id: vars
      run: |
        calculatedSha=$(git rev-parse --short ${{ github.sha }})
        echo "::set-output name=short_sha::$calculatedSha"        

    - 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: ${{ steps.vars.outputs.short_sha }}
      working-directory: ./backend/user-backend
      run: |
        # Build a docker container and
        # push it to ECR so that it can
        # be deployed to ECS.
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . || true
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG || true
        echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
    
    - name: Retrieve most recent ECS task definition JSON file
      id: retrieve-task-def
      run: |
        aws ecs describe-task-definition --task-definition private-user-task --query taskDefinition > task-definition.json
        cat task-definition.json
        echo "::set-output name=task-def-file::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: ${{ steps.retrieve-task-def.outputs.task-def-file }}
        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

기존의 ECR에 업로드 되는 이미지들은 Github Actions를 통해 ${{ github.sha }} 환경변수를 이용하여 커밋의 id를 이미지 태그로 사용하였다.

하지만 커밋 id의 길이가 너무 길다는 점과, 정작 Github에서 보이는 커밋 id는 짧게 되어있기 때문에, 굳이 그대로 사용할 필요가 없다고 느껴져서 짧게 바꾸어 주었다.

# 이미지 태그로 사용될 github.sha 짧게 축소
 - name: Set short git commit SHA
      id: vars
      run: |
        calculatedSha=$(git rev-parse --short ${{ github.sha }})
        echo "::set-output name=short_sha::$calculatedSha"   
        
# 사용되는 코드
- name: Build, tag, and push image to Amazon ECR
      id: build-image
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        IMAGE_TAG: ${{ steps.vars.outputs.short_sha }}

task-definition 불러오는 이유

Secrets Manager 사용, 쓰지못한 이유

위의 링크를 확인해보면 task definition이 github에 올라감으로써 노출되어선 안되는 값들이 노출될 위험이 생겨서 보안적으로 취약해졌다.

하여 Secrets Manager 사용하여 해당 부분을 방지하려했으나 Terraform과의 호환의 문제로 인해서 Secrets Manager를 사용하지 못하게 되었다.

임시 방편으로 github secrets를 사용하여 값을 숨겨서 올려놓았으나 결국 json파일이 github에 올라감으로써 불안함을 느끼게 되었다.

- name: Retrieve most recent ECS task definition JSON file
      id: retrieve-task-def
      run: |
        aws ecs describe-task-definition --task-definition private-user-task --query taskDefinition > task-definition.json
        cat task-definition.json
        echo "::set-output name=task-def-file::task-definition.json"

workflow 내에서 aws cli 명령어를 실행시켜 가장 최근 태스크 정의 파일의 json 파일을 불러올 수 있다.

이 때, task family name을 적어주어야 하는데, 이는 태스크 정의 json 파일의 family가 적혀있기에 어렵지 않게 찾을 수 있다.

해당 부분을 추가하여 aws CLI를 활용하여 값을 불러올 수 있다는것을 알게되어 조금더 보안에 신경쓴 CI/CD 파이프라인을 구축할 수 있었다.

profile
기록하고 공유하려고 노력하는 DevOps 엔지니어

0개의 댓글