AWSのlambdaはサーバレスアーキテクチャで非常に扱いがいいのですが、一つ難点があって、アップロードできるファイルサイズが限られていることです。
最大50MのZIPファイルまでなのですが、裏技を使って展開時に500M以上のファイルを使うことができます。
そのカラクリは、Lambdaの/tmp以下は500Mまで使うことができます。この領域に、Lambdaが起動するときにファイルをS3から読み込めば、非常に大きなライブラリが必要なプログラムも動かすことができます。
以下は、pythonにてkeras+tensorflow+opencvを動かすサンプルです。
ライブラリ準備
python3を使用します。
ライブラリは、あらかじめ、EC2でAmazonLinuxを使って作成しておきます。
requirements.txt
1 2 3 4 | keras opencv-python tensorflow numpy |
1 2 | mkdir lib pip3 install -U -r requirements.txt -t lib |
このlib以下にライブラリがインストールされます。
1 | find lib -name "*.pyc" -exec rm -rf {} ¥; |
pycは削除しておきます。しなくてもいいですが。。。
これを全てLambdaの起動時に追加してもいいのですが、ロードが面倒になるので2つに分けます。
1 2 3 4 5 6 7 8 | mv lib lib_other mkdir lib cd lib_other mv cv2* ../lib mv h5py* ../lib mv keras* ../lib mv tensor* ../lib cd .. |
libを固めてS3にアップ
1 2 | zip -r lib.zip lib aws s3 cp s3://bucketname/ |
lambdaディレクトリ
lambda用のディレクトリに、先ほど分けたlib_otherのライブラリを入れておきます。
これ全部を入れてようやく50Mぐらいまでに収まります。
1 2 3 4 5 | mkdir lambda_dir cd lambda_dir mkdir vendor cd vendor cp -pr ../../lib_other/* . |
lambdaプログラム
lambdaのプログラムには少し工夫が必要です。
起動時に、S3から先ほどアップしたlib.zipをダウンロードし展開、ロードします。
lambda_functioy.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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ファンクションが作ることができます。