概要
Lambda@Edgeとは、CloudFrontのエッジロケーションで実行できるLambda関数です。
コンテンツがオリジンから返されたときにキャッシュできるので、アプリケーション側のパフォーマンスを向上させることができます。
さらにLambda@Edgeの処理として、画像リサイズ機能を組み込むとリサイズされた画像をCloudFrontがキャッシュするので、ユーザはリサイズによるオーバーヘッドを受けない綺麗なアーキテクチャを作ることができます。
具体的には、下図で右下の「Origin response」に画像のリサイズ機能を持ったLambda@Edgeを配置します。
(下図はオフィシャルから拝借)
そんな一見便利そうに見えるLambda@Edgeですが、CloudFrontとLambda@Edgeを使って、画像リサイズのシステムを構築したときにLambda@Edgeの仕様でいくつかハマったのでまとめました。
Lambda@Edgeに東京リージョンはない
Lambda@Edgeに東京リージョン(ap-northeast-1)はありません。
**バージニアリージョン(us-east-1)**で作成しましょう。
Lambda@Edgeでは環境変数は利用できない
Lambda@Edgeは環境変数を持てません。これ結構痛いですね。環境変数を使いたい時は別の方法を探す必要があります。
筆者はAWS System Managerのパラメータストアに事前にパラメータを設定しておき、Lambda関数内で読み込むようにしていました。
(CloudFormationのスタックにアウトプットしておく、DynamoDBに値を格納しておくなどやり方は様々だと思います)
(現時点では)Lambda@EdgeはNode12.xをサポートしていない
(筆者はこれに気づくのになかなか時間がかかりました...)
サポートしているランタイムは、オフィシャルでチェックしましょう。
現時点では、Node8.10はサポート切れ、Node12.xは未サポートのため、Node.jsを使いたい場合はNode10.xを使うしかなさそうです。
LambdaがサポートしているからLambda@Edgeもサポートしている、わけではないので注意が必要です。
CloudFrontにはバージョンつきのLambda関数のARNを設定する必要がある
CloudFront BehaviorにLambda関数のARNを設定する際、Lambda関数の名前のARNだけでは設定できません。
名前+バージョン入りのARNを設定する必要があります。
ちなみに、バージョンは$latestも設定できないので、バージョン番号を指定しないといけません。
lambda関数の更新したら、新しいバージョン番号を発行して、CloudFrontで更新する必要があります。
つまり、lambda関数を更新する度にCloudFront Distributionを更新する、すなわちデプロイ(各エッジロケーションへの伝搬)に数十分かかります。
Lambda@Edgeの実行ログは実行地域のリージョンのCloudWatch Logsに出る
Lambda@Edgeをバージニアリージョン(us-east-1)に作成しましたが、バージニア側にはCloudWatchのログがありませんでした。
これは、Lambda@Edgeが実行されてないわけではなく、Lambda@Edgeが実行されたリージョンにログが出ています。(そりゃそうだって感じですね...)
日本でCloudFrontにアクセスしてLambda@Edgeを実行した場合は、東京リージョン付近のエッジロケーションで実行されるので、ログが出ないと思ったときはまず東京リージョンのCloudWatchのログを確認しましょう。
オフィシャルにも書いてました。
Lambda 関数の CloudWatch メトリクスと CloudWatch Logs
CloudFront イベントのトリガーを作成すると、Lambda から CloudWatch に自動的にメトリクスが送信されるようになります。メトリクスはすべての Lambda リージョンで使用できます。各メトリクスの名前は、/aws/lambda/us-east-1.function-name です。function-name は、関数を作成したときに割り当てた名前です。CloudWatch は、関数が実行される場所に最も近いリージョンにメトリクスを送信します。
Lambda@Edgeで設定した関数は削除に時間がかかる
lambda@Edgeで設定した関数は各リージョンにレプリカが作られて実行されるため、簡単には削除できません。
手順としては、
- CloudFront Behaviorの設定からLambda@Edgeの連携を解除する
- Lambda@Edgeを削除する(削除できない場合は時間が経ってから再度試してみる)
になります。
Tips
CloudFrontのエンドポイントにアクセスすると、503エラーになる
Lambda@Edgeの問題の可能性があります。
- 同時実行数1,000に達している
- サポートされていないランタイムで実行している
- Lambda関数自体に誤りがある
など。
原因の切り分けとして、簡単なLambda@Edgeをデプロイしてみましょう。また、Lambda@Edgeを入れずに、CloudFrontからS3にアクセスできるか、なども原因の切り分けになるかもしれません。
exports.handler = (event, context, callback) => {
console.log("Hello");
callback(null, 'callback');
};