CloudFormationを使用して、Lambda Insightを有効化する

CloudFormationを使用して、Lambda Insightを有効化する

AWS DVAの出題範囲の1つでもある、モニタリング・トラブルシューティングに関する内容です。

LambdaおよびCloudWatchが提供する機能の1つにLambda Insightsがあります。

CloudWatch Lambda Insights は、 で実行されているサーバーレスアプリケーション用のモニタリングおよびトラブルシューティングソリューションですAWS Lambda このソリューションでは、CPU 時間、メモリ、ディスク、ネットワーク使用率などのシステムレベルのメトリクスが収集、集約、要約されます。

Amazon CloudWatch での Lambda Insights の使用

本ページでは、以下のページを参考に、CloudFormationを使用して、Lambda Insightsを有効化したLambda関数を作成する方法を確認します。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Lambda-Insights-Getting-Started-cloudformation.html

構築する環境

Diagram of enabling Lambda Insight using CloudFormation

3つのLambda関数を作成します。

各関数にLambdaレイヤーを関連付けます。
これはLambda Insightsを有効化するために必要な手順です。

同様に、各関数にIAMロールを関連付けます。
こちらもLambda Insightsを動作させるために必要です。

Lambda Insightsによって収集されたメトリクスは、CloudWatchに保存されます。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-dva/tree/main/05/004

テンプレートファイルのポイント解説

Lambda

関数1

Resources:
  Function1:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Code:
        ZipFile: |
          import datetime

          def lambda_handler(event, context):
            print('awstut!')
            return {
              'statusCode': 200,
              'body': str(datetime.datetime.now())
            }
      FunctionName: !Sub "${Prefix}-function1"
      Handler: !Ref Handler
      Layers:
        - !Ref LambdaInsightsLayer
      MemorySize: !Ref MemorySize
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole.Arn
      Timeout: !Ref Timeout

  FunctionUrl:
    Type: AWS::Lambda::Url
    Properties:
      AuthType: NONE
      TargetFunctionArn: !GetAtt Function1.Arn

  FunctionUrlPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunctionUrl
      FunctionName: !GetAtt Function1.Arn
      FunctionUrlAuthType: NONE
      Principal: "*"
Code language: YAML (yaml)

Lambda Insightsを有効化する上でのポイントは、Lambdaレイヤーです。

Lambda Insights は、Lambda レイヤーとして提供される新しい CloudWatch Lambda 拡張機能を使用します。この拡張機能を、サポートされているランタイムで、Lambda 関数で有効にすると、システムレベルのメトリクスが収集され、その Lambda 関数の呼び出しごとに 1 つのパフォーマンスログイベントが発生します。

Lambda Insights によるサーバーレスアプリケーションのモニタリング方法

Lambda Insightsを有効化するために使用するべきLambdaレイヤーは、関数をデプロイするリージョンおよびアーキテクチャに依存します。
詳細は以下のページをご確認いただきたいのですが、例えば本環境(東京リージョン、ARM64)ですと、以下を選択します。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html

arn:aws:lambda:ap-northeast-1:580247275435:layer:LambdaInsightsExtension-Arm64:2

上記の文字列をLayersプロパティに指定します。

Lambda関数で実行するコードをインライン表記で定義します。
詳細につきましては、以下のページをご確認ください。

あわせて読みたい
CloudFormationでLambdaを作成する3パータン(S3/インライン/コンテナ) 【CloudFormationでLambdaを作成する】 CloudFormationでLambdaを作成する場合、大別すると以下の3パターンあります。 S3バケットにコードをアップロードする インライ...

コードの内容ですが、関数を実行した日時を返します。

またprint関数を使って、文字列を出力させます。
これは後述のテキストログに出力先を確認するためです。

本関数はFunction URLを有効化します。
本機能を有効化すると、HTTPSエンドポイントが生成され、URLにアクセスすると、本関数が実行できます。
Function URLに関する詳細は、以下のページをご確認ください。

あわせて読みたい
CFNでLambda Function URL – 認証方式: NONE 【CloudFormationでLambda Function URLを作成する(NONEバージョン)】 2022年4月22日にLambda Function URLがリリースされました。 この新機能は、AWS Lambda サービス...

関数2

Resources:
  Function2:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Environment:
        Variables:
          FUNCTION_URL: !GetAtt FunctionUrl.FunctionUrl
      Code:
        ZipFile: |
          import json
          import os
          import urllib.request

          function_url = os.environ['FUNCTION_URL']
          limit = 5

          def lambda_handler(event, context):
            responses = [urllib.request.urlopen(function_url).read().decode("utf-8") for i in range(limit)]

            return {
              'statusCode': 200,
              'body': json.dumps(responses, indent=2)
            }
      FunctionName: !Sub "${Prefix}-function2"
      Handler: !Ref Handler
      Layers:
        - !Ref LambdaInsightsLayer
      MemorySize: !Ref MemorySize
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole.Arn
      Timeout: !Ref Timeout
Code language: YAML (yaml)

先述の関数1を5回呼び出す内容です。

Lambda Insightsを有効化するために、先述のLambdaレイヤーを使用するように設定します。

関数3

Resources:
  Function3:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Code:
        ZipFile: |
          def lambda_handler(event, context):
            while True:
              pass
      FunctionName: !Sub "${Prefix}-function3"
      Handler: !Ref Handler
      Layers:
        - !Ref LambdaInsightsLayer
      MemorySize: !Ref MemorySize
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole.Arn
      Timeout: !Ref Timeout
Code language: YAML (yaml)

while文で空のループを繰り返す内容です。
タイムアウトを過ぎるまで繰り返し、関数の実行に失敗して終了します。

Lambda Insightsを有効化するために、先述のLambdaレイヤーを使用するように設定します。

IAMロール

Resources:
  FunctionRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy
Code language: YAML (yaml)

Lambda Insightsを有効化する上で、もう1つのポイントは、IAMロールです。

CloudWatchLambdaInsightsExecutionRolePolicy IAM ポリシーを関数実行ロールに追加します。

既存の Lambda 関数で Lambda Insights を有効にするために AWS CloudFormation を使用する

加えて、AWS管理ポリシーAWSLambdaBasicExecutionRoleをアタッチします。
これはCloudWatch Logsにテキストログを配信するために必要な権限を与えるものです。

EventBridge

Resources:
  Rule1:
    Type: AWS::Events::Rule
    Properties:
      Name: !Sub "${Prefix}-EventsRule-01"
      ScheduleExpression: rate(1 minute)
      State: ENABLED
      Targets:
        - Arn: !Ref FunctionArn1
          Id: !Ref Function1

  EventsRulePermission1:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref Function1
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn: !GetAtt Rule1.Arn
Code language: YAML (yaml)

関数1を取り上げます。
関数2および関数3も同様の設定です。

EventBridgeルールを定義して、関数を定期的に実行します。
詳細につきましては、以下のページをご確認ください。

あわせて読みたい
EventBridge(CloudWatch Events)のスケジュール式で、Lambda関数を定期的に実行する 【Lambda関数を定期的に実行する】 EventBridgeを使用することで、定期的なアクションを設定することができます。 今回はLambda関数を定期的に実行します。 【構築する...

今回は各関数を1分おきに実行するように設定します。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • Lambda関数1:dva-05-004-function1
  • Lambda関数2:dva-05-004-function2
  • Lambda関数3:dva-05-004-function3

AWS Management ConsoleからもLambda関数を確認します。

Detail of Lambda 1.
Detail of Lambda 2.
Detail of Lambda 3.

3つの関数が正常に作成されています。

EventBridgeルールを確認します。

Detail of EventBridge 1.

3つのルールが作成されています。
それぞれ1分ごとに3関数を呼び出す内容です。

動作確認

準備が整いましたので、Lambda Insightsのコンソール画面を確認します。

Detail of Lambda 4.

3つの関数に関する様々なメトリクスがグラフ化されています。

特徴的なグラフを確認します。

DurationやErrorsは関数3が高い数値を出しています。
これはwhile文でループを繰り返しているため、タイムアウトまで待機し、最終的に関数の実行に失敗しているためです。

Invocationsは関数1が高い数値を出しています。
これはEventBridgeルールで1分ごとに実行されていることに加えて、関数2から頻繁に呼び出されていることが原因です。

Network Usageは関数2が高い数値を出しています。
これは先述の通り、Function URLを通じて、関数1を頻繁に呼び出しているためです。

関数を指定してグラフを描画することもできます。

Detail of Lambda 5.

上記は、関数1に注目した画像です。

Lambda Insights用の各種メトリクスは、以下のCloudWatch Logsに配信されたログデータが使用されます。

Detail of CloudWatch Logs 1.

サンプルとして、関数1用のロググループを確認します。

Detail of CloudWatch Logs 2.

確かに各種メトリクスのデータが保存されています。

ちなみに本ロググループには、テキストログは配信されません。

Detail of CloudWatch Logs 3.

上記は関数1の内容ですが、今回はデフォルトのロググループ/aws/lamba/dva-04-003-function1に格納されました。

まとめ

CloudFormationを使用して、Lambda Insightsを有効化したLambda関数を作成する方法を確認しました。