はじめに
VPC Lambdaをプライベートサブネットに配置し、手元のPCのターミナルからaws lambda invokeコマンドを実行すると呼び出すことができます。Lambdaがネットに繋がってないのになんで叩けるんや...と思ったので少し調べて見ました。
VPC Lambdaの構造
VPC Lambdaとは言いつつ、Lambdaが実行されるのはユーザーが作成したVPC内ではありません。
AWS Lambda Service VPC というLambda Service管理のVPCがあり、そこにLambdaが配置されています。かわりにユーザーが作成したVPCにはENIが作成されます。LambdaはENIを経由して、ユーザーが用意したVPC内のリソースにアクセスします。
このENIのことをHyperplane ENIと言うそうです(なんかかっこいいですね)。
VPC Lambdaを作成する際に、VPC, サブネット, セキュリティグループを指定する必要があります。Hyperplane ENIはこの時指定したサブネットに配置されるようです。各サブネットとセキュリティグループの組み合わせの数だけHyperplane ENIは作成されます。
Lambda は、各サブネットでセキュリティグループの固有のセットごとにネットワークインターフェイスを作成します。同じサブネットとセキュリティグループの組み合わせを共有するアカウント内の関数は、同じネットワークインターフェイスを使用します。
invoke APIを実行するとなぜVPC Lambdaが実行できるのか
まず前提として、VPC Lambdaの設定上、プライベートサブネットが設定されているとします。
この状況で手元のPCからAWS CLIを使ってinvoke APIを実行したら、私は手元のPCからENIにアクセスする方法がないので、Lambdaの実行はできないものだと考えていました。しかし、実際は冒頭でも述べたようにLambdaを起動させることができます。
この理由は、invoke APIはENIを通してLambdaを呼びだしていないからだと思われます。
公式ドキュメントにも目を通したのですが、AWS Lambda Service VPC に直接アクセスしていることを言及している箇所を見つけることはできませんでした(見落としているだけだったら本当にごめんなさい)。代わりにstackoverflowで、本件に関連している質問を見つけ、その中で言及されていました。
In order to trigger a Lambda function, all that's required is for the caller to have outbound access to the Invoke AWS API. It is not necessary for the invoked Lambda function to have any open inbound ports, or any public Internet access.
つまり、Lambdaを呼び出す側がInvoke APIにアクセスすることができれば、Hyperplane ENIの設定とは無関係にAWS Lambda Service VPCの関数を呼び出すことができます。
一方で、Lambda関数から外部のリソースにアクセスする場合はHyperplane ENIを経由するので、設定したサブネットやセキュリティグループの影響を受けます。そのためVPC LambdaがVPC内やインターネットにアクセスする場合には、セキュリティグループの設定や、NATゲートウェイの配置などを適切に行う必要があります。