AWS SAMでLambdaにレイヤー設定しよう!~Pythonライブラリ編~

eyecatch-aws-sam-layer-python
目次

AWS Lambdaのレイヤーとは?

概要

AWS Lambdaを利用しているといろいろなライブラリを使いたいと思うことがあると思います。しかしLambdaはデフォルトのままではLambdaのランタイムにインストールされているライブラリしか用いることができません。その問題を解決するのがAWS Lambdaのレイヤーです。レイヤーはLambda関数で利用できる共有ライブラリや依存関係、カスタムランタイムなどを提供するための機能です。

レイヤーを使用することで、共通のコードや依存関係を一元化し、Lambda関数の構造をシンプルにし、開発と運用の効率を向上させることができます。例えばPythonでデータ操作を共通化したいと考えたとき、「NumPy」や「Pandas」などの標準外のライブラリをレイヤーとして作成し複数のLambda関数で共有することができます。これによりLambda関数ごとにライブラリをパッケージ化する手間を省け、簡単に標準外ライブラリを利用できます。

このレイヤーを作成するには、LinuxやDockerを利用してzipを作成する方法があります。しかしこの方法ではレイヤーの作成が複雑で、バージョン管理やメンテナンスもしづらくなってしまいがちです。公式ドキュメントにレイヤー作成手順が掲載されていますが、なにやら面倒そうですよね。

そこで本記事ではAWS SAMを利用します。SAMの詳細は下記の記事で説明していますが、ざっくり言うとSAMはLambdaを効率よく開発する機能でレイヤーの作成も気軽にできます。本記事ではSAMを利用したレイヤーの作成を解説します。

レイヤーの追加方法

レイヤーを追加する方法はインストールしたい関連のファイル群(パッケージやバイナリなど)をzipにして配置する方法(配置先はS3、SAMプロジェクト、Lambdaのマネジメントコンソールrequirements.txtを利用する方法の2つがあります。前者は依存関係を正しく理解してzipファイルを作成する必要があり、難易度は高めです。そこで今回は後者のrequirements.txtを利用する方法を紹介します!

レイヤーの構造

レイヤーを正しく動作させる上でLambdaランタイムのレイヤーパスを正しく理解することが重要です。公式ドキュメントを確認するとPythonの場合は下記がレイヤーパスとして指定されています。なおAWS SAMを利用したライブラリを追加した場合、2つ目の/opt/python/lib/python3.8/site-packagesに配置されることになります。

  • /opt/python:
    • 主にカスタムモジュールやスクリプトを配置します。
    • Pythonの標準モジュールパスに追加されるため、import時にモジュール名だけで参照できます。
  • /opt/python/lib/python3.x/site-packages:
    • python3.xはLambda作成時のPythonのバージョンになります。
    • サードパーティライブラリや標準パッケージを配置します。
    • Pythonの標準ライブラリパスに配置されるため、通常のPythonのライブラリと同じ方法でimportできます。

AWS SAMによるレイヤー設定

前提

Cloud9(OSはubuntu 22.04 LTS、インスタンスタイプはt2.micro、dockerがインストール済)
Lambdaランタイム(Python3.12)

プロジェクトの初期化

Cloud9でsam initよりhello worldをテンプレートとしたsam-appプロジェクトを作成し、template.yamlからEventsとOutputsエントリに関わる記述を削除します。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.12
      Architectures:
        - x86_64

詳細については過去記事にAWS SAMのプロジェクト初期化の方法を解説していますので参考にしてください。こちらの記事のLambda関数とyamlの編集まで構築が終わりましたら次の手順に進んでください。

ディレクトリとrequirements.txtの作成

さっそくレイヤーを作成していきましょう。今回はデータ分析でよく利用されるNumpyを追加していきます。

まずはレイヤーを管理するディレクトリとファイルを作成します。下のコマンドの1行目から4行目を参考にnumpy_layerディレクトリとrequirements.txtを作成します。正常に作成できると16行目、17行目のようにディレクトリとその直下にrequirements.txtが作成されます。

cd sam-app
mkdir numpy_layer
cd numpy_layer
touch requirements.txt

tree sam-app
sam-app/
├── README.md
├── __init__.py
├── events
│   └── event.json
├── hello_world
│   ├── __init__.py
│   ├── app.py
│   └── requirements.txt
├── numpy_layer
│   └── requirements.txt
├── samconfig.toml
├── template.yaml
└── tests
    ├── __init__.py
    ├── integration
    │   ├── __init__.py
    │   └── test_api_gateway.py
    ├── requirements.txt
    └── unit
        ├── __init__.py
        └── test_handler.py

続いてpythonでインストールするライブラリを管理するためのファイルであるrequirements.txtを編集します。17行目のファイルを開き、numpyと記述するだけです。ちなみに15行目にもrequirements.txtがありますが、間違えないようにしてくださいね。15行目のrequirements.txtはLambda関数のランタイムに直接ライブラリをインストールしたい場合に利用します。

vi requirements.txt
numpy

app.pyの編集

続いてapp.pyの編集をしてnumpyの動作を確かめるコードを記述します。2行目にnumpyのインポート文を、9~10行目にnumpyを利用した行列の定義とその表示処理を記述します。

import json
import numpy as np

def lambda_handler(event, context):
    print('hello sam')
    print(json.dumps(event))
    
    # 行列の定義と表示
    mat = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    print(mat)

template.ymlの編集

最後にtemplate.ymlを編集します。ここでは11行目で念のためにTimeoutを60秒に修正、22~23行目でLambdaとLayerの対応付けを追記、25~32行目でLayer自体の設定を追記します。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app


Globals:
  Function:
    Timeout: 60

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.12
      Architectures:
        - x86_64
      Layers:
        - !Ref NumpyLayer
      
  NumpyLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      ContentUri: 'numpy_layer/'
      CompatibleRuntimes:
        - python3.12
    Metadata:
      BuildMethod: python3.12

    動作確認

    ここまで記述の修正は完了したので最後にビルド&デプロイでLambda関数を作成していきます。まずは下記のコマンドを実行します。

    sam build -u
    sam deploy
    Deploy this changeset? [y/N]: y

    Lambdaのコンソールマネジメントを確認すると下図のようにsam-appで作られたLambdaが存在していることがわかります。さらにLayerをクリックすると今回作成したNumpyLayerが設定されていることもわかります。

    sam_layer

    そしてこの関数をテスト実行すると下図のように出力結果に行列の表示が確認できます。ここまでできると後は好きなライブラリrequirements.txtに追記するだけで外部ライブラリを簡単に追加することができます!

    最後に作成したLambda関数を削除したい場合は下記のコマンドで削除ください。

    sam delete
    Are you sure you want to delete the stack sam-app in the region us-east-1 ? [y/N]: y
    Do you want to delete the template file 1919fadd17425ffb833b1e2a25aacea1.template in S3? [y/N]: y

    まとめ

    今回の記事ではAWS SAMを利用したレイヤーの追加について解説しました。今までzipを作成して設定していた方からするととても簡単に感じたのではないかと思います。AWS SAMの少ない学習コストでLambda開発効率がアップしますのでぜひ試してみてくださいね!

    よかったらシェアしてね!
    • URLをコピーしました!
    • URLをコピーしました!

    この記事を書いた人

    Hack Luck Labの管理人hakula(ハクラ)です。2012年にSIerに新卒入社し、SE、新規事業、情シスを担当。その後、ITコンサルを経て、現在はバックエンドエンジニア。過去にはC#、SQL Server、JavaScriptで開発を行い、現在はPython、Rest Framework、Postgresql、Linux、AWSなどを使用しています。ノーコードツールやDX関連も興味あり。「技術は価値を生むために使う」ことが信条で、顧客や組織への貢献を重視しています。

    目次