CI/CD 해보기(연습)

박찬미·2022년 2월 23일
0

뭐든 개발

목록 보기
1/2

github action을 이용해서 배포하는 것을 연습해봤다..
현빠가 공부해보라고 했는데, 사실 기본 지식이 부족해서 이론을 읽어도 완벽히 내 것이 아닌 느낌이라서 한번 예제 보면서 따라해봤다..

일단 원래 도커 파일과 컴포즈 파일을 만들어놓고 docker-compose up 을 이용해서 이미지를 pull 받았었는데, Dockerfile 만 이용해서 해봤다.

처음에는
참고1
참고2
위 링크를 참고해서 해봤는데, 자꾸 배포에서 에러가 났다. 권한 문제 같은데 나는 분명 시크릿을 만들어서 넣었는데,, 이렇게 하다가 포기

자꾸 안되니까 화가 나서 아침에 인나자마자 다시 해봤다. 이번엔
참고3
여기 링크를 보고 따라해봤고, 중간 중간 모르는 거는 검색해보며 해결했던 것 같다..드디어 배포 성공을 했지만 확인은 아직 못함 ㅎㅎ

성공은 했지만, 아직까지 전체적으로 이해했고 다른 사람 꺼를 따라하다보니 완벽하게 알지는 못한다. 그냥 용어도 정리하면서 내가 한 과정에 대해 써놓으려고 한다.

자동 배포를 하는 이유

코드에 수정사항이 생길 때마다 SSH Key로 인스턴스에 접속해서 git pull를 하는 건 번거롭다. 이게 한 두번이면 괜찮지만,,장기적 관점에서는 좋지 않다고 한다. 위 참고3의 필자는 수동배포는 업데이트 주기도 늦어지고, 서비스에 대한 관심도도 떨어뜨린다고 말하고 있다.

하려고 하는 거

먼저 로컬에 있던 소스를 github 원격 repository에 올리고, github action을 이용해서 aws 서비스에 배포하는 프로세스를 진행한다.

원래 해야 하는 거는 현쓰 왈 오빠네 서버(러너)에서 aws registry에 넣으라고 함

1. 도커 이미지 빌드

도커 이미지는 링크에 있는 소스를 쓰려고 하니까 pip 때문에 빌드가 잘 안됐다.
어차피 나는 도커 파일을 가지고 있었으므로 이걸로 도커 이미지를 빌드했다.

원래는 위 사진에 ARG NODE_VERSION=${NODE_VERSION}이었는데, 그건 docker-compose 파일도 함께 이용해서 컴포즈로 이미지를 받으려고 했기 때문이다. 도커 파일만 이용할거라 14.19로 넣어주고 진행했다.

도커 파일이 있는 폴더로 들어가서 빌드를 한다. 도커 이미지 이름은 ecs-tutorial로 해주었다.
그럼 도커 이미지가 생성될 것이다.

위 명령어로 ecs-tutorial이 생성됐는지 확인하고

이미지를 실행시키면 8080 포트로 nginx가 잘 뜬다.

2. AWS ECR에서 Repository 생성

일단 ECR은 AWS에서 관리하는 이미지 레지스트리 서비스이다. Docker Hub랑 수행하는 역할이 굉장히 비슷하다고 한다.

ECR이란?
ECS 정책

AWS ECR은 내가 만든 도커 이미지를 보관하고
그 보관소에는 지정된 사용자 또는 ec2 인스턴스가 액세스 가능하도록 한 것

ECR은 리소스 기반 권한을 사용해 리포지토리에 대한 액세스를 제어한다. 그래서 자격이 주어져야 액세스가 가능하다고 한다. 이 정책에 대해서는 위에 링크를 달아놓았다.

먼저 AWS에서 ECR을 검색해서 리포지토리를 생성한다.(나는 이미 다 해서 사진 복붙...)

자 이렇게 하면 Repository 생성은 끝
이제 github action에서 도커 이미지를 이 곳으로 push 해줄 것이다.

3. 작업 정의(task definition) 생성

작업 정의는 어떤 도커 이미지를 쓸 것인지, 포트 매핑은 어떻게 할 것인지, 인스턴스 타입은 어떤 걸 쓸 건지, CPU나 메모리 사용 등을 파일로 정리해서 올리면 정리한대로 컨테이너를 올려준다.(docker-compose와 비슷한 역할)

작업 정의는 AWS console에서 직접 할 수 있지만,,나는 json 파일로 만들어서 aws cli를 통해 올릴거다. 직접 정의 이 링크는 직접 한듯

컨테이너 설정이 변경될 때마다 직접 aws console에 들어가서 task definition을 수정하는 건 번거롭다.

프로젝트 루트에서 task-definition.json 파일을 생성한다. AWS 개발자 가이드에서 template을 볼 수 있다. 아 근데 어려워~~~
천사같은 분이 간단 예제실제 사용 파일을 올려줬다. 나는 비교하면서 만들었다.

아 이전에 task-definition 파일에 들어가야 할 값들이 있는데, 이걸 먼저 설정해줘야 한다.

위는 내 파일인데 보면 executionRoleArn 설정이 있다. 이거는 IAM에 가서 만들어줘야 한다.

공식 문서를 보면 간결하게 나와있다. AWS IAM 1, AWS IAM 2링크도 참고하면 될 거 같다.

파일을 다 만들었으면 aws-cli라는 것을 이용해서 aws에 task-definition 파일을 올려야 한다.
aws-cli를 사용하기 위해서는 초기 설정을 해야 한다. aws-cli 초기 설정

초기 설정을 다 하고 위에 사진처럼 json 파일을 등록한다. 그럼 아래에 json 파일 내용이 보일 것

등록이 잘 되었다면 작업 정의에 잘 뜰 것이다.

4. ECS 클러스터 & 서비스 생성

클러스터란 우리의 task 혹은 service가 돌아가는 논리적인 그룹을 말한다.
내가 정의한 tasks가 있고 그 작업들을 관리해주는 service가 있다. 이것들은 모두 클러스터 위에서 동작한다는 것을 의미한다.

AWS에서는 유저가 ECS를 처음 사용할 때 기본적으로 default라는 이름의 기본 클러스터를 제공하지만, 나는 새로 만들 것이다.

AWS 콘솔에서 ECS에 들어가보면 좌측에 Cluster라는 탭에서 클러스터를 생성할 수 있다.

여기서는 인스턴스 타입을 Fargate(서버리스)를 사용했다. 인스턴스 타입으로 Fargate와 EC2가 있는데 EC2 or AWS Fargate에 설명이 나와있다.

cluster-for-ecs-tutorial이라는 이름의 클러스터를 생성한다. 따로 새로운 VPC는 생성하지 않았다. 바로 create한다. Amazon VPC란?

이제 클러스터도 생성했으니 서비스를 생성한다.

위 사진과 비슷하게 한다..일단 작업 정의 만들어둔거 선택하고 클러스터도 만들어둔거 선택하고 서비스 이름은 service-for-ecs-tutorial로 한다. 작업은 하나니까 1 나머지는 사실 잘 모른다. 걍 따라서 했을 뿐,,위처럼 하고 아래 다른 옵션은 설정 안하고 바로 다음

다음 단계가 정신 없었던 것 같은데, 네트워크에 대한 설정을 해줘야 한다. application load balancer 생성, 보안 그룹 설정 등의 작업을 한다.

위처럼 VPC는 있던 거 쓰고, subnet은 최소 2개가 있어야 한다고 해서 2개를 선택해준다.

자 이제 보안그룹을 설정한다. 위에 사진 보면 편집 버튼 있는데 눌러서 편집

난 이미 만들어놔서 있다고 오류뜬다. task-definition.json에서 8080번 포트로 매핑해뒀기 때문에 보안그룹에서도 8080 포트로 맞춰줘야 한다. 그리고 anywhere(위치 무관)으로 열어준다.

이제 로드 밸런싱을 설정한다.

위처럼 설정하는데 Application Load Balancer(ALB)를 선택한다. 처음엔 로드 밸런서 이름에 선택할게 없었던 걸로 기억한다. EC2 console의 Load Balancer 탭에서 생성했었다.

위에 로드 밸런서 생성을 눌러서

위처럼 설정하고 생성해준다. 로드밸런서는 alb-for-ecs-tutorial로 했고, 나머지 보안 그룹은 만들었던 거 선택해주고 VPC는 원래 있던 거, subnet은 두 개 선택하고 Listener는 건드리지 않았다.

로드밸런서에 추가 눌러서

위처럼 설정하고 Auto Scaling 설정은 건너뛰고 서비스를 생성한다.

휴..너무 어지러워

여기까지 하면 거의 다해따
앱이 배포될 인프라 작업 끝

  • ECR 생성
  • Task Definition 생성 및 등록
  • Cluster 생성
  • Service 생성(ALB, 타겟 그룹 생성)

5. Github Actions 생성

이제 깃허브 액션으로 Container Image를 ECR에 배포할 수 있도록 해야 한다.
깃허브 액션에 설정해놓은 특정 사용자가 소스 푸시를 할 때마다 감지해서 자동으로 빌드하고 테스트하고 배포할 수 있도록 해준다.

일단 환경변수들을 Secrets에 등록해줘야 한다. 위에 보면 IAM에서 발급받은 ID와 KEY를 등록해준다. ECR에 접근하기 위해서 필요

먼저 workflow를 만들어야 한다. 이걸 설정해놓으면 github actions에서 내가 만든 workflow를 자동화 해준다. 또 내가 만든 거 말고도 다른 사람들이 정의해놓은 workflow 파일을 가져와 사용할 수도 있다.

이렇게 많이 있는데 여기서는 Deploy to Amazon ECS 서비스를 찾아서 이용한다.
그러면 이미 만들어져 있는 yml 파일이 나타나는데 여기서 일부를 수정한다.

위 설정들을 수정한다.


# This workflow will build and push a new container image to Amazon ECR,
# and then will deploy a new task definition to Amazon ECS, when there is a push to the main branch.
#
# To use this workflow, you will need to complete the following set-up steps:
#
# 1. Create an ECR repository to store your images.
#    For example: `aws ecr create-repository --repository-name my-ecr-repo --region us-east-2`.
#    Replace the value of the `ECR_REPOSITORY` environment variable in the workflow below with your repository's name.
#    Replace the value of the `AWS_REGION` environment variable in the workflow below with your repository's region.
#
# 2. Create an ECS task definition, an ECS cluster, and an ECS service.
#    For example, follow the Getting Started guide on the ECS console:
#      https://us-east-2.console.aws.amazon.com/ecs/home?region=us-east-2#/firstRun
#    Replace the value of the `ECS_SERVICE` environment variable in the workflow below with the name you set for the Amazon ECS service.
#    Replace the value of the `ECS_CLUSTER` environment variable in the workflow below with the name you set for the cluster.
#
# 3. Store your ECS task definition as a JSON file in your repository.
#    The format should follow the output of `aws ecs register-task-definition --generate-cli-skeleton`.
#    Replace the value of the `ECS_TASK_DEFINITION` environment variable in the workflow below with the path to the JSON file.
#    Replace the value of the `CONTAINER_NAME` environment variable in the workflow below with the name of the container
#    in the `containerDefinitions` section of the task definition.
#
# 4. Store an IAM user access key in GitHub Actions secrets named `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
#    See the documentation for each action used below for the recommended IAM policies for this IAM user,
#    and best practices on handling the access key credentials.

name: Deploy to Amazon ECS

on:
  push:
    branches:
      - main

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest

    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: ap-northeast-2

    - 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 }}
        ECR_REPOSITORY: repo-for-ecs-tutorial
        IMAGE_TAG: ${{ github.sha }}
      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 .
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
        echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
    - 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: container-for-ecs-tutorial
        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: service-for-ecs-tutorial
        cluster: cluster-for-ecs-tutorial
        wait-for-service-stability: true

저렇게 설정하면 돌아간다.

한 번 실패했는데 내가 task-definition을 aws에만 올리고 소스를 github에 안 올려서 에러났다. 파일을 올리니 제대로 됐다.

위 다이어그램 형식으로 서비스가 돌아간다.

리파지토리에 이미지가 업로드된 것을 볼 수 있다.

기본이론

0개의 댓글