0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

S3EventからLamdaコンテナを動かす

Posted at

今回やること

S3 EventでLambdaジョブ(コンテナ)を実行させる

  • 入力: csvファイル
  • 出力: jpgファイル

image.png

やりたかったこと

S3のPutObjectに応じたS3イベントを使って、
Python(Maplotlib/Pandas)を動かして、生成物を再度S3へ保存。

経緯

  • S3 EventとLambdaを組み合わせて簡単に作ろうとした。
  • Maplotlibのボリュームが大きく、レイヤーの容量上限250MBにどうしても入りきらない。
  • Lmadaコンテナを使う

やってみる

やった結果:

Step1 S3イベントの確認する

print(event)だけするLambdaとS3インベントをつないで、
実行の様子とeventメッセージをCloudWatchLogsで確認する。
3つのファイル(hoge.png/hoge1.png/hoge2.png)を同時に放り込んだ。
image.png
Putしたオブジェクトの数だけLambdaが実行されていることが確認できる。

公式ドキュメントにメッセージ構造が示されている。

Step2 Dockerイメージを作成する

ドキュメントに従って必要なものを用意する

  • lamda_function.py
  • requirements.txt
  • Dockerfile

lamda_function.py
import json
import uuid

import boto3
import matplotlib.pyplot as plt
import pandas as pd

s3client = boto3.client("s3")

def handler(event, context):
    records = event["Records"]
    outBucketName = "s3event-experiment"

    for record in records:
        
        csvfilname = "/tmp/" + str(uuid.uuid4()) + ".csv"

        tmp_key = record["s3"]["object"]["key"]
        tmp_bucket = record["s3"]["bucket"]["name"]
        
        s3client.download_file(tmp_bucket, tmp_key, csvfilname)

        df = pd.read_csv(csvfilname,dtype=float)
        colList = list(df.columns)

        plt.figure(figsize=(12,3))
        plt.plot(df[colList[0]],df[colList[1]])
        plt.plot(df[colList[0]],df[colList[2]])

        keyname =  str(uuid.uuid4()) + ".jpg"
        jpgfilename = "/tmp/" + keyname
        plt.savefig(jpgfilename)
        with open(jpgfilename, "rb") as f:
            s3client.put_object(Body=f,Bucket=outBucketName,Key=keyname,ContentType="image/jpeg")
        
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

CMD [ "lambda_function.handler" ]にてLambda関数がキックされる。このため、lamda_function.pyはDcokerイメージのルートディレクトリにCOPYする必要がある。ハンドラの名前やPythonファイルの名前は自由に変更することもできそう。/tmp/以下のファイル名は、被る可能性を排除するためuuidを使った。

Dockerfile
FROM public.ecr.aws/lambda/python:3.11

# Copy requirements.txt
COPY requirements.txt .

# Copy function code
COPY Scritpts/lambda_function.py .

# Install the specified packages
RUN pip install -r requirements.txt

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "lambda_function.handler" ]

Dockerfile作成後、ECRにプッシュする

Step3 全体の実行結果を確認する。

出力のバケットと入力のバケットを同じバケットとした。
大体3秒ぐらいで実行完了している。
image.png

そのほか色々思ったこと

  • 実行時間
    今回使ったECRイメージは300MBもある。にもかかわらず、End2Endで3秒ぐらいの時間しかかからなかった。コンテナの起動が爆速だ。これならAPIGatewayなどと組み合わせて色々な用途で使えそう。
    image.png
    ECRにpushしたイメージをLambdaに登録する際、1分ぐらいの時間がかかった。コンテナ版Lambdaは実行の立ち上がりが非常に速い理由がここにあるのかもしれない。デプロイ時間中にイメージがLambda実行基盤にキャッシュされているとか…。

  • 制約
    Lambdaなので、実行時間最大15分の制約がある。最大永続ストレージ容量もコンテナ最大サイズも10GBなのでよほど引っ掛かることはなさそう。
    VPCも使えなさそう。マネコンからは通常のランタイム版LambdaではVPCが選べるが、コンテナ版LambdaではVPCが選べなかった。VPC的なタスクでは従来通りのFargateを使うしかないのか。
    Lambdaレイヤーが使えないので、共通コンポーネントをLambda上で共有できない。CodeGuruなどレイヤーを使った他サービスの利用もできない。Lambdaでもありコンテナでもあるので、この実行形態に合ったサービスを使いたい。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?