LoginSignup
9
7

More than 3 years have passed since last update.

CloudFront+Lambda@Edgeでハマったこと

Last updated at Posted at 2020-02-28

概要

Lambda@Edgeとは、CloudFrontのエッジロケーションで実行できるLambda関数です。
コンテンツがオリジンから返されたときにキャッシュできるので、アプリケーション側のパフォーマンスを向上させることができます。
さらにLambda@Edgeの処理として、画像リサイズ機能を組み込むとリサイズされた画像をCloudFrontがキャッシュするので、ユーザはリサイズによるオーバーヘッドを受けない綺麗なアーキテクチャを作ることができます。
具体的には、下図で右下の「Origin response」に画像のリサイズ機能を持ったLambda@Edgeを配置します。
(下図はオフィシャルから拝借)

cloudfront-events-that-trigger-lambda-functions.png

そんな一見便利そうに見える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もサポートしている、わけではないので注意が必要です。

Lambda 関数の要件と制限

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で設定した関数は各リージョンにレプリカが作られて実行されるため、簡単には削除できません。
手順としては、
1. CloudFront Behaviorの設定からLambda@Edgeの連携を解除する
2. 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');
};
9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7