본문 바로가기
개발/웹

Flask Microservice 구축 - GitHub Actions로 CI/CD 시스템 구축

by pandatta 2023. 3. 1.

안녕하세요, 저번 Flask Microservice 구축 - Zappa로 AWS Lambda에 Flask Docker 띄우기에 이어 오늘은 이 귀찮았던 작업들을 GitHub에 push 한 번으로 해결할 수 있도록, 깃허브 액션(GitHub Actions)으로 CI/CD 시스템을 구축해보도록 하겠습니다.

CI? CD? GitHub Actions?

CI/CD(Continuous Integration/Continuous Deployment), 한국어로는 지속적 통합과 지속적 배포는 한 몸입니다. 코드를 수정하여 업로드하면 자동으로 빌드와 테스트가 성공한 코드를 모든 개발자들이 통합적으로 공유할 수 있도록 하고, 사용자들에게 코드의 결과 애플리케이션을 자동적으로 배포할 수 있도록 하여 개발자와 사용자 모두가 편리하고 빠르게 개발 프로세스를 자동 공유하는 것입니다.

CI/CD를 수행하게 도와주는 유명한 툴은 젠킨스(Jenkins)서클CI(CircleCI) 등이 있지만, 요즘 오픈소스 사용에 적극적인 회사들은 깃허브(GitHub)에서 제공하는 깃헙 액션(GitHub Actions) 툴을 많이들 사용합니다. 깃허브에 (비)공개 깃(Git) 저장소(repository)를 만들어서 팀원들 간에 코드를 공유하고(CI), 푸시/풀 리퀘스트/머지(push/pull request/merge) 등 원하는 시점마다 빌드/테스트/배포(CD)까지 수행할 수 있는 좋은 툴입니다. 따로 설치할 필요도 없이 깃허브 저장소에서 바로 설정과 실행할 수 있으며, YAML 파일 하나만 있으면 완벽히 설정할 수 있다는 장점이 있습니다.

YAML 파일 세팅만 하면 끝

깃허브 액션으로 CI/CD를 하는 방법은 정말 간단합니다. 깃 저장소의 .github/workflows/ 폴더를 하나 만들고, 그 안에 YAML 파일 하나만 만들어주면 됩니다. 여태까지 우리가 만들어온 플라스크(Flask) 애플리케이션은 아직 테스트 로직을 작성하지는 않았기 때문에, 도커 빌드와 배포 액션(action)만 있는 YAML 파일 서식을 소개해드리겠습니다. 저는 작성할 때 깃허브 액션 공식 문서이 한글 블로그를 많이 참고했습니다.

# .github/workflows/zappa-docker-lambda.yml # 워크플로 단위로 설정합니다
name: Zappa Docker Lambda Deploy # 워크플로의 이름을 정해줍니다
run-name: Deployment of ${{ github.repository }} through Zappa-Docker-Lambda # 워크플로의 상세 설명입니다
on: # 어떤 경우에 이 워크플로가 실행되는지 정해줍니다
  push: # 푸시하면 실행합니다
    branches: [ "main" ] # "main" 브랜치에 푸시하면 실행
  pull_request: # 풀 리퀘스트가 생기면 실행합니다
    branches: [ "main" ] # "main" 브랜치로 풀 리퀘스트가 생기면 실행
jobs: # 한 워크플로는 여러 병렬 실행 가능한 잡을 가질 수 있습니다
  deploy: # 잡 이름을 정해줍니다
    runs-on: ubuntu-latest # 깃허브 서버 내 가상환경의 최신 우분투 환경을 세팅해 진행
    env: # 환경변수를 정해줄 수 있습니다
      ECR_IMAGE_URI: ${{ secrets.ECR_IMAGE_URI }} # 저장소의 비밀 환경변수를 정해주었습니다
    steps: # 잡의 각 단계입니다
      - name: Checkout # 잡의 이름으로, 깃허브 서버로 이 저장소를 내려받습니다
        uses: actions/checkout@v3 # https://github.com/actions/checkout에서 액션을 공유받아 쓸 수 있습니다
      - name: Setup Python # 파이썬을 설치합니다
        uses: actions/setup-python@v4
        with: # 공유받은 액션을 위한 매개변수를 지정해야 합니다
          python-version: 3.8 # 액션에서 파이썬 3.8 버전을 사용하도록 합니다
      - name: Activate a virtual environment # 자파를 위한 가상환경 설치
        run: | # 커맨드라인 명령어를 사용할 수 있습니다
          python3 -m venv venv
          source venv/bin/activate
      - name: Install Python libraries with pip # pip로 파이썬 라이브러리 설치
        run: |
          pip3 install --upgrade pip
          pip3 install -r requirements.txt
      - name: Build Docker image # 도커 이미지 빌드
        run: docker build -t flask .
      - name: Tag Docker image # 도커 이미지를 ECR 경로로 태그
        run: docker tag flask $ECR_IMAGE_URI # 위에서 설정한 환경변수를 사용합니다
      - name: Configure AWS credentials # AWS 계정 로그인
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: ap-northeast-2
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      - name: Transfers authority from AWS ECR to Docker # AWS 계정 정보를 도커로 전달
        run: >
          aws ecr get-login-password |
           docker login --username AWS --password-stdin $ECR_IMAGE_URI
      - name: Push Docker image to AWS ECR # 도커 이미지를 ECR에 업로드
        run: docker push $ECR_IMAGE_URI
      - name: Save python settings for production with Zappa # 자파에 필요한 파일 세팅
        run: zappa save-python-settings-file prod
      - name: Deploy application from AWS ECR to Lambda with Zappa # 자파로 람다에 배포 완료
        run: zappa update prod -d $ECR_IMAGE_URI

주석 외에 알아두면 좋을 점들을 정리해두겠습니다.

  1. 깃허브 액션은 깃 저장소의 .github/workflows/ 폴더 내의 YAML 파일을 검색하고, 각 파일에 기술된 워크플로(workflow)에 대한 명세를 읽어서 그에 따라 깃허브 서버 내에 도커(Docker)처럼 가상환경(virtual environment)을 설정해 모든 작업을 실행합니다. 워크플로 내에 잡(jobs)을 여러 개 설정하면, 그 잡들은 각각 병렬실행됩니다. 한꺼번에 여러 애플리케이션의 빌드를 만들 수도 있고, 여러 위치로 배포할 수도 있겠습니다.
  2. 워크플로를 어떤 경우에 실행하는지 정해줄 수 있습니다. 일반적인 방법으로는 main 브랜치(branch)로 푸시하거나 풀 리퀘스트가 열릴 때마다, 즉 배포해야하는 시점에 실행하는 것이 일반적입니다. 제가 예전에 컨트리뷰트(contribute)했던 사이킷런(scikit-learn) 저장소는 매 푸시마다 실행하는 정책을 만들기도 했습니다.
  3. 가상환경 위에 윈도우/맥/리눅스 등 운영체제를 정해줄 수 있고, 사용하기 위한 환경변수를 설정해줄 수 있습니다. 환경변수는 깃허브저장소 - Settings 탭 - Secrets and Variables - Actions에 가서 설정할 수 있습니다. 보안을 위해서 비밀 환경변수, 즉 secrets를 정해두면 액션을 실행할 때 출력에 해당 환경변수가 암호화되어 출력됩니다. AWS KEY나 URL 등을 저장해두면 좋습니다.

나머지는 저번 포스트에서 자파(Zappa) - 도커(Docker) - AWS ECR, 람다(Lambda)를 통해 플라스크 애플리케이션을 배포한 순서와 동일합니다. 다른 점이 두 가지 있는데, 첫째로 개발용이 아닌 배포용이므로 자파 스테이지명을 prod로 설정했고,

botocore.exceptions.ProfileNotFound: The config profile (default) could not be found

다음으로 이와 같은 에러가 자파 액션에서 발생하길래, 자파 깃허브 이슈(issue)를 참고해 zappa_settings.json 파일의 "profile_name": "default", 줄, 즉 자파 스테이지의 프로필 이름을 삭제하였습니다.

이제 여러분은 깃허브 main 브랜치에 푸시만 해도 AWS 람다에 플라스크 애플리케이션을 배포할 수 있습니다! 긍지 높은 마이크로소프트답게, 남의 서버에 가상환경을 세팅하는데도, 깃허브 액션은 500MB 용량에 한 달 2,000분 실행하는 것까지는 무료입니다! 저는 깃허브 프로 계정이라서 1GB에 3,000분... 역시 윈도우랑 오피스 팔아서 오픈소스에 갖다박는 멋진 회사입니다. 이제 쉽고 간편하게 배포를 할 수 있게 되었으니, 남은 플라스크 마이크로서비스(microservice) 개발을 향해 나아가보도록 합시다.

댓글