Skip to content
Published on

AWS Lambda MicroVMs — エージェントが書いたコードをVM分離で実行するということ、そしてスナップショットが生む新しい問題

シェア
Authors

はじめに — エージェントが書いたコードをどこで実行するか

LLMにコードを書かせるところまでは、もはや簡単な部類に入ります。難しいのはそのコードを実行する方です。モデルがたった今生成したコードは定義上レビューを経ておらず、プロンプトインジェクションが一度決まれば、ユーザーが意図したことのないコードになります。これをどこで動かすかは好みの問題ではなく、隔離境界をどこに引くかという問題です。

コンテナはこの用途にあまり向きません。理由はひとつだけです — カーネルを共有しているからです。namespaceやcgroup、seccompをどれだけ締め上げても、テナントAのコードとテナントBのコードは同じカーネルのシステムコールインターフェースを叩きます。そのインターフェースのどこか一箇所が壊れれば、境界はまるごと崩れます。だからこの問題を真剣に扱うところは、結局もっと下へ降りていきました — ハードウェア仮想化へ、あるいはユーザー空間カーネルへ。

AWSが2026年6月22日にLambda MicroVMsを出したのは、その文脈です。新しい隔離技術ではありません — Firecrackerは2018年から存在し、Lambda自体がその上で動いています。新しいのは売り方です。Firecrackerの隔離・スナップショット・ライフサイクルを直接扱う生の要素として取り出しつつ、ハイパーバイザーは依然としてAWSが運用します。

本稿は製品紹介ではなく、境界についての話です。この境界が正確に何を防ぎ、何を防がず、スナップショットという実装上の選択がどんな新しい問題を連れてくるのかを見ていきます。

Lambda MicroVMsとは実際には何か

AWS Computeブログ(2026年7月10日、Kulkarni・Agarwal・Madan)が説明するモデルはこうです。

  • MicroVMイメージ — DockerfileとコードをzipにまとめてS3に上げると、Lambdaがそのdockerfileを実行し、アプリケーションを起動し、完全に初期化された状態のFirecrackerスナップショットを撮ります。バージョンが付くアーティファクトです。
  • MicroVM — そのイメージからオンデマンドで起動する個々のインスタンス。セッションごと、ユーザーごと、ジョブごとに一つ割り当てられます。

APIはcreate-microvm-imagerun-microvmsuspend-microvmresume-microvmterminate-microvmdelete-microvm-imageと簡潔です。

aws lambda-microvms run-microvm \
  --image-identifier arn:aws:lambda:us-east-1:123456789012:microvm-image:analytics-notebook \
  --idle-policy '{"maxIdleDurationSeconds":300,"suspendedDurationSeconds":28800,"autoResumeEnabled":true}' \
  --maximum-duration-in-seconds 28800 \
  --region us-east-1

検証できる仕様だけを抜き出すとこうなります。出典は開発者ガイドのサイジング表です。

ベースライン            → ピーク(自動4倍垂直スケール)   最大ディスク
0.5 GB / 0.25 vCPU   → 2 GB / 1 vCPU            8 GB
1 GB   / 0.5 vCPU    → 4 GB / 2 vCPU            8 GB
2 GB   / 1 vCPU (デフォルト) → 8 GB / 4 vCPU           8 GB
4 GB   / 2 vCPU      → 16 GB / 8 vCPU           16 GB
8 GB   / 4 vCPU      → 32 GB / 16 vCPU          32 GB

ここでよくある誤解をひとつ整理しておきます。あちこちで引用される「32GB / 16vCPU」はベースラインではなく、最大のベースラインのピークです。メモリだけを設定すればvCPUは2GBあたり1個の比率でついてきて、ピークはベースラインの4倍まで自動的に上がります。AWSのニュースブログの表現は"up to 16 vCPUs, 32 GB of memory, and 32 GB of disk per MicroVM"で、これがその意味です。

残りの境界条件です。

  • ARM64専用。 x86はありません。
  • 5リージョン — バージニア北部、オハイオ、オレゴン、アイルランド、東京。
  • 最大8時間(28,800秒)。セッションの寿命であり、アイドルサスペンドの保持上限でもあります。
  • 各MicroVMは専用のHTTPSエンドポイントを受け取り、HTTP/1.1・HTTP/2・WebSocket・gRPC・SSEをサポートします。認証はcreate-microvm-auth-tokenで発行するJWEトークンをX-aws-proxy-authヘッダーに載せて送ります。トークンには許可ポートと有効期限が埋め込まれます。

VM境界だからこそ可能になることがひとつあり、これは正真正銘の利点です。additionalOsCapabilities["ALL"]に設定すると、ファイルシステムのマウント、ネットワーク名前空間の作成、eBPFの実行といったことが開放されます。ドキュメントの一文は的確です — "Capabilities are applied within the VM isolation boundary and do not affect the host or other MicroVMs."。サンドボックス内に事実上のrootを与えてもホストが安全なのは、その下にハイパーバイザーがあるからです。コンテナではこの取引はできません。

速い起動の正体 — 起動せずスナップショットから復帰する

「near-instant startup」の正体は、起動しないことです。Lambda SnapStartで使われていた手法そのままです — Firecrackerスナップショットから再開します。

イメージビルド時にLambdaが行うことは順番にこうです。ベースイメージから新しいMicroVMを起動し、Dockerfileを実行し、ENTRYPOINT/CMDでアプリを起動し、初期化完了をライフサイクルフックで確認したのち、ディスクとメモリの状態のスナップショットを撮ります。フックは2つです。

/ready    → /aws/lambda-microvms/runtime/v1/ready
            アプリがスナップショットを撮っても良い状態かどうか。503なら再試行、200ならスナップショット。
/validate → /aws/lambda-microvms/runtime/v1/validate
            ビルド後、そのイメージから起動した新しいMicroVMで再開が正常に動作するか確認。

/validateフックにはドキュメントに書かれた隠れた用途があります — ここでモックのペイロードを流すと、Lambdaはスナップショットのどの領域が実際にアクセスされるかを追跡し、起動時にその領域の読み出しを最適化します。スナップショット復元は結局のところメモリページを遅延読み込みする作業であり、どのページが「熱い」かを事前に知らせておくと速くなる、という話です。

スナップショットが含むものはドキュメントに明記されています — 実行中のすべてのプロセスのメモリ状態(バックグラウンドデーモン、cron、子プロセスを含む)、ディスク状態、そして初期化済みのネットワーク接続とファイルディスクリプタです。

最後の項目をもう一度読んでください。ここから先が本稿の本題です。

スナップショットの代償 — 一意であるべきものが一意でない

Lambda MicroVMsのモデルは「一つのイメージ → N個のMicroVM」です。つまり一つのスナップショットから数百のVMが繰り返し再開されます。これが速い理由であり、問題である理由でもあります。

Firecracker自身のドキュメントがこのパターンを何と呼んでいるか、そのまま引用します。

When snapshots are used in a such a manner that a given guest's state is resumed from more than once, guest information assumed to be unique may in fact not be; this information can include identifiers, random numbers and random number seeds, the guest OS entropy pool, as well as cryptographic tokens. Without a strong mechanism that enables users to guarantee that unique things stay unique across snapshot restores, we consider resuming execution from the same state more than once insecure.

同じ状態から二回以上再開することを「insecure」だと明言しています。そしてFirecrackerのドキュメントが例に挙げる「potentially insecure use」の形 — 一つのスナップショットSからmicroVM BとCをそれぞれ再開すること — は、Lambda MicroVMsの正常動作そのものです。

AWSもこれを隠していません。スナップショットのドキュメントの一文です。

If your code generates unique content during image version build phase (unique IDs, secrets, or entropy for pseudorandomness), that content is shared across all MicroVMs run from the same image version.

具体的にどこで問題になるか見ていきます。

環境変数。 ドキュメントによれば、環境変数はイメージビルド時点に設定され(最大50個)、スナップショット構築の過程でコンテナに注入されます。つまり環境変数に入れた秘密情報は、そのイメージから起動するすべてのテナントのMicroVMで共有されます。コンテナの習慣どおりAPIキーをenvに差し込むと、マルチテナントサンドボックス全体が同じキーを見ることになります。ランタイムに注入するにはrun-microvmの動的ペイロードを使う必要があります。

乱数と暗号トークン。 ビルド時点で作られたセッションID、シード、トークンはすべて複製されます。AWSの処方箋は「ビルド時ではなくMicroVM起動後に生成すること」で、再設定用に/runライフサイクルフックを提供しています。

OpenSSL。 これが最も具体的な落とし穴です。ドキュメントはAWS提供のベースコンテナイメージpublic.ecr.aws/lambda/microvms:al2023-minimalを使うよう指示しています。理由は、その中に"AWS-patched version of OpenSSL that is compatible with snapshotting"が入っているからです。自前のベースイメージを使うなら、Amazon Linux 2023のopenssl-snapsafe-libsパッケージを自分で入れる必要があります。

なぜOpenSSLだけが特別扱いされるのでしょうか。次の節がその答えです。

VMGenIDが直すものと直さないもの

カーネル側には解決策があります。VMGenIDは、ゲストが「自分はたった今スナップショットから蘇った」と検知できるようにする仮想デバイスです。16バイトのランダムな識別子をゲストに公開し、スナップショット再開のたびにハイパーバイザーがその値を変えます。Firecrackerはこのデバイスを常に有効化しており、再開時に新しい16バイトの値を書き込んだのち、vCPUを再開する前にゲストへ割り込みを入れます。Linuxは5.18から(ACPI経由、DeviceTreeは6.10から)、この値の変化を検知してカーネル内部のCSPRNGを再シードします。

だからAWSが案内する言語ごとのCSPRNG — Java 11+のSecureRandom、Node.jsのcrypto.randomBytes、Python 3.12+のSecrets.SystemRandom、.NET 8+のCryptography.RandomNumberGenerator — は安全です。共通しているのは、すべて/dev/randomまたは/dev/urandomを通じてカーネルからエントロピーを受け取っている点です。カーネルが再シードされるので、これらも変わります。

問題はカーネルを経由しないものです。Firecrackerのドキュメントの一文をそのまま引きます。

State other than the guest kernel entropy pool, such as unique identifiers, cached random numbers, cryptographic tokens, etc will still be replicated across multiple microVMs resumed from the same snapshot. Users need to implement mechanisms for ensuring de-duplication of such state, where needed.

willに強調が付いているのは原文のままです。VMGenIDが直すのはカーネルのエントロピープールだけです。ユーザー空間が自分のエントロピープールを別に持っていると — OpenSSLがまさにそうです — それは複製されたまま残ります。だからopenssl-snapsafe-libsという別パッケージが存在し、だからAWSがベースイメージを使うよう勧めているのです。

Firecrackerのエントロピー関連のドキュメントは、この限界についてさらに率直に認めています — ユーザー空間のライブラリがそれぞれ独自のエントロピープールを持つ問題について、「現在のプログラミングモデルには一般的な解法はなく、我々にできるのはスナップショット以前のロジックでそれらを使わないよう推奨することだけだ」と書かれています。

ユーザー空間まで通知する標準化作業は進行中です。VMClockデバイスのvm_generation_counterをユーザー空間がmmap()で監視するかpoll()で通知を受け取れるようになっており、この対応はAmazonのエンジニア(itazur@amazon.com)が2026年1月30日に送ったパッチによってLinuxカーネルv7.0にマージされました。Amazon Linuxのmicrovmカーネル5.10系と6.1系にはバックポートされています。ただしこれは「ライブラリがこのデバイスを監視するよう修正されている」場合にしか値を持ちません。今この瞬間にあなたが使っているライブラリがそうなっている可能性は低いでしょう。

まとめると、スナップショット再開時の一意性に関する責任分担はこうなります。

カーネルエントロピープール         → VMGenIDが自動再シード (Linux 5.18+)          [解決済み]
/dev/urandomを使うCSPRNG          → カーネルを経由するので自動的に安全          [解決済み]
OpenSSLなど独自のエントロピープール → パッチ済みビルドが必要 (openssl-snapsafe-libs) [部分的に解決]
アプリが作るID・トークン・シード    → 誰も直してくれない。/runフックで自分で再生成 [自分の責任]
ビルド時点の環境変数              → スナップショットにそのまま焼き付く。ランタイム注入で回避 [自分の責任]

最後の2行が本稿でもっとも重要な部分です。VM隔離境界はこの問題に対して何もしてくれません。テナント間のカーネル脱出を防ぐことと、テナントたちが同じシードを見ることは、まったく別の層の問題です。

VM境界が防がないもの

スナップショットの問題をすべて解決したとしましょう。それでもVM境界が防がないものが残っており、実務ではこちらの方が事故を起こす頻度が高いのです。

デフォルトはインターネットに開いています。 ネットワーキングのドキュメントの一文そのままです — "By default, Lambda MicroVMs have public internet access on the egress path."。プロンプトインジェクションを受けたエージェントがサンドボックス内で認証情報やユーザーデータを読み、curlで外部へ送信するシナリオを考えてみてください。VM境界はこれをまったく防ぎません。ハイパーバイザーの立場から見れば、それはゲストが普通に行うネットワークI/Oでしかないのです。エグレスを制御するには、Lambda Network Connectorでトラフィックを自分のVPCへ回し、セキュリティグループとNACLを通す必要があります。つまり本当の防衛線はハイパーバイザーではなく、あなたが書くネットワークポリシーです。

これはAWSだけの話ではありません。Anthropicの自己ホスト型サンドボックスのセキュリティドキュメントは、同じ境界をもっと率直に書いています — "Without egress restrictions, a compromised tool execution can reach arbitrary external hosts."。そして「Anthropicが代わりにやってくれないこと」のリストにはこうあります — "Isolate tools inside your sandbox. Anthropic's security boundary stops at the sandbox."。ちなみにAWS Computeブログは、Lambda MicroVMsをClaude Managed Agentsの自己ホスト型サンドボックスプロバイダーとして使うパターンを明示的に紹介しています — エージェントループはAnthropic側に、ツール実行はあなたのMicroVMに置く構成です。

IAMは依然としてあなたの仕事です。 Computeブログが指摘する良いディテールがひとつあります。ビルド時のIAMロールと実行時のIAMロールを分離できるという点です。テナントごとに権限を細かく与えるにはこれを使う必要があります。実行ロールが過剰な権限を持っていれば、VM隔離は何の役にも立ちません。

プロンプトインジェクションは隔離の問題ではありません。 モデルが騙されて「許可された作業」を行うことを、ハイパーバイザーが察知する方法はありません。VM境界はブラスト半径を縮める道具であって、エージェントが判断を誤ることを止める道具ではないのです。

数字についての正直な話

起動遅延の数字はAWSが出していません。 Computeブログ、ニュースブログ、開発者ガイドをすべて調べても、「near-instant startup」「resume within seconds」「starts within seconds」といった表現しか出てきません。ミリ秒単位の数値はどこにもありません。なので、ここで数字をでっち上げることはしません — これはあなた自身のイメージサイズとワーキングセットで実測すべき値です。スナップショット復元がページの読み出しに比例することを考えれば、数ギガバイトのワーキングセットと200MBのイメージの再開時間が同じであるはずがありません。

Firecrackerの規模の数字はベンダー自身の主張です。 "15 trillion+ monthly invocations"(開発者ガイド)、"tens of trillions of requests each month for over 1.5 million customers"(Computeブログ)は、いずれもAWSが自社サービスについて語る数値であり、測定条件は公開されていません。Firecrackerが大規模に実証されているという定性的な根拠としては十分ですが、それ以上に読み取れる資料ではありません。

コストは計算できます。 Lambdaの料金ページによるus-east-1のARM基準の公開料率はこうです。

vCPU                     $0.0000276944 / vCPU-second
メモリ                   $0.0000036667 / GB-second
スナップショット書き込み $0.0038  / GB  (サスペンド)
スナップショット読み込み $0.00155 / GB  (起動・再開)
スナップショット保管     $0.08    / GB-month

デフォルトのベースライン(2GB / 1vCPU)を稼働させ続けると、秒あたり0.0000350278ドルです。時間あたり約$0.126、1日で約$3.03、30日で約$91。これはベースラインだけを計算した床値であり、ベースライン超過分やスナップショット・データ転送は別途かかります。ちなみにInfoQの報道で引用されている実務者の推定値も1日$3.03と同じ値でした — 公開料率から独立に導いた値が一致しているので、この数字は信頼してよいでしょう。同じ記事は、これがFargate Spotの9倍を超えるという指摘も引用しています。

ここから設計上の含意が出てきます。この料金モデルでは、アイドル状態のMicroVMをつけっぱなしにするのはただの出費です。サスペンドが選択肢ではなく必須である理由であり、idle-policyがAPIの第一級市民である理由です。サスペンドすればコンピュート課金は止まり、ストレージ料率だけが残ります。逆に、強化学習環境のように短命なVMを大量に回すワークロードなら、起動のたびにスナップショット読み込み料金がかかることをモデルに織り込む必要があります。

運用負担も数字でやってきます。 ベースイメージには廃止サイクルがあります — DEPRECATED(60日) → EXPIRING(30日、新規イメージ作成不可) → EXPIRED(ビルドも実行も不可)。つまりイメージを作って放置すれば、いつか起動しなくなります。再ビルドは定期作業です。

代替策 — gVisor側はどうしているか

同じ問題を別の境界で解いている側も見ておくのが公平です。Googleは2026年5月21日にGKE Agent Sandboxを出しました。ハードウェア仮想化の代わりにgVisor — システムコールをユーザー空間で横取りするカーネル — を使い、デフォルト拒否のKubernetesネットワークポリシーを併せて掛けます。Kata Containersのような他のサンドボックスを差し込めるインターフェースもあり、Kubernetes SIG傘下のオープンソースプロジェクトです。

Googleが主張する数値は「クラスタあたり秒間300サンドボックス割り当て、サブ秒レイテンシ、割り当ての90%が200ミリ秒以内に完了」です。ベンダー自己測定であり、クラスタ構成といった条件はブログに明記されていません。「Axionで他のハイパースケーラー比最大30%優れた価格性能比」も同様にGoogle自身の比較です。

境界の性質の違いははっきりさせておく価値があります。gVisorはシステムコールをユーザー空間で再実装し、ホストカーネルに触れる面を減らします。薄くて速い一方で、結局はソフトウェアがカーネルインターフェースを模倣しているだけなので、そのソフトウェア自体が攻撃対象になります。FirecrackerはKVM上の本物のVMなのでゲストは自分のカーネルを持ちますが、その分重く — そして本稿の半分を占めたスナップショット問題を連れてきます。どちらが「より安全」かは、条件抜きには言えません。確かなのは、デフォルト拒否のエグレスはどちらの陣営でも別途対処が必要だということだけです。

いつ使うべきでないか

使わないでください、もし

  • 実行するコードがあなた自身のコードであるなら。信頼境界がないのに、テナントごとのVM価格を払う理由がありません。1日$3の床値と8時間の上限を受け入れる根拠になりません。
  • ワークロードがステートレスで短命であるなら。スナップショットのライフサイクル・一意性処理・サスペンドポリシーは、すべて状態を保存するための複雑さです。それを使わないなら、素直にLambda関数が正解です。
  • x86が必要であるなら。ARM64専用です。
  • 5リージョンの外が必要であるなら。
  • セッションが8時間を超える必要があるなら。これは上限であり、迂回路はありません。
  • エグレスを閉じられないなら。開いたインターネットのデフォルトの上で信頼できないコードを動かすのは、VM隔離を買っておきながら肝心のドアを開けっぱなしにしているのと同じです。これは「とにかく使うな」というより、「これをやらないならVM隔離にお金を払う理由がない」に近い話です。

値打ちがある場合はその逆にはっきりしています — ユーザーやエージェントが作ったコードをテナントごとに隔離して実行する必要があり、セッションが長く状態を持ちアイドル区間があり、サンドボックス内に高いOS権限を与える必要があり(スキャナーのように)、それでいてFirecrackerのインフラを自分で運用するつもりはない場合。この組み合わせがまさにAWSが狙っている場所であり、実際にその場所にはよく合っています。

おわりに

Lambda MicroVMsは良い製品です。ただし、売っているものと買っているものを混同してはいけません。売っているのはハイパーバイザー運用のアウトソーシングです — Firecrackerの隔離とスナップショットを自分で回さず、APIとして使うこと。買っているのは強いテナント間カーネル境界であり、その境界は実在し、コンテナでは買えません。

買えないものもはっきりしています。スナップショットから蘇ったVMたちが同じ秘密情報と同じシードを見ないようにする仕事は、依然としてあなたの担当です。VMGenIDが直すのはカーネルエントロピープールまでで、その上の層は「複製される」とFirecrackerのドキュメント自身が明記しています。エグレスもあなたの担当です — デフォルトが開いたインターネットだからです。IAMも、プロンプトインジェクションも同様です。

だからこの製品の本当の教訓は、隔離技術そのものよりもその下にあります。速さのために下した実装上の選択が、新しい信頼の前提を作るということです。起動を飛ばすためにスナップショットを使った瞬間、「すべてのプロセスは固有の状態で始まる」という40年来の前提が静かに崩れます。ハイパーバイザーはその事実を知りません。それを知っているのは、ドキュメントを最後まで読んだあなただけです。

参考資料