Amazon Web Services ブログ

Amazon S3 Object Lambdaの紹介 – コードを利用して S3 から取得するデータを処理

Amazon Simple Storage Service(S3)にデータを保存すると、複数のアプリケーションで使用するためにデータを簡単に共有することができます。しかし、それぞれアプリケーションごとに固有の要件があり、データの異なるビューが必要になる場合があります。例えば、eコマースアプリケーションによって作成されたデータセットには個人識別情報(PII)が含まれる場合がありますが、データ分析のために処理するときには個人識別情報は不要であり、編集(マスキング等)がされているべきです。一方、同じデータセットがマーケティングキャンペーンに使用されている場合は、顧客ロイヤルティデータベースからの情報など追加の詳細データで補填する必要があるかもしれません。複数のアプリケーションにデータの異なるビューを提供するには、現在、2つのオプションがあります。データの派生コピーを追加作成、保存、維持して、各アプリケーションに独自のカスタムデータセットを持たせるオプションと、S3 の前にプロキシレイヤーとしてインフラストラクチャを構築および管理して、リクエストごとにデータをインターセプトして処理するオプションです。両オプションともに複雑性とコストが追加で発生するため、S3 チームはよりよいソリューションを構築することを決定しました。

S3 から取得したデータをアプリケーションに返す前に独自のコードを追加して処理できる新機能、 S3 Object Lambda が、本日(2021 年 3 月 19 日)、利用可能になったことをお知らせします。 S3 Object Lambda は既存のアプリケーションと連携し、AWS Lambda 関数を使用して、S3から取得するデータを自動的に処理および変換します。Lambda 関数は標準の S3 GET リクエスト のインラインで呼び出されるため、呼び出し元のアプリケーションコードを変更する必要はありません。
この方法を利用して、同じデータセットから複数のビューを簡単に提供でき、Lambda 関数を更新することで、これらのビューをいつでも変更することができます。

このアプローチによって単純化できる多くのユースケースの例を以下に示します。

  • 個人識別情報を編集した状態で分析、または本番環境以外の環境にデータを提供します。
  • XML から JSON への変換など、データ形式の変換します。
  • 他のサービスまたはデータベースの情報を利用してデータを拡張します。
  • ダウンロード中のファイルを圧縮または解凍します。
  • オブジェクトを要求したユーザーなど発信者固有の情報を利用してリクエスト時に画像のサイズ変更や透かし入れを行います。
  • データにアクセスするためのカスタムの認可ルールを実装します。

いくつかの簡単な手順で S3 Object Lambda を利用できます。

  1. ユースケースに合わせてデータを変換する Lambda 関数を作成します。
  2. S3 管理コンソールから S3 Object Lambda アクセスポイントを作成します。
  3. 上で作成した Lambda 関数を選択します。
  4. S3 Object Lambda がオリジナルの S3 オブジェクトにアクセスできるように、サポートする S3 アクセスポイントを提供します。
  5. 新しい S3 Object Lambda アクセスポイントを使用して S3 からデータを取得するように、アプリケーション設定を更新します。
  6. S3 Object Lambdaがどのように機能するかをよりよく理解するために、それを実践してみましょう。

S3 Object Lambda 用のLambda関数を作成する方法

目的の関数を作成するために、S3 Object LambdaからLambda関数が受け取る入力イベントの構文を確認することから始めます。


{
    "xAmzRequestId": "1a5ed718-5f53-471d-b6fe-5cf62d88d02a",
    "getObjectContext": {
        "inputS3Url": "https://myap-123412341234.s3-accesspoint.us-east-1.amazonaws.com/s3.txt?X-Amz-Security-Token=...",
        "outputRoute": "io-iad-cell001",
        "outputToken": "..."
    },
    "configuration": {
        "accessPointArn": "arn:aws:s3-object-lambda:us-east-1:123412341234:accesspoint/myolap",
        "supportingAccessPointArn": "arn:aws:s3:us-east-1:123412341234:accesspoint/myap",
        "payload": "test"
    },
    "userRequest": {
        "url": "/s3.txt",
        "headers": {
            "Host": "myolap-123412341234.s3-object-lambda.us-east-1.amazonaws.com",
            "Accept-Encoding": "identity",
            "X-Amz-Content-SHA256": "e3b0c44297fc1c149afbf4c8995fb92427ae41e4649b934ca495991b7852b855"
        }
    },
    "userIdentity": {
        "type": "IAMUser",
        "principalId": "...",
        "arn": "arn:aws:iam::123412341234:user/myuser",
        "accountId": "123412341234",
        "accessKeyId": "..."
    },
    "protocolVersion": "1.00"
}

この getObjectContext プロパティには、Lambda 関数にとって最も役立つ情報がいくつか含まれています。
inputS3Urlpresigned URL であり、サポートされたアクセスポイントから Lambda 関数がオリジナルのオブジェクトをダウンロードすることができる情報です。この方法により、Lambda 関数は、オリジナルのオブジェクトを取得するために S3 の読み取り権限を持つ必要はなく、各呼び出しごとに処理するオブジェクトのみにアクセスすることができます。
outputRouteoutputToken は、Lambda 関数によって編集されたオブジェクトを返送するための新 API である WriteGetObjectResponseで利用する二つのパラメータです。

configurationプロパティはS3 Object Lambda アクセスポイントとサポートされたアクセスポイントの 2 つの Amazon Resource Name(ARN)を持っています。

userRequestプロパティは、URL のパスや HTTP ヘッダーなど、元のリクエストの詳細情報を提供します。
最後に userIdentityセクションは、元のリクエストを行ったユーザーの詳細を返し、データアクセスをカスタマイズするために利用できます。

入力イベントの構文がわかったので、Lambda 関数を作成できます。シンプルな例として、次の Lambda 関数は Python で記述されたもので、オリジナルのオブジェクトのすべてのテキストを大文字に変更する関数です。

import boto3
import requests

def lambda_handler(event, context):
    print(event)

    object_get_context = event["getObjectContext"]
    request_route = object_get_context["outputRoute"]
    request_token = object_get_context["outputToken"]
    s3_url = object_get_context["inputS3Url"]

    # Get object from S3
    response = requests.get(s3_url)
    original_object = response.content.decode('utf-8')

    # Transform object
    transformed_object = original_object.upper()

    # Write object back to S3 Object Lambda
    s3 = boto3.client('s3')
    s3.write_get_object_response(
        Body=transformed_object,
        RequestRoute=request_route,
        RequestToken=request_token)

    return {'status_code': 200}

Lambda 関数のコードを見ると、3つの主要なセクションがあります。

  • まず、入力イベント内の inputS3Url はオリジナルのオブジェクトをダウンロードするために利用します。これは、presigned URL なため、Lambda 関数は S3 の読み取り権限は必要ありません。
  • それから、テキストを全て大文字に変換します。ユースケースに合わせて関数の挙動をカスタマイズするために、この部分はご自身で変更する必要がある部分です。例えば、個人識別情報(PII)を検知し編集するために、Amazon ComprehendDetectPiiEntities API で PII エンティティを見つけ 、アスタリスク、または、編集されたエンティティタイプであったことを示す説明等に置き換えます。
  • 最後に、新しい WriteGetObjectResponse API  を使用して、変換の結果を S3 Object Lambda に送り返します。この方法により、変換されたオブジェクトは、Lambda 関数によって応答可能な最大サイズよりもはるかに大きなサイズにできます。より大きなオブジェクトの場合、WriteGetObjectResponse API はストリーミングデータ転送を実装するためのチャンク転送エンコーディング をサポートします。Lambda 関数は、ステータスコード(この場合は200 OK )と最終的なエラーを返すだけでよく、オプションで S3 APIのGetObject 説明されているように返されたオブジェクトのメタデータをカスタマイズできます。

依存関係を含めて関数をパッケージ化し、Lambda にアップロードします。なお、 S3 Object Lambda が使用する Lambda 関数の最大実行時間は 60 秒であり、Lambda 関数が WriteGetObjectResponse API を呼び出すには AWS Identity and Access Management(IAM)アクセス許可が必要であることに注意してください。

コンソールからS3 Object Lambda アクセスポイントを作成する方法

S3 管理コンソールでS3 バケットの1つにS3のアクセスポイントを作成します。

それから、先ほど作成したS3のサポートされるアクセスポイントを利用してS3 Object Lambdaのアクセスポイントを作成します。 Lambda 関数は、サポートされたアクセスポイントを利用してオリジナルのオブジェクトをダウンロードします。

以下に示すように、S3 Object Lambda アクセスポイントの設定時に上記で作成したLambda関数の最新バージョンを選択します。オプションで、バイト範囲またはパート番号 を使用してリクエストのサポートを有効にできます。今回はそれらを無効のままにしておきます。S3 Object Lambda でバイト範囲とパート番号を使用する方法を理解するには、AWS ドキュメントを参照してください

S3 Object Lambda のアクセスポイントを構成する際に、前に説明したサンプルイベントの configurationpayload でわかるように、そのアクセスポイントからのすべての呼び出しに対してLambda 関数に渡されるpayloadに文字列を設定できます。この方法で、複数の S3 Object Lambda アクセスポイントに同じ Lambda 関数を構成し、payloadの値を利用してそれぞれのアクセスポイントごとの動作をカスタマイズできます。

最後に、通常の S3 アクセスポイントと同様にポリシーを設定して、このObject Lambda のアクセスポイントを通して、オブジェクトへのアクセスを提供できます。現時点では、ポリシーはからのままにしておきます。次にデフォルトのオブションはそのままにして、すべてのパブリックアクセスをブロックし、 S3 Object Lambda アクセスポイントを作成します。

ここまでで、S3 Object Lambda アクセスポイントは準備ができましたので、それをどのように使用できるか見てみましょう。

S3 Object Lambda アクセスポイントの使用方法

S3 コンソールで新しく作成した Object Lambda のアクセスポイントを選択します。プロパティで後で使用できるようにARNをコピーします。

AWSコマンドラインインタフェース(CLI) を利用して、S3 Object Lambda アクセスポイントの背後にあるS3バケットにいくつかの文章を含むテキストファイルをアップロードします。

aws cp s3.txt s3://danilop-data/

既存のアプリケーションで S3 Object Lambda を使用するのは非常に簡単です。S3 バケットを S3 Object Lambda アクセスポイントのARNに置き換え、S3 Object Lambda を使う際に利用される S3 Object Lambda ARN の新しい構文を受け入れるためにAWS SDKs を更新する必要があります。

例えば、これは先ほどアップロードしたテキストファイルをダウンロードする Python スクリプトです。最初に、S3 バケットから直接、次にS3 Object Lambda アクセスポイントからダウンロードします。2つのダウンロードの唯一の違いは、Bucketパラメーターの値です。

import boto3

s3 = boto3.client('s3')

print('Original object from the S3 bucket:')
original = s3.get_object(
  Bucket='danilop-data',
  Key='s3.txt')
print(original['Body'].read().decode('utf-8'))

print('Object processed by S3 Object Lambda:')
transformed = s3.get_object(
  Bucket='arn:aws:s3-object-lambda:us-east-1:123412341234:accesspoint/myolap',
  Key='s3.txt')
print(transformed['Body'].read().decode('utf-8'))

手元のラップトップで以下のスクリプトを実行します。

python3 read_original_and_transformed_object.py

これが受け取った結果です。

オリジナルのS3のオブジェクト:
Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance. This means customers of all sizes and industries can use it to store and protect any amount of data for a range of use cases, such as data lakes, websites, mobile applications, backup and restore, archive, enterprise applications, IoT devices, and big data analytics.

S3 Object Lambdaで処理されたオブジェクト:
AMAZON SIMPLE STORAGE SERVICE (AMAZON S3) IS AN OBJECT STORAGE SERVICE THAT OFFERS INDUSTRY-LEADING SCALABILITY, DATA AVAILABILITY, SECURITY, AND PERFORMANCE. THIS MEANS CUSTOMERS OF ALL SIZES AND INDUSTRIES CAN USE IT TO STORE AND PROTECT ANY AMOUNT OF DATA FOR A RANGE OF USE CASES, SUCH AS DATA LAKES, WEBSITES, MOBILE APPLICATIONS, BACKUP AND RESTORE, ARCHIVE, ENTERPRISE APPLICATIONS, IOT DEVICES, AND BIG DATA ANALYTICS.

最初の出力はソースバケットから直接ダウンロードされ、期待どおりに元のコンテンツが表示されます。二つ目の出力は、オブジェクトが取得されるときにLambda 関数によって処理され、その結果、すべてのテキストが大文字になります。

S3 Object Lambda のユースケース

S3 Object Lambda を使用してオブジェクトを取得する場合、S3 バケットに存在するオブジェクトと同じ名前である必要はありません。Lambda 関数は、ファイル名またはHTTPヘッダーの情報を使用して、カスタムオブジェクトを生成できます。
例えば、sunset_600x400.jpgのような名前の付いた画像を S3 Object Lambda アクセスポイントを使って要求した場合、Lambda 関数はsunset.jpgの名前の付いた画像を検索し、ファイル名に記載されている最大の幅と高さに合うようにサイズを変更できます。この場合、指定されたオブジェクトキーは presigned URLで使用されるものとは異なるため、Lambda 関数は元の画像を読み取るためのアクセス許可を必要とします。

もう1つの興味深いユースケースは、あるデータベースのコンテンツに基づいて、動的に生成される order.jsonitems.csvといったJSONまたはCSVドキュメントを取得するユースケースです。リクエスト HTTP ヘッダーのメタデータを使用して、orderId を渡すことができます。いつものように、お客様の創造性は、ここで説明したユースケースをはるかに超えると思います。

これは、S3 Object Lambda の仕組みとその使用方法を説明する短いビデオです。

 

利用可能地域と価格

S3 Object Lambda はアジアパシフィック(大阪)、 AWS GovCloud(米国東部)、 AWS GovCloud(米国西部)、中国(北京)、中国(寧夏)を除くすべての AWS リージョンで本日利用可能です。S3 Object Lambda は、AWS 管理コンソールAWS コマンドラインインターフェース(CLI) 、および AWS SDKs で使用できます。現在、aws s3 cp のようなハイレベルな S3 コマンドは S3 Object Lambda アクセスポイントからのオブジェクトをサポートしていませんが、aws s3api get-object などの低レベルな S3 API コマンドを使用できます。

S3 Object Lambda を使用すると、データの処理に必要な AWS Lambda の計算とリクエストの料金、および S3 Object  Lambda がアプリケーションに返すデータの料金を支払う必要があります。また、Lambda 関数によって呼び出される S3 リクエストの料金も支払う必要があります。価格情報の詳細については、Amazon S3 の価格ページ を参照してください。

この新機能により、複数のアプリケーション間でデータを共有および変換することがはるかに簡単になります。

S3 Object Lambdaの使用を開始して、ストレージアーキテクチャを今すぐ簡素化してください。 

– ダニエル

日本語訳は Professional Services のコンサルタント、堀場 隆文が担当しました。原文はこちらです。