AWS Lambdaでpandasを利用する(Lambda Layers編)

概要

AWSのlambda関数で、外部のライブラリを実行したい場合、昔は、デプロイパッケージに、利用するコードを全て含めてやる必要がありました。
ただ、pandasやscikit-learnなどの重量級のライブラリの場合、毎回アップロードするのは、きついものがあります。
例えば、pandas(依存関係のあるnumpyなども含む)だと、圧縮状態で35Mbyteほどあります。

そこで、AWS Lambda layersの出番です。
これを使うことで、外部ライブラリのアップロードは、1回で済む様になり、自分で書いた部分のみを更新していけば良いことになります。
また、他のlambda関数でも使い回し可能です。
docs.aws.amazon.com

手順

以下、pandasを例にした手順です。

  1. とりあえず、lambda関数の実行環境を確認します。
    • 19年2月現在は、以下の通りでした。
  2. lambdaと実行環境を合わせたEC2を作成します。
  3. EC2へログインして、調べておいたlambdaで実行されるバージョンのpython(今回は、3.7.2)をインストールします。
    • yum list | grep python3 で、出てくれば良いのですが、入っていないのでソースから入れます。
  4. python.orgからソースを取得します。
  5. 解凍して、解凍した先のフォルダへ移動します。
  6. 必要なライブラリをインストールします。
    • yum install gcc openssl-devel bzip2-devel libffi-devel
  7. コンパイルしてインストールします。
    • ./configure --enable-optimizations
    • sudo make altinstall
  8. pandasをインストールするディレクトリ「python/lib/python3.7/site-packages/」を作成します。
    • こうしておくと、以下の理由により、勝手にパスが解決されるので楽です。
      • Lambda Layersは、/opt 配下に、アップロードされたzipファイルを展開します。
      • lambdaは、実行時に、「/opt/python」or 「/opt/python/lib/python3.7/site-packages/」を参照します(他にも見るところはあります)。
  9. 利用したいライブラリ (この場合は、pandas)を上で作ったディレクトリへインストールします。
    • pip3.7 install pandas -t ./python/lib/python3.7/site-packages/
      • 「-t」オプションで、書き出し先を指定しています。
  10. zipで固めます。
  11. これをLambda layersとして、publishしておきます (が、上のAMIのawsコマンドは古いのでアップデートが必要です。)
    • aws lambda publish-layer-version --layer-name [レイヤー名] --zip-file fileb://./hoge.zip --compatible-runtimes python3.7 --region ap-northeast-1 --profile [あなたのプロファイル]
    • レイヤー名は、「hoge」にしています。
  12. 利用したいlambda関数と紐つけます。
    • aws lambda update-function-configuration --function-name [利用したいlambda関数名] --layers arn:aws:lambda:ap-northeast-1:[AWS ID]:layer:hoge:1
    • 「layers」オプションでは、ARNをフルパスで指定します。
    • 最後の数字は、lambda layersのバージョンです(publishするごとに、インクリメントされるので、適宜合わせます)。

以上で、lambdaでpandasを利用する準備が整いました。
最後に、pandasの使用例と実行結果を貼り付けておきます。

import sys;
import json;
import pandas as pd;

def lambda_handler(event,context):
    df = pd.DataFrame([[1,2,3],[4,5,6]]);
    print(df);
    
    return {
        "statusCode": 200,
        "body": json.dumps('Hello pandas!'),
        "version": sys.version,
        "path": sys.path
    };

f:id:marmarossa:20190211235403p:plain
lambda関数の実行結果