본문 바로가기

AWS

Github Action + ECS + Fargate를 통한 CI/CD 구현 2

https://docs.github.com/ko/actions

 

GitHub Actions 설명서 - GitHub Docs

GitHub Actions를 사용하여 리포지토리에서 바로 소프트웨어 개발 워크플로를 자동화, 사용자 지정 및 실행합니다. CI/CD를 포함하여 원하는 작업을 수행하기 위한 작업을 검색, 생성 및 공유하고 완

docs.github.com

Github과 Docker를 이해했다면 이젠 실제로 Github Action을 통해 빌드를 해볼 차례다.
 
문법은 기본적으로 yaml 방식을 사용한다.
파일은 {repository}/.githubh/workflows/{filename}.yaml 로 작성한다.
단, 제대로 해당 파일을 적용하려면 repository의 default branch에 반드시 해당 파일이 들어가 있어야 한다.
 

이 예제에선 Github Action을 통해 다음과 같은 행동을 수행한다.

1. develop branch에 push가 들어오면
2. AWS에 로그인 한다.
3. 리포지토리에 있는 dockerfile을 기반으로 소스를 docker 빌드한다.
4. 빌드된 docker 이미지를 ECR에 푸시한다.
5. ECS에 Task Definition을 업데이트 한다.
6. ECS Service의 Task Definition을 최신으로 변경한다.
7. 대기 후 빌드가 완료되면 슬랙을 알려준다.
 

name: Develop Deploy

on:
  push:
    branches:
      - develop

env:
  AWS_REGION: ${{ secrets.AWS_REGION }}
  ECR_REGISTRY: ${{ secrets.ECR_REGISTRY }}
  ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
  IMAGE_TAG: latest

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        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: ${{ secrets.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
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
          IMAGE_TAG: stg-latest
        run: |
          docker build -f Dockerfile -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

      - name: Download Task Definition Template
        run: |
          aws ecs describe-task-definition \
            --task-definition stg-${{ github.event.repository.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: ${{ github.event.repository.name }}
          image: $ECR_REGISTRY/$ECR_REPOSITORY:$ECR_IMAGETAG

      - name: Deploy Amazon ECS task definition
        uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          task-definition: task-definition.json
          service: ${{ secrets.STG_SERVICE }}
          cluster: ${{ secrets.STG_CLUSTER }}
          wait-for-service-stability: true

      - name: Slack Notification
        uses: rtCamp/action-slack-notify@v2
        env:
          SLACK_CHANNEL: ${{ secrets.SLACK_CHANNEL }}
          SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff'
          SLACK_ICON: https://github.com/rtCamp.png?size=48
          SLACK_MESSAGE: ${{ github.event.head_commit.message }}
          SLACK_TITLE: '[${{ github.event.repository.name }}] 배포 ${{ job.status }}'
          SLACK_USERNAME: DeployNews
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

 
이 코드에는 보안에 극도로 민감한 몇가지 변수가 존재한다.
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY 등
 
가 대표적이지만, 이 코드를 감추면서도 반드시 필요한 권한을 유지하기 위해 해당 예제에선 Github Secrets라는 것을 이용하고 있다. 
 
github.com/org/project/settings/secrets/actions
 
링크로 들어오게 되면 아래와 같은 화면이 나오게 된다.

여기서 New repository secret을 클릭하면 아래와 같이 입력이 가능한 페이지가 나온다.

사용할 키 값과 value를 넣고 저장하면 workflow 파일에서 ${{ secrets.key }} 라는 이름을 통해 사용할 수 있다.
 
단, 차이점이라면 여기에 들어간 키값은 다시 볼 수 없다. (에코로 찍어도 안나오니 잊어버리면 다시 세팅...)
 
문제가 생겼을 경우 수정은 가능하지만 원 데이터는 확인이 불가능하다.
이점은 AWS ssm parameter store와는 다른 면이 있지만, 반대로 보안 입장에선 좋기는 하다.
하지만 까먹으면 참 번거로운 일이니 별도 비문 문서로 간직해야 할수도 있다. (이건 각자 알아서 판단)
 
저 코드는 이미 ECS Cluster가 있고 ECS가 지정되어 있고 ECR에 이미지가 올라가 있음을 전제하고 돌아가는 상태이다.
처음 실행할때는 당연히 ECR 이미지고 ECS도 없을 수 있다.
 

처음 할때 할일은 다음과 같다.

1. ECR 페이지로 가서 Repository 생성
https://ap-northeast-2.console.aws.amazon.com/ecr/get-started?region=ap-northeast-2 

 

https://ap-northeast-2.console.aws.amazon.com/ecr/get-started?region=ap-northeast-2

 

ap-northeast-2.console.aws.amazon.com

2. ECR에 업로드 하고 ECS를 업데이트 칠 수 있는 IAM 생성 (아래 권한 참조)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ecr:PutImageTagMutability",
                "ecr:StartImageScan",
                "ecr:DescribeImageReplicationStatus",
                "ecr:ListTagsForResource",
                "ecr:UploadLayerPart",
                "ecr:BatchDeleteImage",
                "ecr:CreatePullThroughCacheRule",
                "ecr:ListImages",
                "ecr:BatchGetRepositoryScanningConfiguration",
                "ecr:DeleteRepository",
                "ecr:GetRegistryScanningConfiguration",
                "ecr:CompleteLayerUpload",
                "ecr:TagResource",
                "ecr:DescribeRepositories",
                "ecr:BatchCheckLayerAvailability",
                "ecr:ReplicateImage",
                "ecr:GetLifecyclePolicy",
                "ecr:GetRegistryPolicy",
                "ecr:PutLifecyclePolicy",
                "ecr:DescribeImageScanFindings",
                "ecr:GetLifecyclePolicyPreview",
                "ecr:CreateRepository",
                "ecr:DescribeRegistry",
                "ecr:PutImageScanningConfiguration",
                "ecr:GetDownloadUrlForLayer",
                "ecr:DescribePullThroughCacheRules",
                "ecr:GetAuthorizationToken",
                "ecr:PutRegistryScanningConfiguration",
                "ecr:DeletePullThroughCacheRule",
                "ecr:DeleteLifecyclePolicy",
                "ecr:PutImage",
                "ecr:BatchImportUpstreamImage",
                "ecr:UntagResource",
                "ecr:BatchGetImage",
                "ecr:DescribeImages",
                "ecr:StartLifecyclePolicyPreview",
                "ecr:InitiateLayerUpload",
                "ecr:GetRepositoryPolicy",
                "ecr:PutReplicationConfiguration"
            ],
            "Resource": "*"
        }
    ]
}

3. 해당 IAM Policy를 사용하는 IAM User 생성
4. Access Key 만들고 Secrets에 등록
5. 맨 위 파일에서 아래 부분 섹션 주석 처리
- Download Task Definition Template
- Fill in the new image ID in the Amazon ECS task definition
- Deploy Amazon ECS task definition
6. workflow에 push

빌드가 완료 되었다. 이제 ECR에 가서 이미지가 있는지 확인해 볼 수 있다.

위와 같은 느낌으로 이미지가 정상적으로 표시 된다면 정말 ECS Cluster, ECS 서비스를 만들 준비가 끝난 것이다.
 
3편에 계속...