Internal ALBからLambdaとVPC Lambdaを2つとも呼び出せるのか確認してみた

Internal ALBからLambdaを呼び出せるのか気になりました。ドキュメント読み漁るより試した方が早そうだったので手を動かしてみました。
2021.10.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ALB(Application Load Balancer)のバックエンドにEC2、ECS(コンテナ)の他にLambdaも指定できます。サービス間連携で利用されるInternal ALBのバックエンドに通常のLambdaと、VPC Lambdaを設定して呼び出せるのか気になり調べました。

簡単な検証環境を作成し試してみたので結果を共有します。

結論

  • Internal ALBからLambdaと、VPC Lambdaを呼び出せる。
    • Internal ALBからLambdaを呼び出す際にNAT GatewayなどのVPC外と通信するリソースは必要ない

ALBの種類

ALBにはインターネット向け(Internet-facing)と内部向け(Internal)の2種類あります。WebシステムですとACMのSSL/TLS証明書を付けたり、AWS WAFを付けたりとインターネット向けのALBにはよくお世話になっているのではないでしょうか。

当記事では内部向けのALBとLambdaの組み合わせを試してみます。

検証環境

Internal ALBにターゲットグループを2つ紐付けます。ターゲットグループの1つはVPCの外で起動する通常のLambda。もう片方はVPC内で起動するVPC Lambda。パブリックサブネットで起動しているEC2にログインしcurlコマンドでInternal ALBのDNS名にアクセスすると、ポート違いで各Lambdaが実行されます。各Lambdaはインターネットへアクセスし、結果としてLambdaのアクセス元グローバルIPを返します。

ALBのリスナー設定は以下のとおりです。

  • :80ポートにアクセスすると通常のLambdaが起動するターゲットグループを指定
  • :81ポートにアクセスするとVPC Lambdaが起動するターゲットグループを指定

Lambda関数

双方のLambdaのコードは同じ内容です。Lambdaの実行環境がVPC外か、VPC内かの違いがあるため2つ関数を用意する必要があります。 実行内容はhttps://ifconfig.meにアクセスしてグローバルIPを返すだけです。

import json
import urllib.request


def lambda_handler(event, context):
    url = 'https://ifconfig.me'

    req = urllib.request.Request(url)
    with urllib.request.urlopen(req) as res:
        body = res.read()
    print(body)

    return {
        'statusCode': 200,
        'body': body
    }

全く同じコードのLambdaをVPC起動か否かの違いで2つ用意。

やってみた

Internal ALBからVPC外の通常のLambdaを呼び出すときにNAT Gatewayや、VPCエンドポイントなどのVPCの外部へ接続可能なリソースはいるのか?という素朴な疑問もありました。なので、NAT Gatewayあり/なしパターンを試してみます。

NAT Gatewayありパターン

1. Lambda実行結果

ユーザ側で管理できないグローバルIPアドレスから通信していました。

$ curl http://internal-internalALB-1402039929.ap-northeast-1.elb.amazonaws.com:80
13.115.250.226

2. VPC Lambda実行結果

LambdaのグローバルIPアドレスを固定化でお馴染みの構成です。NAT GatewayのEIPから通信していました。

$ curl http://internal-internalALB-1402039929.ap-northeast-1.elb.amazonaws.com:81
54.150.202.168

NAT GatewayのEIPアドレスと同じですね。

NAT Gatewayなし

1. Lambda実行結果

NAT Gatewayありパターンから少し時間が経ったこともあり、アクセス元のグローバルIPアドレスは変わっていました。また、Internal ALBからLambdaを呼び出すのにはNAT Gatewayなどは不要であることが確認できました。

$ curl http://internal-internalALB-1402039929.ap-northeast-1.elb.amazonaws.com:80
18.182.59.248

2. VPC Lambda実行結果

NAT Gatewayがないのでインターネットへでていけず、LambdaはタイムアウトしALBからエラーが返ってきました。

$ curl http://internal-internalALB-1402039929.ap-northeast-1.elb.amazonaws.com:81
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
</body>
</html>

ドキュメントを確認すると、ALBはLambdaのタイムアウトを待つことを知りました。

The load balancer waits until your Lambda function responds or times out. We recommend that you configure the timeout of the Lambda function based on your expected run time. For information about the default timeout value and how to change it, see Basic AWS Lambda function configuration. For information about the maximum timeout value you can configure, see AWS Lambda limits.

引用: Lambda functions as targets - Elastic Load Balancing

おわりに

ALBから直接Lambdaを実行する機会が今までなく、動きそうだけどどうなんだろうかと疑問があったため手を動かしてみました。ALBのヘルスチェックを有効にしてLambdaをチェックするときは、Lambdaのレスポンスでちゃんと200を返さないとヘルスチェック失敗したりと、やってみると些細なところでつまづきました。

ALB + Lambdaの組み合わせで以下のリンクのような実装もあるんだと新しい発見がありいろいろと収穫はありました。

参考