[AWS] SAM(Serverless Application Model)에 새로운 Lambda Layer 추가하는 방법 (feat. 초보자도 쌉가능)

2023. 5. 12. 18:13개발을 파헤치다/서버 인프라

반응형

Lambda Layers

Lambda Layer는 Lambda 함수에서 사용하는 라이브러리들을 더 손쉽게 관리할 수 있게 해주는 도구인데요. Lambda 함수를 실제 서비스에 사용하다 보면 다양한 패키지들이 얽히고설키게 됩니다. 당연히 함수의 크기가 커지게 되고 관리 또한 불편합니다. 
또, 어떤 패키지들은 런타임 환경을 다르게해야 돌아가는 경우도 있죠.
이런 불편함을 해결해 줄 수 있는 것이 바로 Lambda Layer입니다.
Layer라는 단어에서 느낄 수 있듯이, 여러 패키지가 합쳐진 Lambda 함수를 계층으로 나누는 것인데요. 즉, 여러 패키지들을 계층으로 나누어 따로 관리할 수 있는 것입니다.
이렇게 하면 먼저 Lambda 함수의 크기가 줄어들게 됩니다. 필요한 패키지들을 Layer로 만들어서 관리하기 때문에 적용 여부를 설정하기도 훨씬 간편하죠.

여기에서는 AWS SAM(Serverless Application Model) 프로젝트에서 Lambda Layer를 적용하는 방법을 알아보도록 하겠습니다.
시나리오는 이렇습니다. 현재 구현 중인 API 서버가 있습니다. AWS SAM으로 구성되어 있고 각 API가 Lambda 함수와 연계되는 상황입니다. 데이터 분석을 위해 Mix Panel 패키지를 설치하려 하는데 이것을 Lambda Layer로 적용하려고 합니다.


Lambda Layer를 적용하기 위해서는 패키지를 zip 파일로 압축해야하는데요.
먼저 패키지 설치를 해야 합니다. 위의 프로젝트 구조를 보면 aws_lambdas에는 API 로직에 해당하는 Lambda 함수들이 모여있습니다. 
aws_lambda_layers에는 패키지들이 zip으로 압축되어 모여있는데요.
이것들을 SAM 프로젝트의 template.yaml에서 정의해 주면 됩니다.

 

 

Layer로 올릴 패키지 zip 파일 생성

이제 패키지를 설치하겠습니다. 설치 이전에 먼저 알아두어야 할 사실이 있는데요.
Lambda Layer에 적용할 패키지 설치는 반드시 python이라는 디렉터리 안에서 진행되어야 합니다. 이건 왜 그런 걸까요?
Lambda Layer는 여러 Lambda 함수들이 공통적으로 사용하게 됩니다. 각각의 Lambda 함수들은 Layer를 /opt 디렉터리 밑에 export해서 사용하게 됩니다.
이때 PATH 환경변수를 참조하게 되는데요. 이 변수에 경로가 /opt/python으로 설정이 되어있습니다. 이것은 Layer들이 같은 디렉토리 구조를 갖게 만들어서 여러 Lambda 함수들이 Layer에 접근하여 패키지를 사용할 때 문제없이 동작하게 하기 위한 것입니다.
즉, 경로 문제 때문에 디렉터리 구조를 통일한 것이죠. 그렇기 때문에 python이라는 디렉토리 안에 패키지를 설치하지 않으면 Lambda 함수 실행 시 module을 찾을 수 없다는 에러가 발생하게 됩니다.

자, 그럼 이제 패키지를 설치해 봅시다.
프로젝트의 aws_lambda_layers 디렉터리로 이동한 뒤, python이라는 디렉토리를 생성합니다.

$ cd ./aws_lambda_layers
$ mkdir ./python

python 디렉토리 내에서 패키지를 설치해 줍니다.

$ cd ./python
$ pip3 install -t ./ mixpanel "urllib3<2"

이제 해당 패키지를 zip 파일로 압축합니다.

$ cd ../
$ zip -r python-mixpanel.zip ./python



urllib3 Lambda 이슈

앞서 mixpanel 패키지를 설치할 때 urllib3 <2라는 부분이 붙는데요. 이에 대한 얘기를 좀 해봐야 합니다. mixpanel 패키지를 설치하면 내부적으로 requests 패키지와 urllib3 패키지가 설치됩니다. 이때 urllib3 패키지에 이슈가 좀 있는데요. 2.0.3 버전으로 올라가면서 Boto3와 호환성 문제가 발생하게 되었습니다. Boto3는 AWS 서비스를 사용하기 위한 라이브러리인데요.

{"errorMessage": "Unable to import module 'prompt_runner': cannot import name 'DEFAULT_CIPHERS' from 'urllib3.util.ssl_' (/var/task/urllib3/util/ssl_.py)", "errorType":"Runtime.ImportModuleError", "requestId": "5700983c-a460-4e87-bef6-6cbb309d1659", "stackTrace":[]}

Boto3와 urllib3 2.0.3 버전 호환성 문제 때문에 위와 같은 에러가 발생하게 됩니다. 따라서 이 문제를 해결하기 위해 mixpanel 패키지 설치 시 urllib3의 버전대를 2 버전 이하로 조정해줘야 합니다. urllib3<2라는 표현은 2 버전대 이하에서 가장 안정적인 패키지 버전으로 설치를 한다는 의미입니다. 이렇게 설치를 하고 zip으로 압축하면 에러 없이 Lambda 함수에서 안정적으로 실행됩니다.

Lambda Layer 속성 정의


이제 template.yaml에 Lambda Layer 속성을 정의해야 합니다.

# template.yaml

  LambdaLayerPythonMixPanel:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: python-mixpanel
      ContentUri: ../aws_lambda_layers/python-mixpanel.zip
      CompatibleRuntimes:
        - python3.9
      RetentionPolicy: Retain
      
      

위처럼 Layer zip 파일 위치와 이름 그리고 호환 런타임을 적어줍니다. 
이렇게 정의를 하면 필요한 Lambda 함수에서 Layer 추가를 통해 사용할 수 있습니다.

Lambda 함수에 Layer 적용

TestApi:
Type: AWS::Serverless::Function
Properties:
    FunctionName: TestApi
    CodeUri: TestApi
    Handler: lambda_function.lambda_handler
    Runtime: python3.9
    Role: !GetAtt RoleLambdaStepFunction.Arn
    Layers:
    - !Ref LambdaLayerPythonRequestsToolbelt
    - !Ref LambdaLayerPythonMixPanel
    Events:
    AnyMethod:
        Type: Api
        Properties:
        RestApiId: !Ref AuthorizerApi
        Auth:
            ApiKeyRequired: true
            Authorizer: UserAuthorizer
        Path: '/test-api'
        Method: ANY
Metadata:
    BuildMethod: makefile

이제 Lambda 함수를 정의할 때 Properties > Layers에 앞서 정의한 Lambda Layer 속성을 넣어주면 적용이 끝난 것입니다.
이렇게 Layer를 정의해 두고 필요한 Lambda 함수에만 선택해서 적용할 수 있습니다.

반응형