AWSをいじり倒す(13.lambda)

食わず嫌いしてたlambdaを使ってみる。

 

今回は目的があって、

s3にファイルが入ったタイミングで

tensorflowで作成したモデルを使って推論をするプログラムを動かしたい、というもの。

 

まずは下調べしてみたけど、やっぱりちょっとめんどくさい。

今回は手元にあるpythonのコードを動かすのが目的なんだけど、

import numpyとかpandasとかしてたら、

事前にそれらパッケージをzipでアップロードしてあげないといけないようだ

pandasをLambdaのLayerとして追加する - Qiita

そのパッケージも、ローカルで作ってもだめで、指定したEC2で作る必要がある

 

 

まず最初にややこしいのが、使うpythonのバージョンによって

アップロードするパッケージの生成元となるEC2のAMIを選ばないといけない点

AWS Lambda ランタイム - AWS Lambda

今回使おうとしているpython3.7のOSはAmazon Linux(2ではない)

のでこのAMIを選んでインスタンスを起動。

 

次に、EC2のデフォルトpythonのバージョンが2.7だかなんだかで古いので

目的のバージョンのpythonをインストール。

現時点でyumに対応したpythonは3.6系までしかないので、

3.7以降はソースからインストールするしかない

 

今回はPython3.7.6を使う。

具体的な手順はここが参考になった

AWS Lambdaでpandasを利用する(Lambda Layers編) - marmarossa’s blog

 

まず目的のpythonをダウンロード

curl https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz -o Python-3.7.6.tgz

 

解凍

tar xzf Python-3.7.6.tgz

 

ディレクトリに移動

cd Python-3.7.6

 

必須ライブラリをインストール

yum install gcc openssl-devel bzip2-devel libffi-devel

 

コンパイルしてインストール

./configure --enable-optimizations

sudo make altinstall

 

パッケージをインストールするディレクトリを作成

mkdir python/lib/python3.7/site-packages/

 

pandasのインストール

pip3.7 install pandas -t ./python/lib/python3.7/site-packages/

kerasのインストール

pip3.7 install keras -t ./python/lib/python3.7/site-packages/

 

zipに固める

zip pandaskeras.zip python/ -r

 

S3にアップロード(EC2へのS3アクセス権限付与など忘れずに)

aws s3 mv pandaskeras.zip s3://[s3bucket名]/module/pandaskeras.zip

 

S3のコンソール画面からアップロードされたことを確認して、

オブジェクトURLをメモっておく

f:id:Messerarche:20200701192746p:plain

 

 

 

 

 

lambdaの画面に移動

Additional Resourcesからレイヤーを選択、レイヤーの作成

f:id:Messerarche:20200701035239p:plain


レイヤーの作成。

f:id:Messerarche:20200701192926p:plain

S3からアップロードを選択し

リンクURLに先ほどメモしたURLを貼る
互換性のあるランタイムオプションはPython3.7を選択

 

 

次に関数の作成

f:id:Messerarche:20200701161804p:plain

 

まずはHello Worldから。

f:id:Messerarche:20200701162014p:plain


ロールは特に用意していないので作ってもらう

f:id:Messerarche:20200701162114p:plain

関数の作成を実行。

 

ほどなくして作成が完了

f:id:Messerarche:20200701162402p:plain

 

f:id:Messerarche:20200701162421p:plain

何かいろいろできそう(小並感)

 

ともあれ関数を実行してみる。

右上のテストボタンを押す

f:id:Messerarche:20200701163234p:plain

こんな画面が出てくるので、イベント名に適当にhelloと入力、作成

 

f:id:Messerarche:20200701163328p:plain

再度テストを実行

 

f:id:Messerarche:20200701163355p:plain

結果がずらずらとでてきた。とりあえずは動いたようだ。

 

 

さて、問題のimport pandasができるのかを試す

レイヤーを選択

f:id:Messerarche:20200701163526p:plain



お客様のレイヤーにさっき登録したレイヤーが出てきた。

f:id:Messerarche:20200701193452p:plain
numpyとscipyならデフォルトで用意してくれとるのね。

 

ちなみに、余談だが試行錯誤してるときはこんな怒られ方をした

f:id:Messerarche:20200701163800p:plain

どうも、追加パッケージは合計262MBまでしかだめらしい。

AWS LambdaでTensorFlow 2.0を使った画像分類 - ユニファ開発者ブログ

この辺にいかにやりくりするか、みたいなテクニックが書いてあった。

ええ、そこって気を使わないかんとこなの・・・。

いろんなものimportして大きめのプログラム動かそうと思ったらlambdaは諦めて

EC2で普通に動かすしかないのかも。

 

 

とりあえず追加は完了。

f:id:Messerarche:20200701193743p:plain



 

プログラムにimport pandasとかを追加してテストしてみる。

f:id:Messerarche:20200701193836p:plain

ソースを変更したら、Saveしたのちにテストを実行


f:id:Messerarche:20200701193924p:plain


どうやらうまくいったらしい。

import kerasも試してみる

 

f:id:Messerarche:20200701194540p:plain

 

ぐえ、tensorflowもいりますよ、と(凡ミス)。

しかしtensorflowは馬鹿デカ容量なので

上に書いたように262MBなんて余裕で超えて、そのままlambdaには持ってこれない。
 

 

一応EC2にインストールしてみる

pip3.7 install tensorflow -t ./python/lib/python3.7/site-packages/ --no-cache-dir

(--no-cache-dirについては以下)

AWS EC2でMemoryErrorとNo space left on deviceで詰まった話 - Qiita

 

ずらずら、とインストールされた中からダメ元で重そうなのを消してみる。

f:id:Messerarche:20200701195221p:plain

tensorboardとかは確かにいらんよなぁ

 

容量を確認するコマンドを打ってみる

du -sh ./*/

f:id:Messerarche:20200701195749p:plain

本体が1.5GB〜!!

 

犯人探ししていこう

f:id:Messerarche:20200701195917p:plain

 

これか。

f:id:Messerarche:20200701200308p:plain

 

これ消しちゃまずそうなやつ・・・え、みんなどうやってんの?

Running TensorFlow on AWS Lambda using Serverless - Mike Moritz - Medium

slim — Removes unneeded files and directories such as *.so*.pycdist-info, etc.

 

まじ?これ消していいの?(わかってない

どうみてもプログラムの本体だから無理だよなぁ

 

物は試しってことで除外してzipしてみる

[ec2-user@ip-172-31-14-167 ~]$ zip pkt.zip python/ -r -x python/lib/python3.7/site-packages/tensorflow/python/_pywrap_tensorflow_internal.so

 

できたのは164MBのzip

f:id:Messerarche:20200701202612p:plain

 

レイヤーに登録しようとすると

f:id:Messerarche:20200701202728p:plain

これでもでかすぎてだめか。

 

 tensorflowさえ使わなければ万事うまくいきそうなんだけど、

使うんだよな〜〜

 

次回、どうも成功してる事例っぽいserverlessからデプロイするやり方をダメ元で試してみる・・・。 

 

 

あと、s3に格納されたファイルを引数としたり、

結果をs3に格納したりする方法を探してみると

【AWS Lambdaの基本コードその2】 S3へのファイル保存 | ナレコムAWSレシピ

これをみると普通にpythonのコードでs3にアクセスする感じなのね。

てっきり、lambdaの機能として提供されているのかと思った。

 

 そうなってくると、あとはimportがうまくいけば

この関数のトリガーイベントの設定と、

成功時・失敗時ログをどこに流すかって設定するぐらいか。

 

なんだかlambdaの全体像は見えてきたが、超えるべき山がまだ高い