これは、なにをしたくて書いたもの?
AWS Lambdaを動かすのに、以前LocalStackを使ってNode.jsで作成した関数を動かしてみました。
LocalStackを使って、AWS Lambdaを試してみる - CLOVER🍀
今回は、ちょっとPythonで作成してみたいと思います。
お題
お題も前のエントリと似たようなもので、ペイロードで与えられたパラメーターを含めて、メッセージを返却する関数を作成します。
pipでインストールするパッケージも利用します。
環境
LocalStackは、Docker Composeで起動。LocalStackは、「192.168.0.3」というホストで動作しているものとします。
docker-compose.yml
version: "3" services: localstack: image: localstack/localstack:0.9.1 ports: - "4567-4593:4567-4593" - "8080:8080" environment: - SERVICES=${SERVICES- } - DEBUG=${DEBUG- } - DATA_DIR=${DATA_DIR- } - PORT_WEB_UI=${PORT_WEB_UI- } - LAMBDA_EXECUTOR=docker-reuse - KINESIS_ERROR_PROBABILITY=${KINESIS_ERROR_PROBABILITY- } - DOCKER_HOST=unix:///var/run/docker.sock volumes: - "/var/run/docker.sock:/var/run/docker.sock"
AWS Lambdaの実行は、「docker-reuse」にしてコンテナを使いまわすようにしています。
- LAMBDA_EXECUTOR=docker-reuse
これを、単に「docker」にするとコンテナが増え続けていきます…。
コードは、以下の環境で作成。
$ python3 -V Python 3.6.7
Lambda関数を作成する
では、Lambda関数を作成しましょう。
AWS Lambdaで利用可能なPythonのバージョン一覧は以下ですが、今回はローカルに合わせてPython 3.6を使うことにしましょう。
Python による Lambda 関数のビルド - AWS Lambda
ライブラリの利用には、仮想環境を使用します。
$ python3 -m venv venv $ . venv/bin/activate
ライブラリには、PyYAMLを使用しました。
$ pip3 install pyyaml
バージョン。
$ pip3 freeze ... PyYAML==5.1
用途に特に意味はないのですが…。
で、こちらのドキュメントを見ながら、関数を作成。
Python の Lambda 関数ハンドラー - AWS Lambda
my-lambda-function.py
import yaml def my_handler(event, context): print('event = {}'.format(event)) print('context = {}'.format(context)) return yaml.dump({ 'word': event['word'] })
これを、zipファイルにパッケージングします。
.zip ファイルアーカイブで Python Lambda 関数をデプロイする - AWS Lambda
今回は、こんなコマンドで作成しました。
$ cd venv/lib/python3.6/site-packages && \
zip -r ../../../../function.zip . && \
cd ../../../../ && \
zip -g function.zip my-lambda-function.py
Lambda関数のデプロイ
では、Lambda関数をデプロイしましょう。
$ aws configure AWS Access Key ID [None]: my-access-key AWS Secret Access Key [None]: my-secret-access-key Default region name [None]: us-east-1 Default output format [None]:
作成したパッケージをデプロイ。作成したLambdaの関数名は、「--handler」オプションで「ファイル名(拡張子なし):関数名」で
登録するようです。
$ aws --endpoint-url http://192.168.0.3:4574 lambda create-function \
--function-name my-lambda \
--runtime python3.6 \
--handler my-lambda-function.my_handler \
--role test-role \
--zip-file fileb://function.zip
{
"FunctionName": "my-lambda",
"FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:my-lambda",
"Runtime": "python3.6",
"Role": "test-role",
"Handler": "my-lambda-function.my_handler",
"VpcConfig": {
"SubnetIds": [
null
],
"SecurityGroupIds": [
null
]
},
"Environment": {
"Variables": {},
"Error": {}
},
"TracingConfig": {}
}
LocalStackに登録するので、「--endpoint-url」での指定が必要です。
$ aws --endpoint-url http://192.168.0.3:4574 lambda create-function \
登録した関数の一覧。
$ aws --endpoint-url http://192.168.0.3:4574 lambda list-functions
{
"Functions": [
{
"FunctionName": "my-lambda",
"FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:my-lambda",
"Runtime": "python3.6",
"Handler": "my-lambda-function.my_handler",
"CodeSize": 50,
"Version": "$LATEST",
"Environment": {
"Variables": {}
}
}
]
}
Lambdaの呼び出し。結果は、引数で指定したファイルに出力されます。
$ aws --endpoint-url http://192.168.0.3:4574 lambda invoke --function-name my-lambda --payload '{"word": "Hello Lambda"}' result.log
{
"StatusCode": 200
}
確認。とりあえず改行は気にしない…。
$ cat result.log "word: Hello Lambda\n"
ここで、ちょっと関数の定義を変更してみます。
def my_handler(event, context): print('event = {}'.format(event)) print('context = {}'.format(context)) return yaml.dump({ 'word': event['word'], 'foo': 'bar' })
更新には、「update-function-code」を使用。
$ aws --endpoint-url http://192.168.0.3:4574 lambda update-function-code --function-name my-lambda --zip-file fileb://function.zip
{
"FunctionName": "my-lambda"
}
再度呼び出し。
$ aws --endpoint-url http://192.168.0.3:4574 lambda invoke --function-name my-lambda --payload '{"word": "Hello Lambda"}' result.log
{
"StatusCode": 200
}
確認。
$ cat result.log "foo: bar\nword: Hello Lambda\n"
ちゃんと、結果が反映されましたね。
最後に、関数を削除しておしまい。
$ aws --endpoint-url http://192.168.0.3:4574 lambda delete-function --function-name my-lambda
確認。
$ aws --endpoint-url http://192.168.0.3:4574 lambda list-functions
{
"Functions": []
}
ログを確認したい
「docker container logs」で確認したい…ところですが、Lambdaの実行が「docker-reuse」だとログが残らず…。
- LAMBDA_EXECUTOR=docker-reuse
これを「docker」にするとログが残るのですが、代わりにLambdaの実行とともに終了したコンテナが増えていく…。
- LAMBDA_EXECUTOR=docker
うーん…。