✅ zappa로 lambda에서 django 서버 배포하기
현재 상황을 간단히 정리해보고 해결방법을 찾아보자. 우선 본문에 쓰인 제목처럼 zappa를 통해 lambda 함수를 만들고 실행시킨 다음, API 게이트웨이와 연결짓는 것이 목표였다.
처음에 zappa를 설치하고 시작한 다음 아래 명령어를 통해 배포를 시도해봤다.
pip install zappa
zappa init
zappa deploy dev
그런데 다음과 같은 오류가 났다.
Traceback (most recent call last):
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/zappa/cli.py", line 804, in deploy
self.lambda_arn = self.zappa.get_lambda_function(function_name=self.lambda_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/zappa/core.py", line 1419, in get_lambda_function
response = self.lambda_client.get_function(FunctionName=function_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/botocore/client.py", line 565, in _api_call
return self._make_api_call(operation_name, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/botocore/client.py", line 1021, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.errorfactory.ResourceNotFoundException: An error occurred (ResourceNotFoundException) when calling the GetFunction operation: Function not found: arn:aws:lambda:ap-northeast-2:264760273909:function:backend-dev
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/zappa/cli.py", line 3048, in handle
sys.exit(cli.handle())
^^^^^^^^^^^^
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/zappa/cli.py", line 521, in handle
self.dispatch_command(self.command, stage)
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/zappa/cli.py", line 563, in dispatch_command
self.deploy(self.vargs["zip"], self.vargs["docker_image_uri"])
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/zappa/cli.py", line 838, in deploy
self.lambda_arn = self.zappa.create_lambda_function(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/zappa/core.py", line 1145, in create_lambda_function
response = self.lambda_client.create_function(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/botocore/client.py", line 565, in _api_call
return self._make_api_call(operation_name, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/soyoung/Projects/backend/onestep_dev/lib/python3.12/site-packages/botocore/client.py", line 1021, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.errorfactory.InvalidParameterValueException: An error occurred (InvalidParameterValueException) when calling the CreateFunction operation: Unzipped size must be smaller than 262144000 bytes
==============
Need help? Found a bug? Let us know! :D
File bug reports on GitHub here: https://github.com/Zappa/Zappa
And join our Slack channel here: https://zappateam.slack.com
Love!,
~ Team Zappa!
GPT에게 분석을 의뢰하니 크게 두 가지의 원인이 있다고 했다.
- AWS 프로파일(profile) 정보가 잘못 입력되었을 가능성
- python 패키지가 최대 크기인 250MB를 초과했을 가능성
그래서 두 가지의 가능성을 체크한 다음 하나씩 고쳐 주었다.
1번의 경우 아래 명령어를 입력하면 현재 AWS에서 사용하고 있는 profile 정보를 볼 수 있었다. 그런데 이 정보는 .zshrc 폴더에 있는 AWS_ACCESS_KEY 값을 갖는 profile의 정보인 것으로 추측되었다. 나는 이전에 이 값을 등록해 놨었는데, 그때는 현재는 만료된 기존의 소마 계정의 값을 가져왔었다. 이 부분을 수정해서 현재 내 IAM 계정의 access key, secret key 값을 넣어주었다.
aws configure list
그랬더니 다음과 같이 프로필이 잘 나오더라.
2번의 경우는 zappa의 설정 변수를 모아둘 수 있는 zappa_settings.json 파일(zappa init 명령어를 입력하면 해당 json 파일이 생긴다)에 다음과 같은 옵션을 추가해 주었다.
"slim_handler": true
그리고 다시 아래 명령어를 입력하였더니, 일단은 중간에 에러가 나오면서 종료되지는 않았다. 다만 걸리는 부분은 이런 로그가 떴다는 것이었다.
Deploying API Gateway..
Waiting for lambda function [backend-dev] to be updated...
Error: Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 500 response code.
추측상 AWS lambda 함수는 잘 만들어졌는데, 이걸 API 게이트웨이로 배포하는 과정에서는 오류가 발생한 것이라고 이해했다. 아래의 명령어로 확인해보니 AWS 람다 함수는 잘 만들어졌다. (원래는 빈 리스트가 나왔다)
aws lambda list-functions --region ap-northeast-2
그리고 AWS 람다 페이지에서도 확인해보니 기존엔 빈 리스트였던 페이지에 새 함수가 추가되어 있었다.
다만 GPT의 설명에서는 원래 'zappa deploy' 명령어를 실행하면 API 게이트웨이의 엔드포인트가 같이 떠야 한다고 했는데, 그 부분이 위에서 언급했던 에러 로그 때문에 생략된 것 같았다. 그래서 이 부분부터 다시 해 줘야 되겠다.
✅ lambda 함수를 API 게이트웨이에 배포해서 엔드포인트 얻기
lambda 레코드는 생성되었는데 API 게이트웨이 레코드는 생성이 된 것인지 확실하지 않았다. 다행히 API 게이트웨이 페이지를 확인해보니 레코드가 생성되어 있었다.
그렇다면 왜 'zappa deploy' 명령어를 입력했을 때 API 게이트웨이 엔드포인트가 자동으로 나오지 않았을지는 의문이다. 나는 API 게이트웨이의 엔드포인트 URL을 얻고 싶었다. 이걸 확인하려면 어떻게 해야할지 물어봐봤다. GPT 피셜, API를 클릭한 다음에 '스테이지'를 누르면 된다고 한다.
그래서 URL을 얻어냈다. 그런데 막상 엔드포인트로 접속하니 다음과 같은 에러가 떴고, 구체적인 사항은 'zappa tail' 커맨드를 통해 확인할 수 있다고 한다. 일단 확인해보자.
zappa tail dev
로그를 자세히 보니 AWS secrets manager에서 관련 환경변수를 가져오는 코드에서 오류가 났다. 아차 싶었던 것은 이 코드는 이전의 소마 계정의 secrets manager를 참고하고 있었다. 해당 계정은 이미 사라진 계정이었으니 오류가 나는 것이 당연했다. 그렇다면 별도로 AWS secrests manager를 하나 만들어서, 그 안에 기존에 사용했던 환경변수 코드들을 넣어 줘야 하겠다.
✅ zappa를 통해 django 코드를 lambda에 배포하기 vs python으로 django 코드를 직접 lambda에 배포하기
말 그대로다. 약 4시간 동안 삽질을 하면서(물론 새벽 삽질이라 효율성이 좋진 않았다) django 코드를 zappa를 통해 aws lambda로 배포하는데 여러 난관에 부딪혔다. 계속해서 아래와 같은 에러가 나는 상황이었다.
[1734632870695] LAMBDA_WARNING: Unhandled exception. The most likely cause is an issue in the function code. However, in rare cases, a Lambda runtime update can cause unexpected function behavior. For functions using managed runtimes, runtime updates can be triggered by a function change, or can be applied automatically. To determine if the runtime has been updated, check the runtime version in the INIT_START log entry. If this error correlates with a change in the runtime version, you may be able to mitigate this error by temporarily rolling back to the previous runtime version. For more information, see https://docs.aws.amazon.com/lambda/latest/dg/runtimes-update.html
[1734632870695] [ERROR] ClientError: An error occurred (UnrecognizedClientException) when calling the GetSecretValue operation: The security token included in the request is invalid.
이 에러를 해결하기 위해서 여러 방법을 시도했었다.
- IAM 콘솔에 들어가서 zappa가 생성한 역할에 SecretsManager에서 GetSecretValue 작업을 할 수 있는 권한을 추가했다.
- boto3에서 사용하는 aws 계정의 세부 정보와 실제 aws의 계정 정보가 다른 것이 원인일 수 있다고 판단해서, boto3 라이브러리의 sts 관련 코드를 추가하여 임시 역할과 관련된 액세스 토큰 정보를 가져올 수 있도록 했다.
- boto3 라이브러리에서 코드가 다시 update/deploy 되어도 캐시로 기존의 세션 정보를 가지고 있을 수 있다는 가능성이 있어서 boto3의 세션을 초기화하는 코드를 넣어주었다.
그 외에도 자잘한 여러 방법을 시도했던 것으로 기억하는데, 유감스럽게도 잘 되지 않았다. 그래서 다시 몇 스텝 뒤로 돌아가서 과연 zappa를 통해 django 코드를 배포하는 것이 맞았을까? 라는 의문을 다시 가져 보기로 했다. 결국은 비용은 똑같으니 편리함의 문제였다. 마침 관련된 블로그 글을 봐서 후자의 옵션으로 마음이 조금 더 기울었다.
우선은 오늘은 여기까지 코딩을 하고, django 코드를 최대한 간단하게, 외부 라이브러리를 거치지 않고 aws lambda에 배포 가능하도록 바꾸는 방법을 고안해봐야겠다.
✅ 궁금한 점
- 'zappa deploy' 명령어의 원리는 무엇일까?
- slim_handler: true 라는 옵션을 붙이면 어떻게 배포 파일의 크기가 줄어드는 걸까?
'개발 일기장 > SWM Onestep' 카테고리의 다른 글
20241223 TIL: api gateway에서 custom domain을 사용해서 porkbun 도메인과 연결하기 [진행중] (0) | 2024.12.23 |
---|---|
20241222 TIL: zappa로 lambda에서 django 서버 배포하기 [진행중] (0) | 2024.12.22 |
20241216 TIL: subnet 안에 lambda 배치하기 [진행중] (1) | 2024.12.16 |
20241215 TIL: terraform으로 aws vpc 세팅하기는 핑계고 (1) | 2024.12.15 |
20241214 TIL: terraform으로 AWS 설정 새로 세팅하기 [진행중] (0) | 2024.12.15 |