AWSのlambdaはサーバレスアーキテクチャで非常に扱いがいいのですが、一つ難点があって、アップロードできるファイルサイズが限られていることです。
最大50MのZIPファイルまでなのですが、裏技を使って展開時に500M以上のファイルを使うことができます。
そのカラクリは、Lambdaの/tmp以下は500Mまで使うことができます。この領域に、Lambdaが起動するときにファイルをS3から読み込めば、非常に大きなライブラリが必要なプログラムも動かすことができます。
以下は、pythonにてkeras+tensorflow+opencvを動かすサンプルです。
ライブラリ準備
python3を使用します。
ライブラリは、あらかじめ、EC2でAmazonLinuxを使って作成しておきます。
requirements.txt
keras opencv-python tensorflow numpy
mkdir lib pip3 install -U -r requirements.txt -t lib
このlib以下にライブラリがインストールされます。
find lib -name "*.pyc" -exec rm -rf {} ¥;
pycは削除しておきます。しなくてもいいですが。。。
これを全てLambdaの起動時に追加してもいいのですが、ロードが面倒になるので2つに分けます。
mv lib lib_other mkdir lib cd lib_other mv cv2* ../lib mv h5py* ../lib mv keras* ../lib mv tensor* ../lib cd ..
libを固めてS3にアップ
zip -r lib.zip lib aws s3 cp s3://bucketname/
lambdaディレクトリ
lambda用のディレクトリに、先ほど分けたlib_otherのライブラリを入れておきます。
これ全部を入れてようやく50Mぐらいまでに収まります。
mkdir lambda_dir cd lambda_dir mkdir vendor cd vendor cp -pr ../../lib_other/* .
lambdaプログラム
lambdaのプログラムには少し工夫が必要です。
起動時に、S3から先ほどアップしたlib.zipをダウンロードし展開、ロードします。
lambda_functioy.py
import sys
import os
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), './vendor'))
import boto3
import zipfile
import importlib
def lambda_handler(event, context):
s3 = boto3.resource("s3")
def load_zip(file):
print("load_zip:"+file)
s3.Bucket(bucket_name).download_file(libfiledir+"/"+file,"/tmp/"+file)
with zipfile.ZipFile("/tmp/"+file) as zip:
zip.extractall("/tmp")
os.remove("/tmp/"+file)
if os.path.exists("/tmp/lib") is False: # 2回目以降はスキップ
load_zip("lib.zip")
sys.path.append('/tmp/lib')
importlib.import_module("numpy")
importlib.import_module("scipy")
importlib.import_module("six")
importlib.import_module("yaml")
importlib.import_module("enum")
importlib.import_module("h5py")
importlib.import_module("absl")
importlib.import_module("astor")
importlib.import_module("bleach")
importlib.import_module("external")
importlib.import_module("gast")
importlib.import_module("google.protobuf")
importlib.import_module("grpc")
importlib.import_module("html5lib")
importlib.import_module("markdown")
importlib.import_module("werkzeug")
importlib.import_module("wheel")
importlib.import_module("cv2")
importlib.import_module("tensorflow")
importlib.import_module("keras")
import cv2
import keras
import numpy as np
こんな感じでコードを書きます。
Lambdaは一度起動すると、しばらくはインスタンスが残っているので、2回目以降に再度S3からダウンロードするのを防ぎます。
こんな感じで、500M以上のモジュールをつかったLambdaファンクションが作ることができます。