✈️ Github Action와 zappa를 이용하여 Lambda 배포 자동화하기

배주웅·2020년 1월 26일
0
post-thumbnail

친구들과 하는 토이 프로젝트 서버를 Lambda에 올려 사용하고 있다. Flask를 이용하고 Zappa를 이용해 배포하는 중이다. 처음 배포 할 때에는 그냥 zappa update 명령어를 이용해 배포를 하곤 했었는데, 매번 master 브랜치에 머지하고 수동으로 배포하자니 귀찮기도 하고, 추후 테스트 등을 배포과정과 합칠 때 엄청 고생할 바에 미리 Github Action에 적응하면 좋을 거 같았다. 그래서 이번 주 블로그 주제는 이걸로 결정. 이래놓고 한주 반을 더 헤맸다;;

목표

  • origin/master에 push하면, 알아서 zappa update 명령어를 이용해 람다에 배포한다.

Github Action을 이용해 배포하기

레포지토리를 들어가 보면, 이렇게 Actions 라는 탭이 생겼다. 여기서 새로운 Workflow를 생성할 수 있다. 아니면 레포지토리에 .github/workflows 안에 *.yml 파일을 만드는 방법으로 생성할 수도 있다. 우리는 후자를 이용해서 만들어 보겠다.

Workflow 이름과 실행 시점 정하기

name: Deploy to Lambda with Zappa

on:
  push:
    branches: 
    - master

특정 브런치 ( 여기서는 master )에 push 이벤트가 일어난 경우에만 배포를 진행하고 싶으므로, 다음과 같이 적어주자. 브런치 이름의 wildcard도 지원하는 듯 하다. release/* 이런식으로도 가능하다고 한다.

기본 배포과정 설정하기

배포 과정에는 크게

  1. 파이선 설정
  2. PIP를 이용해서 dependency 설치
  3. zappa를 이용해 배포 ( zappa update dev )
  4. 약간의 삽질 과정 😅

이 있겠다.

1. 파이썬 설정

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v1
    - name: Set up Python 3.7
      uses: actions/setup-python@v1
      with:
        python-version: 3.7

actions 에서 기본으로 제공하는, Python Setup action이 있다. 이를 이용해서 특정 파이선 버전을 지정해 주면 된다. 로컬의 개발 환경과, Lambda가 실행되는 환경 모두 Python 3.7 버전이므로 3.7에 맞추어 주었다.

2. 가상 환경을 만들고, PIP를 이용해서 dependency 설치

zappa는 venv상에서만 작동한다. 실제 배포 명령어인 zappa update dev 를 실행하기 전에 우선 가상 환경을 만들어 주자.

- name: Create Virtual Environment
      run: |
        python -m venv venv
        source venv/bin/activate

requirements.txt 파일 안에 저장되어 있으니, pip install -r requirements.txt 명령어로 설치 해 주자.

- name: Install dependencies
      run: |
        pytion -m pip install --upgrade pip
        pip install -r requirements.txt

3. zappa를 이용한 배포

그냥 배포를 해주면 되는데, VENV를 못 찾는 경우가 생긴다. VENV는 VIRTUAL_ENV라는 환경 변수를 찾아서 여부를 확인하므로, ENV에 VIRTUAL_ENV 값을 넣어준다.

name: Deploy to Lambda with Zappa

on:
  push:
    branches: 
    - master

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1
    - name: Set up Python 3.7
      uses: actions/setup-python@v1
      with:
        python-version: 3.7
    - name: run venv
      run: |
        python -m venv venv
        source venv/bin/activate
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: deploy with zappa
      env:
        VIRTUAL_ENV: ./venv
      run: |
        zappa update dev

짠 코드도 다시 보자, 빠진 거 채우기

아마 이대로 만들면 배포가 되지 않을 것이다. 왜냐? AWS Credential이 어디에도 없기 때문이다. zappa는 코드를 업로드 할 때 boto3 라이브러리를 사용한다. boto3에서 Credential을 다음과 같이 순회하며 검색한다.

  1. Passing credentials as parameters in the boto.client() method
  2. Passing credentials as parameters when creating a Session object
  3. Environment variables
  4. Shared credential file ( ~/.aws/credentials )
  5. AWS config file ( ~/.aws/config )
  6. Assume Role provider
  7. Boto2 config file ( /etc/boto.cfg and ~/.boto )
  8. Instance metadata service on an Amazon EC2 instance that has an IAM role configured.

출처: boto3 공식 문서

우리가 1번, 2번을 할 수는 없으므로, 가상환경에 ENV를 넣어주어야 한다. Github Action 문구에 따르면 다음과 같은 문법을 쓰면 된다고 나와있다.

steps:
  - name: My first action
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      FIRST_NAME: Mona
      LAST_NAME: Octocat

그냥 Github Action 설정 파일에 바로 때려박을 수는 없으니, serects 에 값을 넣어 주자. 레포지토리 설정 > Secrets에 값을 넣을 수 있다.

이후 배포 과정에서 zappa가 있는 부분 에 해당 env를 넣어준다. 그리고 배포를 해 본다.

    - name: deploy with zappa
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      run: |
        zappa update dev
        

한번에 되면 참 좋겠는데, 역시 그렇지 않다;; 문제를 차근 차근 고쳐나가 보자.

약간의 삽질 과정

config 관련정보를 못 찾아서 그렇다. zappa_setting.json 에 가서 환경 변수를 볼 수 있게 profile_name 부분을 지워보자.

??? credential이 사라졌습니다~
제공되는 aws-actions 를 이용해 credential 파일을 만들어 주자

- 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

배포는 제대로 되는데, 여기서 오류가 난다; 배포는 되었으나 배포된 람다의 Health Checking 하는 과정에서 오류가 나는 거 같다. zappa의 advanced configure을 보니, touch 옵션이 true 이면 Endpoint에다가 health check를 시도하는 거 같다. 로컬에선 정상적으로 되는데, Github Action으로 올라가면 안 되는 거 보니 VM에서 aws URL로 직접 접근하려 할 때 문제가 있는지도 모르겠다. 일단 해당 옵션을 꺼 주고, 별개의 Health Checker를 달아주는 것으로 해결하기로 했다. 사실 어짜피 필요한 거였는데, 핑계가 생겼으니 이젠 정말 만들어야지.

zappa_settings.json 파일의 dev 오브젝트 안에 "torch": false를 추가 해 준다.

{
    "dev": {
        "app_function": "app.__init__.app",
        "aws_region": "ap-northeast-2",
        "project_name": "dummy_app",
        "runtime": "python3.7",
        "s3_bucket": "dummy_app_bucket",
        "touch": false
    }
}

정상적으로 되는 모습을 볼 수 있다. 언제가 될 지 모르겠지만 다음 글에는 Slack Notification을 달아 보겠다.

추가
해당 글을 쓰는데 큰 도움이 된 조민규님의 블로그 글을 첨부한다. 덕분에 헤메이는 과정을 줄일 수 있었다. 그렇다고 안 헤메인 건 아니다ㅠ

추가2
torch가 문제가 아니라, CI단에서 라이브러리가 정상적으로 들어가지 않았던 문제였다. (즉 배포하면 서버가 무조건 죽는다 ㅠ) 이는 pipenv를 이용해서 해결해 주었는데, 나중에 다시 블로그 글로 작성해 보려고 한다.

profile
공부하자 먹고살자 오늘도 방실방실 밝은 대한민국의 하늘

1개의 댓글

comment-user-thumbnail
2020년 5월 4일

글 잘 읽었습니다 ㅎㅎ

그냥 Github Action 설정 파일에 바로 때려박을 수는 없으니, serects 에 값을 넣어 주자. 레포지토리 설정 > Secrets에 값을 넣을 수 있다. 에서 serects 오타났어욤

답글 달기