LambdaからVPC内のリソースにアクセスすると初回実行がものすごく遅い
先日、待ちに待ったLambdaのVPC内へのリソースへのアクセスが可能となりました。
早速テストコードを書いて、これでもうTomcatとはおさらばできると小躍りしたのもつかの間、あることに気が付きました。
「初回実行がものすごく遅い」
ものすごく遅いのです。
数秒とかのレベルではなく数十秒とかかかっています。
VPC内のリソースにアクセスした際のレイテンシーの原因
これはLambda functionがVPC内のリソースにアクセスする際にはENI(Elastic Network Interface)が作成されることが原因のようです。
このENIの作成には数十秒から1分程度の時間を要します。
また、このLambdaによって作成されたENIは一定時間使用されないと自動で破棄されます。
このレイテンシーはバッチ処理などでは問題にならないかもしれませんが、API GatewayのバックエンドでLambdaを使ってWebAPIなどを構築する場合には大きな問題となります。
解決方法(案)
これに対する解決策のひとつとして「定期的にLambda functionをinvokeする」という方法が考えられるのですが、果たしてそれが根本的な解決となるか、また最適な間隔を検証すべく、以下の確認を行いました。
- 同一のVPC設定の場合、作成済みのENIは再利用されるか。
- 同一のVPC設定の場合、作成済みのENIは別functionでも再利用されるか。
- 作成されたENIが保持される時間はどのくらいか。
解決方法(案)の検証
テスト用のLambda functionを作成し、ひとまず10分間隔で定期的にinvokeするように設定し、ENIがどのように作成・破棄されるかを見てみます。
VPC設定は以下のようにしました。
- VPC
- VPC-1
- Subnets
- subnet-a, subnet-c
- Security Groups
- sg-00000001
※それぞれの項目の名前は便宜上つけたものです
検証結果
結果は以下のとおり。
- 最初の実行ではENIが一つ、「VPC-1, subnet-a, sg-00000001」に対応したものが作成された。
- 二度目の実行ではENIは作成されなかった。
- 三度目の実行ではENIが一つ、「VPC-1, subnet-c, sg-00000001」に対応したものが作成された。
- その後、何回か実行を監視したが新たにENIは作成されなかった。
この結果を見ると同VPC、同Security GroupのsubnetごとにENIが作成され、再利用されていることがわかります。
ここまでは良かったのですが、さらにしばらく様子を見たところ、
上記2つのENIは残っている(破棄されていない)にもかかわらず「VPC-1, subnet-a, sg-00000001」に対応したENIが新たに作成されていました。
つまり、再利用できるはずのENIが保持されているにもかかわらずENIが作成されることもある、ということです。
また、同じVPC設定を行った別のfunctionをinvokeしてみたところ、新たにENIは作成されませんでした。
つまり別functionでも同じVPC設定なら作成済みのENIは共有されるということです。
さらに、ENIの作成のタイミングや条件を見るために、「VPC設定を行ったが実際にはアクセスしないfunction」を試してみました。
結果としては実際にVPC内のリソースへのアクセスをするかどうかにかかわらず、invokeされた時点でENIが作成されることが確認できました。
ENIの保持期間について
ENIの保持期間については下記のブログ記事のとおり、Lambdaの実行環境はコンテナなので、コンテナの保持期間と等しいようです。
https://aws.amazon.com/blogs/compute/container-reuse-in-lambda/
ただし、コンテナの寿命については公開されていないため、結局のところENIの保持期間は不明ということになります。
まとめると
- 作成されるENIはVPCの設定による。実際にそのVPCにアクセスするかどうかは関係ない。
- ENIの保持期間はコンテナ依存だが、コンテナの保持期間は公開されていない。つまり不明。
- 同一のVPC設定の場合、「基本的には」ENIは共有・再利用されるが必ず再利用されるわけではない。
結論
以上から、「定期的にLambda functionをinvokeする」については
「効果はあるが確実ではない」、
また、
「定期的にinvokeする最適な間隔は不明」
ということになります。
なかなか厳しい結果ですが、他に有効な方法も今のところ見つかっていないので現状では最も有効な方法なのかなと思います。
そもそもLambdaにVPC設定させるのじゃなくて、任意のENIをアタッチできるようになってくれればよさそうですが。
API GatewayのバックエンドとしてLambdaを使用したWebAPIってかなり需要があると思うので、なんとかなって欲しいですね。