3分で作る、S3イベントで実行するLambda

AWS製の Chalice というサーバーレスアプリケーションフレームワークを使用して、S3イベントで実行するLambdaを爆速で作成します。
2020.04.24

前回の S3イベントバージョンです。Chaliceを使ってS3の各種イベントをトリガーにLambdaを起動してみたいと思います。

環境

  • macOS Catalina 10.15.4
  • Python 3.7.7
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.4
BuildVersion:	19E287

$ python3 -VV
Python 3.7.7 (default, Mar 10 2020, 15:43:33)
[Clang 11.0.0 (clang-1100.0.33.17)]

やってみる

仮想環境の作成

今回は Python で標準機能の venvを利用します。

$ mkdir chalice-example && cd chalice-example
$ python3 -m venv venv

仮想環境の有効化

$ source ./venv/bin/activate
(venv) $

Chaliceのインストール

(venv) $ pip install chalice

パッケージのインストール

画像処理に使用するパッケージをインストールします。

(venv) $ pip install boto3 Pillow

プロジェクトの作成

new-projectコマンドを利用してプロジェクトの雛形を作成します。s3-event-lambda フォルダが作成され、各種ファイルが作成されています。

(venv) $ chalice new-project s3-event-lambda

コーディング

app.pyの内容を下記のようにします。処理内容は指定したバケットにオブジェクトが作成された時に、キーが prefixsuffixに合致するものを通知対象としています。画像のリサイズを行い、別のバケットにアップロードしています。

app.py

import logging
import uuid

import boto3
from PIL import Image
from chalice import Chalice
from chalice.app import S3Event

app = Chalice(app_name='s3-event-lambda')
app.log.setLevel(logging.INFO)

s3 = boto3.client('s3')


def resize_image(image_path, resized_path):
    with Image.open(image_path) as image:
        image.thumbnail(tuple(x / 2 for x in image.size))
        image.save(resized_path)


@app.on_s3_event(bucket='chalice-s3-event-demo',  # 必須: 対象バケット名
                 events=['s3:ObjectCreated:*'],   # オプション: 対象イベント (省略時は s3:ObjectCreated:*)
                 prefix='images/',                # オプション: 対象プレフィックス
                 suffix='jpg',                    # オプション: 対象サフィックス
                 name='resize-image')             # オプション: Lambda名 (省略時は関数名を使用)
def lambda_handler(event: S3Event):
    bucket = event.bucket
    key = event.key
    tmp_key = key.replace('/', '')
    image_path = '/tmp/{}{}'.format(uuid.uuid4(), tmp_key)
    resized_path = '/tmp/resized-{}'.format(tmp_key)
    
    s3.download_file(bucket, key, image_path)
    resize_image(image_path, resized_path)
    s3.upload_file(resized_path, '{}-resized'.format(bucket), key)
    
    app.log.info("resized image: %s", event.key)

必要なライブラリの設定

実行に必要なライブラリを requirements.txtに記載します。これによりデプロイ時に一緒にアップロードされます。

(venv) $ pip freeze | grep boto3 >> requirements.txt
(venv) $ pip freeze | grep Pillow >> requirements.txt
(venv) $ cat requirements.txt
boto3~=1.12.42
Pillow~=7.1.1

S3バケットの作成

画像をアップロードするバケットと、リサイズした画像をアップロードするバケットを作成します。バケット名はユニークである必要があるので、ソースコードとあわせて適宜変更してください。

$ aws s3 mb s3://chalice-s3-event-demo
make_bucket: chalice-s3-event-demo

$ aws s3 mb s3://chalice-s3-event-demo-resized
make_bucket: chalice-s3-event-demo-resized

デプロイ

(venv) $ chalice deploy --stage dev
Creating deployment package.
Creating IAM role: s3-event-lambda-dev
Creating lambda function: s3-event-lambda-dev-resize-image
Configuring S3 events in bucket chalice-s3-event-demo to function s3-event-lambda-dev-resize-image
Resources deployed:
  - Lambda ARN: arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:s3-event-lambda-dev-resize-image

作成されたものを確認

Lambda

IAMロール

ポリシーにS3の権限が自動で付与されています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": [
                "*"
            ],
            "Sid": "49a732cbfcc7454f8c3fc9ced179612d"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        }
    ]
}

S3バケットのイベント設定

オブジェクトの作成イベントでLambdaが呼び出される設定になっています。

動作確認

S3にトリガー条件に適合する画像をアップロードして見ます。

リサイズ用のバケットを確認します。Lambdaによってリサイズ処理されていることが分かります。

ログを確認します。

後片付け

次のコマンドで作成したリソースが削除できます。ロググループは削除されないので手動で消す必要があります。

(venv) $ chalice delete --stage dev

指定できるイベント

下記が指定できるイベント一覧です。複数組み合わせて指定することができます。詳細はAWSドキュメントをご参照ください。

Amazon S3 イベント通知の設定 - Amazon Simple Storage Service

  • s3:ObjectCreated:*
  • s3:ObjectCreated:Put
  • s3:ObjectCreated:Post
  • s3:ObjectCreated:Copy
  • s3:ObjectCreated:CompleteMultipartUpload
  • s3:ObjectRemoved:*
  • s3:ObjectRemoved:Delete
  • s3:ObjectRemoved:DeleteMarkerCreated
  • s3:ObjectRestore:Post
  • s3:ObjectRestore:Completed
  • s3:ReducedRedundancyLostObject
  • s3:Replication:OperationFailedReplication
  • s3:Replication:OperationMissedThreshold
  • s3:Replication:OperationReplicatedAfterThreshold
  • s3:Replication:OperationNotTracked

さいごに

スケジュール実行と同様に非常に簡単にS3イベントと連携できるLambdaが作成できました。

参考情報