Amazon Lambda関数の構築、展開、管理ツールであるApexを使ってLambdaに関数をデプロイしてみる。
実行環境
macOS High Sierra 10.13.3
環境構築
Lambdaがサポートしている言語はいくつかありますが、今回はPython3.6系でやっていきます。
まず最初に仮想環境を作ります。(任意です)
Pythonの仮想環境を作る方法はいくつかありますが、今回はcondaを使います。
Anacondaをインストールしてcondaコマンドを実行します。
lambda-envという名前で環境作成
$ conda create -n lambda-env python=3.6
環境の切り替え
$ source activate lambda-env
$ python --version
Python 3.6.3 :: Anaconda custom (64-bit)
Apexの導入
公式サイトに書いている通りにやっていきます。
http://apex.run/
インストール
$ curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sh
AWS資格情報の設定
AWSの資格情報を環境変数か、~/.aws
以下に設定します。
アクセスキーやシークレットキーはIAMユーザ作成時に取得できます。
とりあえず何もアクセス権限を持たないlambda-user
というユーザを作成し、aws cliで設定を行います。
$ aws configure --profile lambda-user
[lambda-user]
aws_access_key_id = xxxxxxxx
aws_secret_access_key = xxxxxxx
[lambda-user]
region = ap-northeast-1
output = json
Minimum IAM Policy
まず、以下の(公式サイト参照)IAM PolicyをIAM->ポリシー->ポリシーの作成のJSONタブを選択し、貼り付けます。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"iam:CreateRole",
"iam:CreatePolicy",
"iam:AttachRolePolicy",
"iam:PassRole",
"lambda:GetFunction",
"lambda:ListFunctions",
"lambda:CreateFunction",
"lambda:DeleteFunction",
"lambda:InvokeFunction",
"lambda:GetFunctionConfiguration",
"lambda:UpdateFunctionConfiguration",
"lambda:UpdateFunctionCode",
"lambda:CreateAlias",
"lambda:UpdateAlias",
"lambda:GetAlias",
"lambda:ListAliases",
"lambda:ListVersionsByFunction",
"logs:FilterLogEvents",
"cloudwatch:GetMetricStatistics"
],
"Effect": "Allow",
"Resource": "*"
}
]
}

作成したポリシーを先ほど作成したユーザにアタッチします。(ユーザグループにアタッチして、ユーザをグループに含めるのでも大丈夫です)
プロジェクト作成
$ apex init --profile lambda-user --region ap-northeast-1
初期状態ではnode.jsの関数が用意されています。
.
├── functions
│ └── hello
│ └── index.js
└── project.json
Pythonで関数を作りたいので、helloフォルダは削除します。
関数の作成
今回はPythonのライブラリpandasを使って基本統計量を求める関数を試しに作ってみます。
functions
以下にdescribe
というフォルダを作り移動します。
function.json
という設定ファイルと、index.py
という空のファイル作ります。
{
"description": "pandas describe",
"runtime": "python3.6",
"handler": "index.lambda_handler",
"environment":{
"PYTHONPATH": "/var/runtime:/var/task/site-packages"
}
}
外部ライブラリをLambdaで使いたいときはデプロイパッケージに含める必要があります。
ライブラリの設定ファイルrequirements.txt
を作成します。
pandas==0.23.1
次にライブラリをインストールするフォルダを作成しておきます。
$ mkdir site-packages
フォルダの構成はこんな感じです。
.
├── functions
│ └── describe
│ ├── function.json
│ ├── index.py
│ ├── requirements.txt
│ └── site-packages
└── project.json
pandasとその依存ライブラリをsite-packagesにインストールしたいところですが、
$ pip install -r requirements.txt -t site-packages
これだとmac環境でビルドされたライブラリになり、Amazon Linux環境のLambdaでは実行できません。
例えば、import numpy
した関数をLambdaにdeployして実行すると、
Unable to import module 'index': Missing required dependencies ['numpy']
こんなエラーが出て実行することができません。
LambdaはAmazon Linux環境なので、同じ環境でビルドしたライブラリでないと実行ができないからです。
Linux環境でpip install
dockerでLinuxのコンテナを作ってpip install
します。
https://qiita.com/hoto17296/items/a579c333a8690c96a56c
やり方はこちらの記事を参考にさせていただきました。
$ docker pull python:3.6
$ docker run --rm -v $(pwd):/work -w /work python:3.6 pip install -r requirements.txt -t site-packages
正確にはAmazon Linux環境ではないですが、これでLambdaで実行できます。
Linux上で開発したいときは、
$ docker run -it --name ${CONTAINER NAME} python:3.6 /bin/bash
でコンテナ上に入って開発するなどすれば良さそうです。
(たまに2回pip install
しないとうまくインストールできないライブラリがあったりするので、そういうときはコンテナ上でインストールする必要があったりします)
実行する関数
今回は適当にpandasのdescribe関数を使うだけの関数を作りました。
import pandas as pd
def lambda_handler(event, context):
df = pd.DataFrame({
'hoge': [1, 2, 3, 4, 5],
})
return df.describe().to_json()
deploy
$ apex deploy describe --profile lambda-user --region ap-northeast-1
コンソールから実行
$ apex invoke describe --profile lambda-user --region ap-northeast-1
"{\"hoge\":{\"count\":5.0,\"mean\":3.0,\"std\":1.5811388301,\"min\":1.0,\"25%\":2.0,\"50%\":3.0,\"75%\":4.0,\"max\":5.0}}"
delopyと実行ができていることがわかります。
AWSのコンソールで確認すると、確かにデプロイされていました。
まとめと課題
ApexでAmazon LambdaにPythonの関数をデプロイして実行することができました。
S3にcsvファイルアップロードしたタイミングで実行したりもできるので、Lambdaを使うことで色々できることの幅が広がりそうです。
ただし、deploy packageのサイズの制限があり、分析用のライブラリのサイズによってはLambdaで使えなかったりしました...
そういった場合、どのように解決しているのか気になります