今まではGCPを使っていたのですが、最近は会社でAWSを使い始めました
今回はLambdaを使う必要があったので入門しました
Lambdaで関数を作成する際にはzipをアップロードしたりS3からアップロードしたりブラウザで書いたりする方法があるようですが
- ローカルでもある程度開発したものをLambdaにデプロイしたい
- デプロイもコマンド一発で行いたい
これらを満たすものとして今回はServerless Frameworkを使用してみました
導入自体は npm install -g serverless
で完了するので楽ちんですね
今回はPython3を使って構築することにしたので下記のようにPython3でのテンプレートを指定して新規プロジェクトを作成します
slsはserverlessのalias $ sls create -t aws-python3 -p s3_objects
ファイルとしてはhandler.py
とserverless.yml
の2つが生成されてYAMLファイルはLambdaでの設定などを記載して
Pythonのファイルには実際の関数の中身を書いていきます
例えば今回は定期的にS3の指定されたパス配下のファイル一覧をSlackに通知するとします
まずSlackへの通知は下記のパッケージを使用します
ただLambdaには上記のパッケージは最初は使えないので自分で追加してあげる必要があります
Serverless Frameworkにはプラグインを追加することが出来るのですが、今回はPythonのパッケージリストを記載したファイルを用意しておくとデプロイ時のパッケージに含んでくれる下記のプラグインを使用しました
プラグインのインストール自体はnpm install --save serverless-python-requirements
で完了してserverless.ymlに下記のように追加します
plugins: - serverless-python-requirements
後はserverless.yml
, handler.py
と同じ階層にrequirements.txt
というファイルを追加して下記のように定義してあげます
※boto3はここで定義しなくてもLambda上では使えるみたいですが今回はローカルでもpip install -r requirements.txt
でいれたかったので定義しています
boto3==1.4.4 slackweb==1.0.5
serverless.ymlには下記のように設定しました
今回は最低限動くものを定義しています
公式にサンプルが用意されているので参考になりました
service: hoge-service frameworkVersion: ">=1.14.0 <2.0.0" provider: name: aws runtime: python3.6 stage: prd region: ap-northeast-1 role: arn:aws:iam::xxxxxxxxx:role/ServerlessRole plugins: - serverless-python-requirements functions: hello: handler: handler.hello events: - schedule: cron(30 9 * * ? *) # 毎日9:30に実行される environment: BUCKET_NAME: 'hoge-bucket' S3_KEY_PREFIX: 'hello/world' WEBHOOK_URL: 'https://hooks.slack.com/services/xxxxxxxx/yyyyyyyyy'
handler.pyは下記のようにします
import json import boto3 import slackweb from os import getenv def hello(event, context): slack = slackweb.Slack(url=getenv("WEBHOOK_URL")) slack.notify(text='START!!') objects = _get_all_objects() all_keys = [row['Key'] for row in objects] slack.notify(text="ファイル一覧です\n%s" % "\n".join(all_keys)) slack.notify(text='END!!') return all_keys def _get_all_objects(start_after='', objects=[]): client = boto3.Session().client('s3') response = client.list_objects_v2( Bucket=getenv('BUCKET_NAME'), Prefix=getenv('S3_KEY_PREFIX'), StartAfter=start_after ) if 'Contents' in response: objects.extend(response['Contents']) if 'IsTruncated' in response: _get_all_objects(start_after=objects[-1]['Key'], objects=objects) return objects
S3からオブジェクトする際のlist_objects_v2では一度に最大で1000件までしか取れないので再帰的にメソッドを呼び出して指定されたディレクトリ配下のすべてのオブジェクトを取れるようにしています
ローカルで確認する際には
$ sls invoke local -f hello
を使用してデプロイしてそのLambda関数を呼び出すのは
# デプロイ $ sls deploy -v # 作成されたLambda関数をcallする $ sls invoke -f hello
これにより毎日13時にhoge-bucketBucketのhello/world配下のファイル一覧が通知されるようになりました
Lambda便利ですねー