NeeNetです。
今回はS3のPutイベントで起動するLambdaをAWS SAMでデプロイする方法をご紹介します。
具体的には、以下のリソースをAWS SAMで作成したいと思います。
- S3バケット
- バケットポリシー
- Lambda
- Lambdaの実行ロール
事前準備
AWS SAM CLIのインストールがまだな方は、公式ドキュメントを参考にインストールしてください。
sam --version
コマンドでバージョンが表示できればインストールできています。
$ sam --version
SAM CLI, version 1.113.0
スクリプトの作成
今回のフォルダ構成は以下の通りです。
.
├── handler
│ └── app.py
├── samconfig.toml
└── template.yaml
samconfig.toml
samconfig.toml
には、SAMでデプロイするための設定を記載します。
version = 0.1
[default]
region = "ap-northeast-1"
[default.build.parameters]
debug = true
[default.deploy.parameters]
stack_name = "<YOUR STACK NAME>"
s3_bucket = "<YOUR S3 BUCKET>"
s3_prefix = "sam-deploy"
capabilities = "CAPABILITY_NAMED_IAM"
confirm_changeset = true
<YOUR STACK NAME>
と<YOUR S3 BUCKET>
には、それぞれご自身で決めた任意のスタック名と、SAMのデプロイを行うための資材を配置するS3バケット名を入力してください。
template.yaml
SAMでデプロイするリソースを記載したテンプレートファイルであるtemplate.yaml
は以下の通りです。
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: "SAM Application"
Parameters:
BucketName:
Type: String
Default: "<YOUR S3 BUCKET NAME>"
LambdaName:
Type: String
Default: "<YOUR LAMBDA FUNCTION NAME>"
Globals:
Function:
Timeout: 180 # 180 seconds
MemorySize: 128
Resources:
# S3
MyS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${BucketName}"
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
NotificationConfiguration:
EventBridgeConfiguration:
EventBridgeEnabled: true
# S3 Bucket Policy
MyS3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref MyS3Bucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: AllowSSLRequestsOnly
Action:
- "s3:*"
Effect: Deny
Resource:
- !Sub "arn:aws:s3:::${MyS3Bucket}"
- !Sub "arn:aws:s3:::${MyS3Bucket}/*"
Principal: "*"
Condition:
Bool:
"aws:SecureTransport": "false"
# Lambda
MyLambdaFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub "${LambdaName}"
Role: !GetAtt MyLambdaFunctionRole.Arn
CodeUri: handler/
Handler: app.lambda_handler
Runtime: python3.9
Architectures:
- x86_64
Layers:
- arn:aws:lambda:ap-northeast-1:336392948345:layer:AWSSDKPandas-Python39:15
Events:
S3PutEvent:
Type: S3
Properties:
Bucket: !Ref MyS3Bucket
Events: "s3:ObjectCreated:*"
# IAM Role for Lambda
MyLambdaFunctionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${LambdaName}-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/AmazonS3FullAccess
<YOUR S3 BUCKET NAME>
と<YOUR LAMBDA FUNCTION NAME>
には、それぞれご自身で決めた今回新規作成するS3バケット名とLambda関数名を入力してください。
それぞれのリソースについて簡単に説明すると、まずS3バケットは暗号化を有効にし、EventBridgeへの通知をONにする設定にしています。
またパブリックアクセスについても明示的にブロックするようにしています。
バケットポリシーについては、SSL以外でのアクセスを拒否するように設定しています。
Lambda関数について、アーキテクチャはx86_64とし、LambdaレイヤーとしてマネージドレイヤーであるAWS SDK for pandas
を利用できるようにしています。
AWS SDK for pandas
にはnumpy
やpandas
がモジュールとして含まれているので、ファイル処理等をする際に便利です。
Lambda関数の実行ロールについては、どちらもマネージドポリシーであるAWSLambdaBasicExecutionRole
とAmazonS3FullAccess
を設定しています。
app.py
今回Lambda関数で動かすためのapp.py
は以下の通りです。
import json
import logging
logger = logging.getLogger()
logger.setLevel("INFO")
def lambda_handler(event, context):
s3_bucket = event["Records"][0]["s3"]["bucket"]["name"]
object_key = event["Records"][0]["s3"]["object"]["key"]
logger.info(f"s3_bucket: {s3_bucket}, object_key: {object_key}")
return {"message": "success"}
今回はS3へのPutイベントを契機にLambdaが起動するよう設定しているので、PutされたファイルのS3バケット名とオブジェクトキーをログに表示するようなサンプルにしています。
デプロイと実行
デプロイは以下のコマンドで実行可能です。
$ sam deploy
実行すると、以下のようにスタックのchange setが表示されると思うので、内容を確認します。
デプロイが完了すると、CloudFormation上でsamconfig.toml
に設定したスタック名でデプロイがされていることを確認できると思います。
作成されたS3バケットに適当なファイルをアップロードすると、Lambdaが起動します。
CloudWatchのログを確認すると、以下のようにバケット名とアップロードしたファイルのオブジェクトキーが表示されていることを確認できます。
最後に
今回はS3のPutイベントで起動するLambdaをAWS SAMでデプロイする方法をご紹介しました。
参考になりましたら幸いです。
ご依頼について
NeeNetではIaC(Infrastructure as Code)を利用したAWS上でのインフラ環境の構築、およびその上で動くアプリケーションの開発のご依頼・ご相談をお引き受けしております。
個人・法人問わず、何かご相談事項がございましたら、一度ご連絡いただければと思います。