【アップデート】非同期Lambda失敗時の送信先にS3が指定できるようになりました

【アップデート】非同期Lambda失敗時の送信先にS3が指定できるようになりました

Clock Icon2024.11.25

リテールアプリ共創部@大阪の岩田です。

2024/11/20付けのアップデートで非同期呼び出し/イベントソースマッピングから起動するLambdaの処理失敗時に送信先としてS3が指定できるようになりました。

https://aws.amazon.com/jp/about-aws/whats-new/2024/11/aws-lambda-s3-failed-event-destination-stream-event-sources/

さっそく触ってみたので簡単に紹介させて頂きます。

アップデート概要

これまで非同期呼び出し/イベントソースマッピングのLambdaが失敗した場合の送信先には以下4つのサービスが指定できました。

  • SNS
  • SQS
  • Lambda
  • EventBridge

送信先にS3が選択可能に

今回S3バケットが指定できるようになったことで、従来の送信先タイプでは保存できなかったような巨大なペイロードが保存できるようになりました。

仕様など

送信先にS3を指定する場合は以下の仕様があるので抑えておきましょう。

  • S3に保存されるオブジェクトキーは以下のフォーマットになります

    • aws/lambda/async/<function-name>/YYYY/MM/DD/YYYY-MM-DDTHH.MM.SS-<Random UUID>
  • 送信先にS3を指定するにはLambda実行ロールに以下の2つの権限が必要です。

    • s3:PutObject

    • s3:ListBucket

    • KMSキーを利用して対象のバケットが暗号化されている場合はkms:GenerateDataKeyの権限が追加で必要になります。

    • 別アカウントのS3バケットにオブジェクトが保存されないよう、上記の権限に追加のConditionを付与することが推奨されています。
      例:

      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Sid": "S3BucketResourceAccountWrite",
                  "Effect": "Allow",
                  "Action": [
                      "s3:PutObject",
                      "s3:ListBucket"
                  ],
                  "Resource": "arn:aws:s3:::*/*",
                  "Condition": {
                      "StringEquals": {
                          "s3:ResourceAccount": "111122223333"
                      }
                  }
              }
          ]
      }
      

やってみる

それでは実際に試していきましょう。

Lambdaの設定で処理失敗時の送信先としてS3バケットを指定します。

処理失敗時の送信先にS3を指定

Lambdaのコードは以下の通りで、絶対に失敗する実装になっています。

def lambda_handler(event, context):

    raise Exception('Lambdaの実行に失敗')

上記のLambdaを以下のコードで非同期実行してみます。

import boto3
lambda_client = boto3.client('lambda',region_name='us-east-1')
lambda_client.invoke(FunctionName='<Lambdaの関数名>',InvocationType='Event',Payload=json.dumps({"a":"b"}))

CWLogsのログを確認するとLambdaの実行に失敗したことが確認できます。

Lambda実行失敗のログ

しばらく待ってからS3バケットを確認するとオブジェクトが保存されていることが分かります。

送信先に指定したS3バケットの中身

AWS CLIを使って上記オブジェクトの中身を標準出力に出力してみましょう。

aws s3 cp  s3://<オブジェクトキー> -

結果は以下の通りでした。

{"version":"1.0","timestamp":"2024-11-25T00:13:14.360Z","requestContext":{"requestId":"c97791d4-fad8-4b6d-8ce5-bbd9e3184804","functionArn":"arn:aws:lambda:us-east-1:<AWSアカウントID>:function:lambda-failure-to-s3:$LATEST","condition":"RetriesExhausted","approximateInvokeCount":3},"requestPayload":{"a": "b"},"responseContext":{"statusCode":200,"executedVersion":"$LATEST","functionError":"Unhandled"},"responsePayload":{"errorMessage": "Lambdaの実行に失敗", "errorType": "Exception", "requestId": "c97791d4-fad8-4b6d-8ce5-bbd9e3184804", "stackTrace": ["  File \"/var/task/lambda_function.py\", line 3, in lambda_handler\n    raise Exception('Lambdaの実行に失敗')\n"]}}

Lambda実行時のペイロードもバッチリ保存できていることが分かります。

まとめ

Lambdaの処理がエラーになった場合の送信先としてS3を指定してみました。今回のアップデートによって、これまで面倒なリトライ/リカバリ処理を独自実装していた部分をマネージドサービスに寄せることができるかもしれません。ユースケースに合いそうであれば、うまく活用していきたいですね。

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.