[アップデート] Lambdaにテナント分離モードが設定可能になり、テナント毎にLambda実行環境を分離できるようになりました!

[アップデート] Lambdaにテナント分離モードが設定可能になり、テナント毎にLambda実行環境を分離できるようになりました!

セキュリティ要件を満たしやすくなるアップデートです! コールドスタートの発生頻度と追加料金にだけ注意しましょう。
2025.11.21

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

2025/11/19付けのアップデートでLambda Functionに「テナントの分離モード」が設定できるようになりました。

https://aws.amazon.com/jp/blogs/aws/streamlined-multi-tenant-application-development-with-tenant-isolation-mode-in-aws-lambda/

これはマルチテナントのSaaSアプリケーションなどを想定した機能であり、この機能を有効化することでテナントごとにLambda実行環境を分離できるようになります。これでセキュリティ要件でテナント毎のコンピューティング環境分離が要求されるようなユースケースにおいてもLambdaが採用しやすくなりました!

どのレイヤでの分離なのかまで詳細は明記されていませんが、Worker単位での分離となるとAWS側も大量のベアメタルEC2インスタンスが必要になるので、恐らくFirecrackerのMicroVMレベルでの分離と考えて良いでしょう。

やってみる

さっそくテナント分離モードを有効化したLambda Functionを試していきましょう。

マネコンから色々確認してみる

まずはイメージを掴みやすくするためにマネコンから試していきます。テナント分離モードはLambda Function作成時に有効化可能で、作成後に有効化/無効化はできません。作成時のマネコン表示はこんな感じです。

Lambda Function作成時のテナント分離モードの指定

作成後は「関数の概要」の部分から設定値が確認できます。

関数の概要から確認できるテナント分離モード

テナント分離モードを有効化したLambdaはInvoke時にテナントIDの指定が必須となります。マネコンからテスト実行する際も以下のようにテナントIDの指定が要求されます。

テストイベントのテナントID指定

AWS CLIからInvokeしてみる

AWS CLIからも実行してみましょう。リリースノートを見ると2.32.0のリリースノートに

  • api-change:lambda: Added support for creating and invoking Tenant Isolated functions in AWS Lambda APIs.

の記載があります。

https://raw.githubusercontent.com/aws/aws-cli/v2/CHANGELOG.rst

ということでテナント分離モードが有効化されたLamdba Functionの実行はAWS CLI 2.32.0以後が必要になります。

まず2.32.0以前のAWS CLIからInvokeを試みます。

aws lambda invoke --function-name <Lambda Function名> -

すると以下のエラーになりました。

An error occurred (InvalidParameterValueException) when calling the Invoke operation: The invoked function is enabled with tenancy configuration. Add a valid tenant ID in your request and try again.

テナントIDが必須なので指定するように言われていますね。

改めてテナントIDを指定して実行してみます。

aws lambda invoke --function-name <Lambda Function名> --tenant-id 1  -

今度はAWS CLIのバージョンが低いため--tenant-idというオプションに未対応というエラーになりました。

usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:

  aws help
  aws <command> help
  aws <command> <subcommand> help

Unknown options: --tenant-id, -

AWS CLIをバージョンアップしてから再実行してみます。

aws --version
aws-cli/1.43.1 Python/3.9.24 Linux/6.1.156-177.286.amzn2023.x86_64 exec-env/CloudShell botocore/1.41.1
aws lambda invoke --function-name <Lambda Function名> --tenant-id 1 -

今度は無事にInvokeできました!

{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}

API GWと統合してみる

API GWとLambdaを統合する場合ですが、ドキュメントを見る限りクエリパラメータのtenant-idもしくはリクエストヘッダのX-Tenant-IDでテナントIDを指定したLambdaを呼び出せそうなのですが単純にLambdaプロキシ統合を利用するだけでは呼び出せませんでした。

https://docs.aws.amazon.com/lambda/latest/dg/tenant-isolation-invoke.html#tenant-isolation-invoke-apigateway

HTTP API

curl https://<API GWのID>.execute-api.us-east-1.amazonaws.com?tenant-id="123" -H "X-Tenant-ID: 123"
{"message":"Internal Server Error"}

REST API ✕ Lambdaプロキシ統合の場合

curl https://<API GWのID>.execute-api.us-east-1.amazonaws.com/dev?tenant-id=123 -H "X-Tenant-ID: 123"
{"message": "The invoked function is enabled with tenancy configuration. Add a valid tenant ID in your request and try again."}

ということでREST APIの統合リクエストを手動で追加編集し、リクエストヘッダのX-Tenant-IDをLambdaをInvokeする統合リクエストのX-Amz-Tenant-Idにマッピングしてみます。

メソッドリクエストにX-Tenant-IDを追加

統合リクエストでX-Tenant-IDをX-Amz-Tenant-Idにマッピング

curl https://<>API GWのID>.execute-api.us-east-1.amazonaws.com/dev -H "X-Tenant-ID: 123"

今度は無事に呼び出し成功しました!

{}

プログラミングモデル

テナント分離モードを有効化したLambdaではhandler起動時に渡されるコンテキストオブジェクトからテナントIDが取得可能です。テナントIDの取得方法はランタイムによって微妙に異なりますが、context.tenant_idcontext.tenantIdcontext.getTenantId();といった記述で取得できます。例えばPythonの場合は以下のようにLambdaのコードからテナントIDにアクセスできます。

def lambda_handler(event, context):

    print(context.tenant_id)
    ...

これでLambdaのコード側でテナントに応じた処理の分岐なども自由に実装できますね。

料金

テナント分離モードを利用する場合は通常のLambdaの利用料金に加えて、Lambda実行環境毎に以下の追加費用が発生します。

  • x86... $0.000167 per 1 GB environment
  • ARM... $0.000167 per 1 GB environment

コールドスタートが発生するたびに上記の追加料金が発生すると考えると分かりやすいでしょう。

コールドスタートへの影響はどうなる?

テナント毎にLambda実行環境が分離されるのはセキュリティ観点ではメリットですが、パフォーマンス等への影響も気になります。

同一のLambda FunctionにテナントAのリクエスト、テナントBのリクエスト、テナントCのリクエスト...と直列にリクエストが発生する場合を例に考えてみましょう。

従来はテナントB,Cのリクエストはwarm状態のLambda実行環境を使いまわせますが、テナント分離モードを有効化するとLambda実行環境が共有できないためテナント毎にコールドスタートが発生することになります。

ということで簡単なシェルスクリプトで20テナント分リクエストを発行して検証してみました。

#!/bin/bash

for i in {1..20}
do
  curl https://<API GWのエンドポイント>.execute-api.us-east-1.amazonaws.com/dev -H "X-Tenant-ID: $i"
  echo ""
done

Lambdaのコードは以下でリクエストされたテナントIDを返却するだけのものです。

import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': json.dumps({
            "tenant_id": context.tenant_id
        })
    }

シェルスクリプトを実行...

{"tenant_id": "1"}
{"tenant_id": "2"}
{"tenant_id": "3"}
{"tenant_id": "4"}
{"tenant_id": "5"}
{"tenant_id": "6"}
{"tenant_id": "7"}
{"tenant_id": "8"}
{"tenant_id": "9"}
{"tenant_id": "10"}
{"tenant_id": "11"}
{"tenant_id": "12"}
{"tenant_id": "13"}
{"tenant_id": "14"}
{"tenant_id": "15"}
{"tenant_id": "16"}
{"tenant_id": "17"}
{"tenant_id": "18"}
{"tenant_id": "19"}
{"tenant_id": "20"}

このあとCW Logsからplatform.initStartを含むログを検索すると20件のログがヒットし、テナント毎にコールドスタートが発生していることが分かります。

CW Logsに出力されたコールドスタートのログ

当たり前といえば当たり前ですが、この挙動は注意が必要ですね。

Single purpose LambdaよりLambdalithな構成の方がコールドスタートが発生しやすいのと類似のトレードオフと言えるでしょう。

まとめ

マルチテナントなSaaSアプリケーションを開発するようなユースケースにおいては本アップデートによってセキュリティ要件を満たしやすくなったのではないでしょうか?

セキュリティ観点で考えるとテナント毎にLambda実行環境が分離されるのはメリットですが、環境を共有できないことによってコールドスタートの発生率が上がるという観点ではデメリットもあるのでその点だけ注意して利用していきたいですね。

参考

この記事をシェアする

FacebookHatena blogX

関連記事