AWS Lambda(以下、Lambda)のコンピューティングタイプとして Amazon EC2 (以下、EC2) が選択可能になり、新たに「Lambda Managed Instances」が登場しました!
Lambda を EC2 で動かせるようになったことで、OS やランタイム言語のパッチ適用や負荷分散などを管理することなく、また EC2 Savings Plans やリザーブドインスタンスなどを適用して運用することができるようになりました。

公式ブログでは東京リージョンでも利用できるとありますが、執筆時点ではまだ表示されないため米国東部 (バージニア北部) リージョンで検証しています。

作成してみる

コンピューティングタイプにEC2を選択するには、キャパシティプロバイダー (Lambdaがバックグラウンドで管理するEC2インスタンスの定義) を先に作成しておく必要があります。

サイドバーから「キャパシティプロバイダー」を選択します。

VPCやサブネット、セキュリティグループを選択します。
設定後は変更できないため、変更したい場合は再作成になります。

また、Lambda Managed Instances は VPC 内で動作するため、CloudWatch Logs へログを送信するには VPC エンドポイント(Interface Endpoint)を設置して経路を確保する必要があります。

EC2 の操作を許可するポリシーをLambdaに付与する必要があるため、IAMポリシーを作成します。執筆時点ではキャパシティプロバイダー作成画面からロールは作成されないようなので、AWS IAM のコンソールに移り、作成します。
ポリシーはドキュメント通り、マネージドポリシーである AWSLambdaManagedEC2ResourceOperator を設定し、IAMロールを作成します。信頼ポリシーもlambda.amazonaws.comが設定されているか確認します。

参考として、AWSLambdaManagedEC2ResourceOperatorに含まれる権限定義(JSON)は以下の通りです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:RunInstances",
                "ec2:CreateTags",
                "ec2:AttachNetworkInterface"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:instance/*",
                "arn:aws:ec2:*:*:network-interface/*",
                "arn:aws:ec2:*:*:volume/*"
            ],
            "Condition": {
                "StringEquals": {
                    "ec2:ManagedResourceOperator": "scaler.lambda.amazonaws.com"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeAvailabilityZones",
                "ec2:DescribeCapacityReservations",
                "ec2:DescribeInstances",
                "ec2:DescribeInstanceStatus",
                "ec2:DescribeInstanceTypeOfferings",
                "ec2:DescribeInstanceTypes",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeSubnets"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:RunInstances",
                "ec2:CreateNetworkInterface"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:subnet/*",
                "arn:aws:ec2:*:*:security-group/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:RunInstances"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:image/*"
            ],
            "Condition": {
                "StringEquals": {
                    "ec2:Owner": "amazon"
                }
            }
        }
    ]
}

ここまでは必須の設定ですが、アーキテクチャや自動スケーリングの最大インスタンス数なども設定できます。


作成が完了したら、Lambda関数を作成します。

通常のLambda関数作成時と同じように、ランタイムやアーキテクチャを設定します。

ここでキャパシティプロバイダーで設定したアーキテクチャ以外を選択すると、作成時に以下のエラーが発生します。
You cannot use a Lambda Managed Instances function with a capacity provider that does not support the architecture of the function

他にもメモリサイズや 1vCPU あたりに割り当てられるメモリ容量の設定などが行えます。


これで作成完了です。

実装する時の注意点

グローバル変数に注意

Each execution environment can process multiple requests rather than handling just one request at a time. This can significantly reduce compute consumption, because your code can efficiently share resources across concurrent requests instead of spinning up separate execution environments for each invocation.

ニュースに記述がある通り、1つの実行環境(プロセス)の中で複数のリクエストが並行する可能性があるため、グローバル変数での用途には注意が必要です。

import json

# 処理中で更新するグローバル変数を定義
global_var = {} 

def lambda_handler(event, context):
    global global_var

    session_id = event.get('session_id')

    # ここでglobal_varが書き換わり競合が発生する
    global_var = {"session": session_id, "status": "processing"}

    # 時間がかかる処理があると仮定
    do_heavy_process()

    return {
        'statusCode': 200,
        'body': json.dumps(global_var)
    }

メモリ設定

Pythonアプリケーションの場合は「Execution environment memory (GiB) per vCPU ratio」を「4:1」か「8:1」に設定することがベストプラクティスとして定義されています。

For Python applications, choose a higher ratio of memory to vCPUs (such as 4 to 1 or 8 to 1) because of the way Python handles multi-concurrency

またWebアプリケーションやAPI呼び出しなどIO重視のアプリケーションでは、同時実行数(Concurrency)を高く設定することで、複数の同時実行されたリクエストを効率よく処理できるようになります。

まとめ

Lambda Managed Instances の登場により、サーバーレスの利便性と EC2 の柔軟性が統合されました。
RI (Reserved Instances) や Savings Plans を活用したコスト最適化や、従来の Lambda だけでは対応が難しかったセキュリティ要件など、新たな選択肢として活躍しそうです。
まだ登場したばかりの機能ですので、今後のアップデートやユースケースの広がりに期待です!

参考