LoginSignup
1
0

Lambda Layer上でインポートするパッケージをローカルでインストール〜アップロードまで

Last updated at Posted at 2024-03-26

これは何?

今までインフラエンジニアで開発経験など無かったのですが, 趣味やサーバレスの検証も兼ねてLambda Layerを初めて自分で作成し実装した際にライブラリが異なることでinvalid ELF headerエラーが発生した際の対処法になります.

調査

Pythonで、momentoライブラリを導入してLambda Layerにアップロードした際に、 invalid ELF header エラーが発生しました.
(momentoについて詳しくはこちら)

https://docs.momentohq.com/ja/cache

これは、ローカルで実行しているPythonライブラリとLambdaで実行しているPythonライブラリが異なるため、ELF(Executable and Linking Format)ヘッダーの規定が異なりインポートエラーが発生しているものとなります.

{
  "errorMessage": "Unable to import module 'lambda_function': /opt/python/cryptography/hazmat/bindings/_rust.abi3.so: invalid ELF header",
  "errorType": "Runtime.ImportModuleError",
  "requestId": "xXxXxX-xXxXxX ...",
  "stackTrace": []
}

そのため, Lambdaで使用しているPythonのコンテナイメージを取得し、ローカル上でパッケージインストールする方法を後述で解説します.

imageについて

Lambdaのランタイムバージョンのイメージについてはこちらを参考にdocker pullを実行します.
実行するランタイムの最新バージョンを以下の赤線のように指定し, コピーしました.

image.png

手順

フォルダの構成は以下の通りとなります.

./path/to/dir
├── layer.zip
├── python
│   ├── momento
│   ├── momento-1.19.1.dist-info
│   │     :
│   │     :
│   │         
│   ├── requests
│   └── requests-2.31.0.dist-info
└── requirements.txt

ローカルフォルダ./pythonにパッケージをインストールします.

重要なのはフォルダ名を ./python として、下にパッケージをインストールします.

これはLambdaレイヤーで使用するライブラリはpythonフォルダ上である必要があるためです.
https://repost.aws/ja/knowledge-center/lambda-import-module-error-python

重要: Python 用にインポートするライブラリを /python フォルダ内に配置します.

cd ./path/to/dir

docker run --rm -v ./:/var/task public.ecr.aws/sam/build-python3.10:1.110.0-20240222205900 \
pip install -r requirements.txt -t ./python

zipコマンドでパッケージを圧縮.

zip -r layer.zip ./python

圧縮できたら, あとはLambda Layerに圧縮ファイルをアップロードすれば準備完了です.

テスト

Lambda Layerのバージョンを更新した後, 以下のLambda関数を実行します.

MOMENTO_API_KEY は Momento Cache でRead/Write権限を持ったAPIキー.
MOMENTO_CACHE_NAME は Momento Cacheのキャッシュ名を環境変数として指定する. かもしくは)

import json
import os
from datetime import timedelta
import logging
from momento import CacheClient, Configurations, CredentialProvider
from momento.responses import CacheGet, CacheSet, CreateCache, ListCaches, CacheIncrement
import requests

MOMENTO_API_KEY = os.getenv('MOMENTO_API_KEY', 'xXxXxXxXxXxXxXxXxX')
MOMENTO_CACHE_NAME = os.getenv('MOMENTO_CACHE_NAME', 'test-cache-name')

logger = logging.getLogger()
logger.setLevel("INFO")

def lambda_handler(event, context):
    client = create_cache_client()
    client.set(MOMENTO_CACHE_NAME, "test-key", "test-value")
    res = client.get(MOMENTO_CACHE_NAME, "test-key")
    logger.info("Result: {}".format(res))
    return {
        'statusCode': 200,
        'body': json.dumps(res)
    }

def create_cache_client():
    cache_client = CacheClient(
        configuration=Configurations.Laptop.v1(),
        credential_provider=CredentialProvider.from_environment_variable("MOMENTO_API_KEY"),
        default_ttl=timedelta(seconds=600),
    )
    return cache_client

これでエラーが出力されなければOKになります.

リファレンス

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0