GA直後のAWS Lambda MicroVMsをGoで試す — suspendしてもカウンタを覚えているサーバレス

2026年6月、AWSがLambda MicroVMsをGAさせた。Lambdaの基盤であるFirecrackerをそのまま開発者に開放するようなサービスで、「VMレベルの隔離」「スナップショットからの高速起動」「suspend/resumeでメモリ・ディスク状態を保持」という、従来のステートレスなLambdaとはまるで性格の違う代物だ。東京リージョンが初期対応に入っていたので、GAから3週間足らずだが一通り触ってみた。

結論から書くと、起動2.5秒、suspend中に叩いても985msで自動復帰し、メモリ上のカウンタはちゃんと生き残っていた。本稿はそこに至るまでの構成判断とデバッグの記録である。

Lambda MicroVMsとは何か

仕組みはこうだ。アプリケーションコードとDockerfileをzipにしてS3に置き、create-microvm-image を呼ぶと、AWSがDockerfileを実行してアプリを起動した状態のFirecrackerスナップショットを取る。以後 run-microvm するたびに、そのスナップショットから復元されたMicroVMが数秒で立ち上がる。コールドブートではなく「初期化済みプロセスの復元」である点が肝だ。

  • ARM64のみ。最大16 vCPU / 32GBメモリ / 32GBディスク、総実行時間8時間
  • MicroVMごとに専用HTTPSエンドポイントが発行され、HTTP/2・gRPC・WebSocketに対応
  • アイドル時はsuspendしてコンピュート課金が止まる(ストレージのみ)。着信で自動resume
  • 想定用途はAIコード実行サンドボックス、ユーザーごとの開発環境、マルチテナントCI/CDなど

検証の設計

作ったのは「豪奢なHello, World」だ。ただの fmt.Println では検証にならないので、Goの標準ライブラリだけで小さなHTTPサーバを書き、金色のシマーアニメーション付きHTMLページと、いくつかのAPIを持たせた。

要となるのは /api/count である。呼ばれるたびにインメモリのカウンタを+1して返すだけのエンドポイントだが、これがsuspend/resume後も値が続けばメモリ状態保持の証明になるという証人役だ。

もうひとつの作法として、起動時に外部コネクションを張らない設計にした。スナップショットはアプリ初期化後に取られるため、初期化時に張ったコネクションや時刻依存の状態は復元後に腐る。先人の報告に従い、ゲストは接続レス・無状態初期化とした。

構成 — TerraformとSDKの分担、そしてトークン問題

全体構成は次のとおり。

構成図

構成を決める上でポイントが2つあった。

その1: TerraformはMicroVMを知らない。 terraform-provider-awsはまだLambda MicroVMsに対応していない(issue #48526)。そこで役割を割り切った。Terraformは変化しない土台(S3バケット、IAMロール、API Gateway、プロキシLambda)だけを持ち、MicroVMのライフサイクル(イメージ作成〜起動〜suspend〜破棄)はGo SDK(aws-sdk-go-v2/service/lambdamicrovms v1.0)で書いたドライバが受け持つ。

その2: 認証トークンは最長60分しか生きない。 MicroVMの専用エンドポイントは、毎リクエストに X-aws-proxy-auth ヘッダでJWEトークンを要求する。トークンは create-microvm-auth-token で発行するのだが、有効期限の上限が60分。つまりAPI Gatewayの静的なヘッダ注入では毎時死ぬ。そこで間に小さなプロキシLambdaを挟み、トークンを発行・キャッシュしてリクエストに付け替える構成にした。転送先のMicroVM IDとエンドポイントはSSM Parameter Store経由で渡すので、MicroVMを作り直してもドライバがSSMを書き換えるだけで済み、プロキシの再デプロイは不要だ。

ちなみにMicroVMイメージ用のDockerfileは3行しかない。

FROM scratch
COPY guest /guest
CMD ["/guest"]

GoをARM64静的ビルドしてzipに同梱するので、FROM scratch で外部レジストリへの依存がゼロになる。OS層は --base-image-arn(AWS管理のAL2023ベースイメージ)が別途提供するので、コンテナ側は本当にバイナリだけでいい。イメージビルドは約2分44秒だった。

ハマったところ(デバッグ記録)

GA直後のサービスをSDKで叩くと、ドキュメントの行間で転ぶ。4つ記録しておく。

1. GetMicrovmImage は名前を受け付けない。 CLIの例では --image-identifier my-image-name と名前で通るように見えるが、SDKで名前を渡すと ValidationException: Invalid ARN format: gorgeous-hello で弾かれた。ARNを組み立てて渡す必要がある。

2. 同名イメージの再作成はConflictExceptionではない。 エラーハンドリングで Conflict を待ち構えていたら、実際に飛んできたのは ValidationException に “already exists” のメッセージだった。エラーコードではなくメッセージで判定する羽目になった。

3. トークンAPIの戻り値は文字列ではなくmap。 CreateMicrovmAuthToken のレスポンスの AuthToken フィールドは map[string]string で、キー X-aws-proxy-auth の値を取り出して使う。ヘッダ名ごと返してくる設計は珍しい。

4. IAMアクションのプレフィックスは lambda-microvms: ではなく lambda: CLIのコマンド名前空間は aws lambda-microvms なのに、IAMポリシーに書くアクションは lambda:CreateMicrovmAuthToken だ。サービスモデルの署名名がlambdaのままだからで、ここを間違えるとプロキシがAccessDeniedで沈黙する。

実測値

東京リージョン(ap-northeast-1)での実測。

項目 実測
イメージビルド(zip 6MB、FROM scratch) 約2分44秒
RunMicrovm → RUNNING 2.5秒
初回リクエスト(復元直後) 838ms
ウォーム時(エンドポイント直叩き) 56ms
suspend完了 3.3秒
suspend中に着信 → 自動resume → 応答 985ms

本題: suspendしてもカウンタは生きているか

検証のクライマックスである。手順はこうだ。

  1. API Gateway経由で /api/count を叩き、カウンタを5まで進める
  2. SDKから SuspendMicrovm を呼ぶ。3.3秒でSUSPENDEDになったことをAPIで確認
  3. suspend中のMicroVMに向けて、API Gateway経由で /api/count を叩く

結果、985msで {"counter":6} が返ってきた。リクエストが着信した瞬間に自動でresumeされ(idle policyの autoResumeEnabled)、メモリ上のカウンタは5を覚えたまま6を返した。状態確認するとRUNNINGに戻っている。プロセスからみれば、時間が止まって再開しただけだ。

もうひとつ面白い観察があった。ゲストが自己申告する boot_time が、MicroVMの起動時刻よりを指していたのだ。値はイメージビルドの実行時刻。つまりプロセスはイメージビルド時に一度だけ起動し、以後のMicroVMはすべて「起動済みの状態」から復元されている。RunMicrovm→RUNNINGが2.5秒で済む理由がこの数字に表れている。

コストの後始末

MicroVMは起動している間vCPU秒+メモリGB秒で課金される。検証の放置事故を防ぐため、二重の保険をかけた。idle policyで「10分無通信でsuspend、suspend 4時間で自動terminate」、さらに MaximumDurationInSeconds で最長4時間の強制終了。恒久リソース(API Gateway+Lambda+SSM+S3+IAM)は実質ゼロ円なので、消し忘れても財布は痛まない。

まとめ

  • Lambda MicroVMsは「状態を持てるサーバレス」という新しいプリミティブだ。起動2.5秒・resume 1秒弱・suspend中はストレージ課金のみ、という数字は実用の域にある
  • Terraformは未対応なので、土台をTerraform・ライフサイクルをSDKドライバと割り切る構成が現時点の正解
  • 認証トークン上限60分の制約は、トークンを付け替えるプロキシLambdaで吸収できる
  • GA直後のSDKには行間が多い。ARN必須、mapで返るトークン、lambda:プレフィックス——この手の罠はログが全部教えてくれる

次はWebSocket/gRPCの疎通を試す予定だ。検証リポジトリは追って公開する。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール