- Fastapi + Serverless, AWS Lambda에 배포하기
- Unable to import module ‘main’ 에러 해결
- Github Action으로 Lambda에 자동 배포 하기
- AWS Lambda CloudWatch Logs Insights 쿼리로 분석
처음 Next.js프로젝트를 Vercel에 배포할때 충격을 많이 받았다.
뭐.. 이게 끝이라고?? 하는 생각이 저절로 들었는데, 내가 한거라곤
그냥 연결한 Repo만 지정했을 뿐인데 이후 PR에 대해서 알아서 테스트 서버도 뛰워줘, 오류 잡아서 알려줘, 통과하면 배포해줘..
Next.js가 vercel에 너무 종속된다는 비판은 있지만 배포 flow를 한번 경험해보니 AWS 가상머신위에 서버는 고사하고 비교적 간단한 Lambda function에 서버 배포 과정과 log 확인하는 과정이 떠올라 비교됐다. 물론 각각 장단점이 있겠지만 CI/CD를 거의 알아서 해주니 개발자 경험만큼 좋을 수 밖에 없을 것 같다.
프론트 서버 배포를 하고 나니 AWS의 Lambda에 배포하고 있는 Fastapi 서버가 생각났다.
현재 serverless라는 프레임워크를 사용해서 배포를 하는데
sls deploy
라는 명령어 한줄로 쉽게 배포를 할 수 있다.
하지만 여전히 직접 로컬 디렉토리 안에서 명령어를 입력해야하는 것을 똑같기에 자동화를 했다.
일단 Github Action을 다뤄보는게 처음이라 간단하게 main브랜치에 push되었을 때 자동으로 배포 되는 것 까지만 구현하였다.
GitHub Actions은 GitHub의 CI/CD (Continuous Integration/Continuous Deployment) 플랫폼입니다. 이를 통해 개발자들은 소프트웨어 개발 워크플로우를 자동화할 수 있습니다. 기본적인 개념과 특징들을 살펴보겠습니다:
GitHub Actions가 뭐냐는 질문에 대한 ChatGPT의 답변
워크플로우: GitHub Actions의 핵심 단위입니다. 워크플로우는 특정 이벤트에 반응하여 실행되는 자동화된 프로세스입니다. 예를 들어, 코드가 저장소에 푸시될 때 빌드 및 테스트를 자동으로 실행할 수 있습니다.
이벤트: 워크플로우는 GitHub 저장소에서 발생하는 특정 이벤트에 의해 트리거됩니다. 예를 들어,
push
,pull request
,issue
생성 등의 이벤트가 해당됩니다.잡(Job): 워크플로우는 여러 잡으로 구성될 수 있으며, 각 잡은 워크플로우의 한 부분을 수행합니다. 잡은 병렬 또는 순차적으로 실행될 수 있습니다.
스텝(Step): 각 잡은 여러 스텝으로 구성됩니다. 스텝은 개별 작업이나 명령을 실행합니다.
러너(Runner): 워크플로우는 GitHub에서 제공하는 서버(러너)에서 실행됩니다. 러너는 Linux, Windows, macOS 등 다양한 운영 체제에서 실행될 수 있습니다.
액션(Action): 액션은 재사용 가능한 워크플로우 구성 요소입니다. 개발자는 자신만의 액션을 만들거나, 다른 사람이 만든 액션을 사용할 수 있습니다.
마켓플레이스: GitHub Actions 마켓플레이스에서는 수많은 액션을 찾고 사용할 수 있습니다. 이를 통해 빌드, 테스트, 배포 등의 과정을 쉽게 자동화할 수 있습니다.
답변만 봐서는 복잡하게 느껴지는데 실제 workflow파일을 보면 매우 간단하다
name: Deploy to AWS Lambda with serverless
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '14'
- name: Install Serverless and dependencies
run: |
npm install -g serverless
npm install
- name: Setting .env
run: |
echo "OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }}" >> api/.env
- name: Install Serverless Plugins and Deploy
run: |
cd api
npm install
serverless plugin install --name serverless-python-requirements
serverless plugin install --name serverless-dotenv-plugin
serverless deploy
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
문법을 찾아보거나 할 필요없이 대강 읽어보기만해도 충분히 이해할 수 있다. 이미 배포 프레임워크를 사용하고 있기때문에 더 단순화 된 부분도 있는 것 같다.
코드를 살펴보면,
on:
push:
branches:
- main
일단 event부분이다. 난 main브랜치에 push가 되었을 때 아래 명령들을 수행하도록 event를 설정해 두었다. 간단한 API서버라서 vercel처럼 개발서버나 테스트 서버를 따로 열어서 미리 확인해 볼 필요까진 없을 것 같고 나중에 pr이 열렸을때 테스트를 진행하여 push 되기 전에 미리 모든 endpoint에 테스트라던지 Lint등 코드 자체를 테스트 해볼 수 있도록 하면 좋을 것 같다.
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '14'
job에 등록된 step들 중 일부이다.
Checkout code, Set up Python, Set up Node.js는 마켓플레이스에 있는 액션들을 가져다 사용했고, 마켓플레이스를 쉽게 이용하려면 로컬 에디터가 아니라 Github웹 페이지에서 해당 yml파일을 수정하면 된다.
에디터의 우측에 바로 마켓플레이스의 액션들을 검색하고 확인하며 작성할 수 있다.
- name: Install Serverless and dependencies
run: |
npm install -g serverless
그리고 serverless프레임워크를 다운로드 받아줬다. 사실 api 디렉토리안에 서버관련 코드들이 모두 들어가 있지만 나중에 다른 서버를 같이 올릴 수 도 있을 것 같아서 전역으로 설치했다.
- name: Setting .env
run: |
echo "OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }}" >> api/.env
AWS console로 접속해서 Lambda fucntion에서 사용한 환경 변수들을 따로 설정할 수 있지만 serverless 프레임워크에서 .env파일을 읽어서 Lambda에 등록해주는 플러그인이 있어서 이를 사용해 왔다.
하지만 Github에 민감한 정보들이 담긴 환경 변수파일을 올릴 수 없기에 Github secrets에 변수들을 저장해 두고, 이를 가상환경에서 .env파일에 출력하여 serverless가 배포할때 사용할 수 있도록 했다.
결국 웹 사이트로 접속해서 수정해야 한다는 것은 변함이 없지만,
AWS console로 직접 접근해서 변경하는 것보다 협업을 할때 권한을 주기도 편하고 보안적으로도 더 좋은 방법인 것 같다.
- name: Install Serverless Plugins and Deploy
run: |
cd api
npm install
serverless plugin install --name serverless-python-requirements
serverless plugin install --name serverless-dotenv-plugin
serverless deploy
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
그리고 Github secret에 저장해 둔 AWS key들도 불러와서 설정해주고 서버가 있는 디렉토리(serverless.yml파일이 위치한 디렉토리)안에서 serverless 플러그인들을 다운로드 받아주고 배포 명령어를 실행한다.
나는 그냥 명령어를 직접 실행했는데 사실 serverless action이 마켓플레이스에 있긴하다. 가독성이 오히려 떨어지는 것 같기도 하고 여러 명령어를 실행하고 나중에 입맛대로 커스터마이징 하기에 불편할 것 같아서 그냥 사용하지 않았다.
Actions에 들어가서 설정한 Workflow가 잘 작동하는지 확인해주면 끝이다.
workflow를 클릭하여 Log도 쉽게 확인할 수 있다.