본문 바로가기
AWS/기능 소개 및 에러처리

[AWS] Windows 개발 환경에서 Serverless Framework 오류 (Runtime.ImportModuleError)

by Pacloud 2024. 3. 29.
반응형

현재 사내에서 AWS 관련 대학생 커뮤니티를 운영하고 있는데, 어느덧 그 숫자가 2000명이 넘어갔다.

 

그러다보니 학생 분들은 AWS IAM 사용자 계정을 받아 프로젝트를 진행하게 했는데,

당연히 최소 권한의 원칙을 따라야 하는 우리로서는 모든 서비스에 권한을 제공해주지 않는다.

(어마무시한 비용이 발생하면,,,,혼나니까)

 

현재는 삭제권한도 주지않고 특정 티어 이상은 생성도 불가능하나 

논리적으로 사용이 필요한 경우에는 계속해서 권한을 업데이트 해주고 있다.

 

해당 부분을 지켜보던 커뮤니티 학생(당시에 학생이었으나 지금은 대학원생.)이 재밌는 아이디어를 제공했다.

 

매번 내가 권한을 주면서 밤새는 모습을 보아서 그랬는가?

나를 AI 봇으로 만들어서 24시간 돌리겠다는 재밌는 아이디어를 제공했고 프로세스는 아래와 같다.

 

 

  1. AWS IAM 관리자가 이 요청을 실시간으로 처리해줄 수 없다.
  2. 1번으로 인해 요청자는 요청이 처리되기 전까지 개발을 진행할 수 없다.
  3. 그렇기 때문에 슬랙으로 권한에 대한 요청을 받고
  4. AI 가 이를 해결한다.

 

 

해당 서비스는 오류메세지로부터 추출된 필요 권한 리스트의 위험도를 측정하고 이를 기준으로 세가지 플로우가 발생할 수 있는데,

 

  1. 측정된 위험도가 기준(80/100)보다 낮다
  2. 측정된 위험도가 기준(80/100)보다 높다 & IAM 계정 관리자가 권한 부여를 승인한다
  3. 측정된 위험도가 기준(80/100)보다 높다 & IAM 계정 관리자가 권한 부여를 거절한다

이 3가지 상황에 맞게, 리액션으로 현재 상태를 공유 / 관리자에게 권한 부여 확인 요청 DM 전송 / 권한 부여 등을 수행한다.

 

구조도는 아래와 같다.

 

 

 

봇진성은 기본적으로 AWS Lambda 에서 작동하는 서비스고. Python 3.11 + Serverless Framework 로 개발 및 배포를 진행했다.  위 아키텍처 그림에서도 나타나 있듯이 Slack 과 GPT API 를 사용하므로, slack\_sdkopenai 라이브러리를 필요로 했고,

 

# serverless.yml
service: myService

provider:
  name: aws

layers:
  hello:
    path: layer-dir # Lambda Layer 파일 경로(.zip 파일 경로 등)
    name: ${sls:stage}-layerName # Lambda Layer 이름
    description: blabla # Lambda Layer 의 설명 텍스트
    compatibleRuntimes: # 해당 Lambda Layer 를 사용할 수 있는 런타임
      - python3.11
    compatibleArchitectures: # 호환 아키텍처
      - x86_64
      - arm64

 

AWS Lambda 에서 기본적으로 제공되는 라이브러리 그 외의 라이브러리를 사용하려면, 대부분 Lambda Layer 로 업로드하여 사용하고. Serverless Framework Docs 공식 문서에서는 위와 같은 serverless.yml 가 Lambda Layer 로 작성되어 있었고, 이를 토대로 작성했다.

 

오류 해결

Runtime.ImportModuleError: Unable to import module 'handler': No module named 'pydantic_core._pydantic_core'

 

배포를 하는 과정에서 위와 같은 에러를 만났는데  Lambda Layer 를 잘못 올렸을 때 자주 발생하던 에러인 No module named '~~~~' 의 형태였다. 정말 간단하게 필요 라이브러리만 추가해주면 해결될 오류인데.. 아무리 해도 해결이 쉽지 않았고,

 

이 오류와 관련된 여러 글들을 읽어봤는데, 의심되는 부분을 해당 깃허브에서 발견했고.이 질문글의 댓글에서는 다음과 같이 말하고 있었다. "AWS Lambda 와 개발 환경 간의 아키텍처 차이 때문에 발생하는 오류이다"

 

# requirements.txt
openai==0.28
slack_sdk==3.27.1

# serverless.yml
plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    useDownloadCache: false
    useStaticCache: false

 

그래서 직접 로컬에서 PIP 로 라이브러리를 설치하고, 이를 .zip 파일로 압축하여 레이어로 등록시키는 방식이 아닌 다른 방법을 찾았다.  Serverless Framework 의 플러그인들 중 serverless-python-requirements 를 사용하면, Python 프로젝트의 의존성 관리를 비교적 쉽게 할 수 있다.

 

  requirements.txt 또는 Pipfile 에 명시된 Python 패키지를 자동으로 패키징하고 배포 패키지에 포함시켜주고

이때 serverless-python-requirements 의 옵션값으로 useDownloadCache 와 useStaticCache 를 모두 false 로 설정해 주었다. 이는 이미 로컬에 설치되어 있는 AWS Lambda 와 아키텍처가 일치하지 않는 버전 을 재배포에 사용하지 않도록 하기 위해서 설정했다.

 

custom:
  pythonRequirements:
    dockerizePip: true
    useDownloadCache: false
    useStaticCache: false

 

Windows 환경과 Mac 환경을 번갈아가며 개발을 진행하고 있어, 조금 더 안정적인 의존성 관리를 위하여 serverless-python-requirements 플러그인의 dockerizePip 옵션을 사용했다

 

dockerizePip 옵션은 Serverless Framework의 serverless-python-requirements 플러그인에서 사용할 수 있는 옵션이고 Python의 의존성을 설치할 때 Docker를 사용할지 여부를 결정한다.

 

dockerizePip: true로 설정하면, pip 명령이 Docker 컨테이너 내에서 실행되어 Python 패키지를 설치한다.

 

이는 로컬 환경과 AWS Lambda의 실행 환경 간에 차이를 최소화하고, 모든 의존성이 AWS Lambda에서도 문제 없이 작동하도록 도와준다.

 

디폴트 설정인 dockerizePip: false 로 설정하면, pip 명령이 로컬 환경에서 직접 실행되어 Python 패키지를 설치한다.

 

아키텍처 오류?

'내 Lambda Function 도 x86, 내가 개발하고 있는 윈도우 환경도 x86 인데,, 왜 아키텍처 오류가 나는 것이지?' 라는 생각이 들었다, 이에 대해 많은 자료를 찾아봤고, 그에 대한 요약은 아래와 같다.

AWS Lambda 는 기본적으로 Linux 기반의 실행 환경을 한다. 이는 결국 Linux 의 x86 을 의미한다. 하지만 봇진성의 개발 환경은 Windows 의 x86 이였고, 이 사이에 여러 차이가 발생할 수 있다.

같은 x86 이여도, 현재 운영체제에 최적화 되어있기에 이를 다른 환경에서 사용 시에 문제가 발생할 수 있다.

파이썬 패키지 중에는 순수 파이썬으로만 작성되어 있는 것이 있는 반면, C 언어 등이 혼합되어 작성되어 있는 패키지 또한 존재한다. 후자의 경우 운영 체제에 크게 종속되어 이와 같은 오류가 발생할 수 있다.

 

Amazon Linux EC2 에서 배포를 진행하면 어떨까?

 

Amazon Linux EC2 환경에서 Cloud9 으로 배포를 진행했다. 배포를 할 때 사용한 serverless.yml 파일은 아래와 같다. 이러한 설정으로 배포를 진행하게 되면, requirements.txt 에 작성되어 있는 패키지들을 pip 기본 옵션으로 install 하고, 이를 패키징 해서 Lambda 함수에 사용하게 된다.

 

# serverless.yml
service: bjs
frameworkVersion: "3"

provider:
  name: aws
  runtime: python3.11
  architecture: x86_64
  stage: dev
  region: ap-northeast-2
  httpApi:
    id: cvd11qoyh4
  iamRoleStatements:
    - Effect: Allow
      Action:
        - lambda:InvokeFunction
      Resource: "arn:aws:lambda:ap-northeast-2:629515838455:function:bjs*"

functions:
  entrypoint:
    handler: handler.lambda_handler
    timeout: 30
    tags:
      service: bot-jinseong
    events:
      - httpApi:
          path: /bjs
          method: POST
  attach-policy:
    handler: bjs-attach-policy.lambda_handler
    timeout: 30
    tags:
      service: bot-jinseong
    events:
      - httpApi:
          path: /attach-policy
          method: POST

plugins:
  - serverless-python-requirements

Request API Call Log

 

Lambda x86 과 Amazon Linux x86 은 서로 같은 환경을 공유하기에, serverless-python-requirements 에 별다른 옵션을 주지 않아도, 패키지 사용에 문제가 없는 것을 확인했다.

 

결론

이렇게 Lambda 환경과 개발 환경 간의 차이로 인해서 발생하는 오류를 확인하였고, 이를 해결했다.

Lambda 를 이용한 개발 및 배포는 '이렇게 쉬워도 되나' 싶을 정도로 쉽지만, 그 환경에 대한 이해는 필수임을 배울 수 있었던 좋은 경험이었고 좋은 아이디어와 시도를 해준 인하대학교 김건탁 님한테 다시한번 감사한 마음을 전한다.

 

참고

https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/foundation-arch.html