114. LambdaとECSタスクはENIという足でVPCに立つ — Hyperplane ENIの共有とawsvpcの専用ENI
「サーバーレスやコンテナはどうやってVPCに現れるのか」を、Lambdaの共有ENIとECSの専用ENIという2つの足の作り方で図で追っていきます。どちらも部品はENIひとつで、本編で組み上げたSG・ルートテーブル・NAT・DNSがそのまま全部効きます。
① 出発点 — Lambdaは最初から「見えないVPC」の中に居る
- 公式の言い回し:「Every Lambda function runs inside a VPC that is owned and managed by the Lambda service.」— この管理VPCは顧客には見えない
- 公式は続けて明言:「Configuring your function to access other AWS resources in an Amazon VPC has no effect on the Lambda-managed VPC your function runs inside.」— VPC接続を設定しても、関数の実体はLambda側に居たまま。顧客VPCのサブネット+SGの指定に応じてHyperplane ENIが作られ、そこが通用口になる
VPC接続とは関数を顧客VPCへ引っ越す操作ではありません。関数は元からLambda管理VPCで動いており、顧客VPCのサブネットにHyperplane ENIという管理された足を1本立てて、そこを通用口にするだけです。(根拠: lambda/configuration-vpc.html の冒頭Note と「Understanding Hyperplane ENIs」節)
② 核心 — Hyperplane ENIは「サブネット×SGの組」ごとに1つ、アカウント内で共有
- 公式:「The first time you attach a function to a VPC using a particular subnet and security group combination, Lambda creates a Hyperplane ENI. Other functions in your account that use the same subnet and security group combination can also use this ENI.」
- 公式:「Wherever possible, Lambda reuses existing ENIs to optimize resource utilization and minimize the creation of new ENIs.」— 実行環境ごとでも関数ごとでもない。組み合わせごと・アカウント内共有が肝
- キャッシュ編の遅延読み込みと同じ償却の設計: ENI作成という物理コストを初回一度きりに畳み込み、以後は再利用する
ENIは関数ごとでも実行環境ごとでもなく、サブネットとセキュリティグループの組み合わせごとに1つだけ作られ、同じ組を使うアカウント内の他の関数と共有されます。実行環境が何千に増えても足の数はそれに比例しません。これはキャッシュ編で見た「初回だけ高く以後は再利用」の償却そのものです。かつてVPC接続のLambdaが遅いと言われた背景にENI作成の重さがあったことは、公式が今もENI作成に数分かかり得ると書いていることからも裏づけられます。(根拠: 同ページ Performance best practices 節 と Hyperplane ENIs 節)
③ 1本の足で足りる理由と、足りなくなったとき — 65,000接続と自動増設
- 公式:「Each Hyperplane ENI supports up to 65,000 connections/ports. If the number of connections exceeds this limit, Lambda scales the number of ENIs automatically based on network traffic and concurrency requirements.」
- API Gateway編/メッセージング編で見た「多対1の集約」と同じ構造 — 有限だが十分広い資源を多数で共有する
1枚のENIは最大65,000接続まで捌けます。NATが多対1でポート空間を共有したのと同じ発想で、多数の実行環境がこの1本を共有し、上限に近づくとLambdaが足を自動で増やします。共有は「安かろう悪かろう」ではなく、十分広い資源を賢く畳み込む設計です。(根拠: 同ページ Hyperplane ENIs 節)
④ 足は永続しない — Pending → Active → Inactive のライフサイクル
- 公式:「For new functions, while Lambda is creating a Hyperplane ENI, your function remains in the Pending state and you can't invoke it. Your function transitions to the Active state only when the Hyperplane ENI is ready, which can take several minutes.」— Pendingで呼び出せないのは新規関数の話。既存関数のVPC設定変更中は、バージョン作成やコード更新などの操作はできないが、以前のバージョンの呼び出しは継続できる
- 公式:「if a Lambda function remains idle for 14 days, Lambda reclaims any unused Hyperplane ENIs and sets the function state to Inactive. The next invocation attempt will fail, and the function re-enters the Pending state ... We recommend that your design doesn't rely on the persistence of ENIs.」
- Lambdaは負荷分散やENIヘルスチェックへの対処のため、ENIを削除・再作成することがある(これも公式明記)
初回の工事コストは残ります。新規関数はENI作成が終わるまでPendingで呼び出せず、数分かかることがあります。しかも足は永続前提ではなく、14日アイドルで未使用ENIが回収されてInactiveになり、次の呼び出しは一度失敗してPendingに戻ります。公式が明言する通り「ENIの永続性に依存するな」が設計原則です。(根拠: 同ページ Hyperplane ENIs 節)
⑤ ハマりどころ — VPC接続した関数はパブリックサブネットでも外に出られない
- 公式:「Connecting a function to a public subnet doesn't give it internet access or a public IP address.」
- 外向き通信の公式手順: 関数はプライベートサブネットに置き、そのルートテーブルで 0.0.0.0/0 をNATゲートウェイへ向ける。IPv6(デュアルスタックサブネット)の場合は ::/0 をegress-only internet gatewayへ向ける
- 参考: VPC接続しないデフォルトのLambdaは、Lambda管理VPC経由で最初からインターネットに出られる — 出られなくなるのはVPC接続したときだけ
VPC接続した関数はパブリックサブネットに置いてもインターネットには出られません。パブリックIPが付かないからです。外に出したいならプライベートサブネットに置いてNATゲートウェイを用意する — 本編で組んだNATの出番がここで回収されます。(根拠: 同ページ Attaching 節のNote、および lambda/configuration-vpc-internet.html)
⑥ もう一方の足 — ECSのawsvpcモードは「タスクごとの専用ENI」
- 公式:「the same networking properties as Amazon EC2 instances」「Each task can only have one ENI.」内部DNSホスト名は enableDnsHostnames + enableDnsSupport が有効なVPCで付与
- 公式: awsvpcのサービスが使えるロードバランサーはALBとNLBのみで、ターゲットグループは「must choose ip as the target type. Do not use instance.」— タスクはENIに紐づきインスタンスには紐づかないため
- Lambdaの「組み合わせごとに共有される足」と対照的に、ECSは「タスクごとの専用の足」
ECSのawsvpcモードは真逆の設計です。タスクごとに専用ENIが割り当てられ、タスクはEC2インスタンスと同じネットワーク属性(プライベートIP・内部DNSホスト名)を持ちます。だからSGをタスク単位で付けられ、フローログにタスク単位で通信が現れ、ロードバランサーのターゲットはinstanceではなくipになります。(根拠: AmazonECS/task-networking-awsvpc.html 冒頭と Linux considerations)
⑦ 専用ENIの実装 — pauseコンテナと名前空間の相乗り
- 公式:「the Amazon ECS container agent creates an additional pause container for each task before starting the containers in the task definition. It then configures the network namespace of the pause container by running the amazon-ecs-cni-plugins CNI plugins. The agent then starts the rest of the containers in the task so that they share the network stack of the pause container.」
- 結果:「all containers in a task are addressable by the IP addresses of the ENI, and they can communicate with each other over the localhost interface.」
- コンテナ編で見たLinux namespaces(ネットワーク名前空間)の実戦投入 — 「1つの名前空間を複数プロセスで共有する」がそのままタスク内通信の実装になっている
タスク内の全コンテナが同じIPを持ち、localhostで会話できるのは、まずpauseコンテナを起動してCNIプラグインでそのネットワーク名前空間を作り、残りのコンテナをそのネットワークスタックに相乗りさせるからです。コンテナ編のnamespacesが、ここで「1つの足を複数コンテナで共有する」実装として回収されます。(根拠: 同ページ Linux considerations の pause/CNI 項)
⑧ 専用ゆえの制約 — ENIの枚数がタスク密度の上限になる
- 公式:「by default, a c5.large instance might have only up to three ENIs that can be attached to it. The primary network interface for the instance counts as one. You can attach an additional two ENIs ... you can typically only run two such tasks on this instance type.」
- 公式:「When you need increased ENI density, use the awsvpcTrunking account setting. Amazon ECS also creates and attaches a "trunk" network interface」— コンテナエージェント 1.28.1 以上が必要
- 公式(EC2起動タイプ):「your task ENIs aren't given public IP addresses. To access the internet, tasks must be launched in a private subnet that's configured to use a NAT gateway.」「Tasks that are launched within public subnets do not have access to the internet.」
- Fargateは対照的に公式が「every Amazon ECS task on Fargate is provided an elastic network interface (ENI)」「When using a public subnet, you can optionally assign a public IP address to the task's ENI」と明記 — インスタンスのENI枚数制約はそもそも存在しない(根拠: AmazonECS/fargate-task-networking.html)
専用の足には物理的な上限があります。EC2起動タイプではインスタンスタイプごとのENI上限がタスク数の上限になり、c5.largeは既定でENI最大3枚=プライマリ1枚を除いてawsvpcタスクは典型的に2つまでです。密度を上げたいならawsvpcTrunkingでトランクENIを足します。そしてEC2起動タイプのタスクENIにはパブリックIPが付かないので、外に出るにはLambdaと同じくNAT経由になります。(根拠: 同ページ Linux considerations のENI上限・trunking・NAT各項、Fargate補足は fargate-task-networking.html)
⑨ 締め — 同じ部品「ENI」で組んだ、共有の足と専用の足
- Lambda = 共有の足、ECS = 専用の足。設計思想は逆でも、VPCに立つための部品はどちらもENIひとつ
- SG・ルート・NAT・DNSという本編で学んだ道具が、サーバーレスにもコンテナにもそのまま適用できる — これが「答え合わせ」の結論
Lambdaは「組み合わせごとに共有される足」、ECSは「タスクごとの専用の足」。設計は正反対でも、VPCに立つための部品はどちらもENIという同じネットワークカードです。だからSG・ルートテーブル・NAT・DNSという本編の道具立てが、サーバーレスにもコンテナにも一切の例外なく効きます。(根拠: 両ページの総合。Lambda共有ENI = lambda/configuration-vpc.html、ECS専用ENI = AmazonECS/task-networking-awsvpc.html)