【Lambdaチュートリアル】Amazon S3 トリガーを使用してサムネイル画像を作成する
はじめに
Lamdbaの以下のチュートリアルでかなりハマってしまいました...。調べてもよくわからず、M1 Macを使用しているからなのか?など色々難しく考えてしまっていたのですが、解決方法はシンプルでした。
ちなみにどんなエラーだったのかというと
上記のような記事を参考にさせていただき、ローカルでzipファイルを作成してレイヤーに追加する方法を試したところ、以下のエラーが出ていました。Unable to import module 'lambda_function': cannot import name '_imaging' from 'PIL' (/opt/python/PIL/__init__.py)",
ちなみに今回は以下のアーキテクチャとランタイムを使用して行います。
アーキテクチャ x86_64
ランタイム Python 3.8
S3バケットを作成
まず、S3バケットを2つ作成してください。
1つ目は<お好きなバケット名>
、2つ目は<1つ目に作成したバケット名>-resized
として作成してください。
作成したら、1つ目のバケットに今回リサイズしたい画像をアッロードしてください。
ファイル名は後から必要になるので控えておいてください。
IAMポリシーの作成
JSON
を選択、
以下のバケット名
の部分をご自身が作成した名前に変更し作成してください。
今回はポリシー名をチュートリアルに習ってAWSLambdaS3Policy
としました。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:PutLogEvents",
"logs:CreateLogGroup",
"logs:CreateLogStream"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::<1つ目に作成したバケット名>/*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::<2つ目に作成したバケット名>/*"
}
]
}
IAMロールの作成
サービスまたはユースケース
で
lambda
を選択して、次へ
を選択、
許可ポリシーでは先ほど作成したAWSLambdaS3Policy
を検索して選択して、次へ
を選択、
今回はロール名をlambda-s3-role
とします。
ロール名を入力したら下へスクロールしてロールを作成
を選択してロールを作成してください。
Lambda関数の作成
一から作成
を選択、今回は関数名をpillow-test-func
ランタイムはPython 3.8
、アーキテクチャはx86_64
を選択します。
アクセス権限では、既存のロールを使用する
を選択し、先ほど作成したロール名(lambda-s3-role
)を選択し、関数の作成
を押してLambda関数を作成してください。
関数を作成したら、下記リンクにアクセスし、関数デプロイパッケージを作成する
のサンプルコードからpython
をコピーして
lambda_function.py
に記述します。
import boto3
import os
import sys
import uuid
from urllib.parse import unquote_plus
from PIL import Image
import PIL.Image
s3_client = 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)
def lambda_handler(event, context):
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = unquote_plus(record['s3']['object']['key'])
tmpkey = key.replace('/', '')
download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey)
upload_path = '/tmp/resized-{}'.format(tmpkey)
s3_client.download_file(bucket, key, download_path)
resize_image(download_path, upload_path)
s3_client.upload_file(upload_path, '{}-resized'.format(bucket), 'resized-{}'.format(key))
記述し終わったら、Deploy
を選択し変更を反映させてください。
PillowライブラリのARNを取得する
下記リンクから今回使用するpillowライブラリのARNを取得してください。
今回はランタイムはPython 3.8
、リージョンはap-northeast-1 Asia Pacific (Tokyo)
なので以下のように該当するcsvを選択してARNを確認します。
CSVからPillow
のARNを確認し、この後のレイヤーの追加で使用するので控えておきます。
現在はarn:aws:lambda:ap-northeast-1:770693421928:layer:Klayers-p38-Pillow:10
というARNでした。
Pillowとは
Pythonで画像処理を行うためのライブラリで、今回はリサイズするために使用します。
レイヤーの追加
下記を選択するかスクロールで下の方へ進み、
レイヤーの追加
を選択してください。
ARNを指定
を選択し、先ほど確認したARNを入力したら検証
を押してください。
関数のアーキテクチャ、ランタイムと相互性があることを確認したら、追加
を選択してレイヤーを追加してください。
テストの作成
Test
を選択します。
今回はイベント名tutorial-test-event
として、イベントJSONには下記を修正した下記の内容を記述してください。
- <リージョン名>、
- <1つ目に作成したバケット名>(2箇所あります)、
- <1つ目に作成したバケットにアップロードした画像の名前>
{
"Records":[
{
"eventVersion":"2.0",
"eventSource":"aws:s3",
"awsRegion":"<リージョン名>",
"eventTime":"1970-01-01T00:00:00.000Z",
"eventName":"ObjectCreated:Put",
"userIdentity":{
"principalId":"AIDAJDPLRKLG7UEXAMPLE"
},
"requestParameters":{
"sourceIPAddress":"127.0.0.1"
},
"responseElements":{
"x-amz-request-id":"C3D13FE58DE4C810",
"x-amz-id-2":"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"
},
"s3":{
"s3SchemaVersion":"1.0",
"configurationId":"testConfigRule",
"bucket":{
"name":"<1つ目に作成したバケット名>",
"ownerIdentity":{
"principalId":"A3NL1KOZZKExample"
},
"arn":"arn:aws:s3:::<1つ目に作成したバケット名>"
},
"object":{
"key":"<1つ目に作成したバケットにアップロードした画像の名前>",
"size":1024,
"eTag":"d41d8cd98f00b204e9800998ecf8427e",
"versionId":"096fKKXTRTtl3on89fVO.nfljtsv6qko"
}
}
}
]
}
イベントJSONの記述が済んだら保存
を押して作成したテストを保存してください。
テストの実行
Test
を押すと先ほど作成したテストが実行されます。
バケットを確認してリサイズが行われていることを確認してください。
1つ目のバケット
2つ目のバケット
リサイズされたものが保存されていることが確認できました✨
Task timed outというエラーメッセージが出た場合
Lambdaのタイムアウト値がデフォルトでは3秒に設定されているため、それ以上時間がかかると表示されるエラーです。
設定
から
一般設定
を選択して、編集
を押してください。
今回は30秒に変更して保存
します。
変更後、無事にエラーが解決しているかテストして確認してください。
終わりに
何かありましたらお気軽にコメント等いただけると助かります。
ここまでお読みいただきありがとうございます🎉
Discussion