既存の大量の Lambda 関数に、Errors と Throttles メトリクスのアラーム通知設定を自動で行う

一度セットアップしてしまえば、メンテナンス不要で、対象リージョンの Lambda 関数の Error や Throttles のログを Slack 通知できます。
2022.07.17

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

はじめに

こんにちは、サービスグロースチームの筧です。

「既存の大量の Lambda 関数に対して、CloudWatchLogs の Error や Throttles のメトリクスのログを取得して Slack に通知する設定をしたい」

って思ったことありませんか? 通知設定方法の一つとしては、Lambda 関数を CloudWatch アラームでモニタリングし、Amazon SNS 経由で AWS Chatbot で通知する方法があります。

Lambda 関数を 、AWS Chatbot で通知を受け取る | Amazon Web Services ブログ

上記ブログののソリューションでは、モニタリングしたい Lambda 関数を指定したい際に、 CloudFormation のパラメータに、Lambda 関数名をカンマ区切りリストで入力しています。 こちらのソリューションの利用を検討した際に、モニタリングしたい Lambda 関数をパラメータ入力ではなく、 自動的に追加されるような機能があれば、更に簡単に展開でき、メンテナンスも減って良いなと思いました。

つくったもの

そこで以下の PoC サービスを作成しました。

  • Serverless Framework の resources で、緑枠のリソースを作成。当該内容は先日のブログで紹介済です。
    • Amazon SNS Topic
    • AWS Chatbot SlackChannelConfiguration
    • IAM Role(上記 AWS Chatbot 設定用の IAM Role)

Serverless Framework で AWS Chatbot と Amazon SNS のリソースを作成してみた

  • Serverless Framework の functionsで、赤枠のリソースを追加/削除する機能を持つ Lambda 関数を作成。Lambda 関数は Step Functions のステートマシンの Task として定義されており、Amazon EventBridge のイベントルールで日本時間正午にそのステートマシンが実行されるようにイベントスケジュール。本ブログではこちらの Serverless Framework の functions を作成する箇所をメインにご紹介します。

前提

筆者の環境

% sw_vers
ProductName:    macOS
ProductVersion: 12.2.1
BuildVersion:   21D62
% sls --version
Framework Core: 3.19.0 (local) 3.19.0 (global)
Plugin: 6.2.2
SDK: 4.3.2
% pipenv --version
pipenv, version 2022.6.7

リポジトリ

動かしてみる

セットアップ

以下の README を参照してセットアップください。

Code - takaakikakei/blog-alert-lambda | GitHub

README にも書いていますが、アラーム設定したいリージョンごとにセットアップが必要です。 システムの仕様上、東京リージョン(ap-northeast-1)アラーム設定したい Lambda 関数がない場合でも必ずセットアップしてください。 セットアップ後、セットアップ済みのリージョンで、アラーム設定されてない Lambda 関数はイベントスケジュールに従って自動追加されます。

本ブログでは東京リージョン(ap-northeast-1)のみでセットアップした前提で進めます。

Add function の実行

Add functionは、CloudWatch アラームの追加に利用します。東京リージョンの CloudWatch アラームのサービス画面にアクセスしてみると、現在の環境では、アラームが既に17個設定されている状況です。

Lambda のサービス画面にアクセスしてみると、108個の関数が存在していることが分かります。手動で全ての関数に CloudWatch アラームを設定するのは大変です。

Add function に紐づくステートマシンを手動実行します。

成功したら、CloudWatch アラームのサービス画面に再度アクセスしてみます。233個のアラームが設定されており、216個(108 * 2) のアラームが追加されたことが分かります。なぜ Lambda 関数の2倍のアラームが設定されたかというと、Errors と Throttles のメトリクスごとにアラームを作成しているからです。これで大量のアラームを簡単に設定できました。

なお、ステートマシンの設定上で、Amazon EventBridge のイベントルールを定義しており、日本時間正午にステートマシンが実行されるように、イベントスケジュールしています。なので適当な Lambda 関数を追加して、次の日本時間正午時間まで待つと、自動で対象関数用のアラームも追加されます。

エラー通知を確認する

serverless.yml の functions で create_error を定義しています。これは 意図的にエラーを発生させる Lambda 関数です。対象の Lambda 関数のサービス画面にアクセスして、テスト実行します。

数分で Slack 通知がされました。

通知がこない場合、CloudWatch アラームの設定が裏側で時間がかかっている可能性があります。時間をあけてリトライしてみてください。Slack 通知内容の Show logs や Show error logs をクリックすることで、Slack 上で、CloudWatch Logs の内容も確認できます。便利ですよね。

Delete function の実行

Delete functionは、設定した CloudWatch アラームの一括削除に利用します。 Delete function に紐づくステートマシンを手動実行します。

成功したら、CloudWatch アラームのサービス画面に再度アクセスしてみます。本ツールで作成したアラームが全て削除され、アラームが17個に戻っていることが分かります。

function の概要説明

Add function(CloudWatch アラームの追加関数)

概要

Add function はデプロイ済みの Lambda 関数に、CloudWatch アラームを自動設定する関数になります。デプロイ済みの Lambda 関数と、本ツールでアラーム設定した Lambda 関数の diff を取り、アラーム未設定の Lambda 関数にアラーム設定を行います。CloudWatch アラームの設定内容としては、Lambda 関数の CloudWatchLogs で Errors と Throttles のログが出力された際に、前回のブログで設定した、Amazon SNS と AWS Chatbot を経由して、Slack へアラーム通知を行います。

コードの定義箇所

serverless.yml では functions で add として定義しています。そして、includes/state-machines.yml のステートマシンの設定上で、add を参照しています。またステートマシンの設定上で、Amazon EventBridge のイベントルールを定義しており、日本時間正午にステートマシンが実行されるように、イベントスケジュールしています。もちろん、対象のステートマシンで手動実行も可能です。

serverless.yml

・・snip・・

functions:
  add:
    handler: src/handlers/add.handler
    timeout: 300
  delete:
    handler: src/handlers/delete.handler
    timeout: 300
  create_error:
    handler: src/handlers/create_error.handler
    timeout: 60

・・snip・・

stepFunctions: ${file(includes/state-machines.yml)}

・・snip・・

includes/state-machines.yml

stateMachines:
  AlertLambda-Add:
    events:
      - schedule: cron(00 03 * * ? *) #https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/services-cloudwatchevents-expressions.html
    name: AlertLambda-Add-${self:provider.stage}
    definition:
      StartAt: Add
      States:
        Add:
          Type: Task
          InputPath: "$"
          Resource:
            Fn::GetAtt: [add, Arn]
          ResultPath: "$"
          End: true

Lambda関数自体は src 配下に書いています。階層構造を定義していますが、それぞれの役割は以下です。 handlers -> use_cases -> services 配下の関数順に確認すると分かりやすいと思います。

  • handlers: function のエントリーポイントを定義
    • add.py
  • use_cases: function のビジネスロジックを定義
    • add.py
  • services: function で用いるサービスを定義
    • cloudwatch.py
    • lambda_client.py

Delete function(CloudWatch アラームの削除関数)

概要

Delete function は本ツールで設定した CloudWatch アラームを一括削除する関数になります。CloudWatch アラーム名の prefix が AlertLambda のものを削除します。万が一、本ツール設定以前に当該 prefix を利用した CloudWatch アラームがある場合は、誤削除に注意ください。

コードの定義箇所

serverless.yml では functions で delete として定義しています。そして、includes/state-machines.yml のステートマシンの設定上で、delete を参照しています。対象のステートマシンで手動実行も可能です。

serverless.yml

・・snip・・

functions:
  add:
    handler: src/handlers/add.handler
    timeout: 300
  delete:
    handler: src/handlers/delete.handler
    timeout: 300
  create_error:
    handler: src/handlers/create_error.handler
    timeout: 60

・・snip・・

stepFunctions: ${file(includes/state-machines.yml)}

・・snip・・

includes/state-machines.yml

・・snip・・

  AlertLambda-Delete:
    name: AlertLambda-Delete-${self:provider.stage}
    definition:
      StartAt: Delete
      States:
        Delete:
          Type: Task
          InputPath: "$"
          Resource:
            Fn::GetAtt: [delete, Arn]
          ResultPath: "$"
          End: true

Add function と同じく、Lambda関数自体は src 配下に書いており、同じ階層構造を取っています。

  • handlers: function のエントリーポイントを定義
    • delete.py
  • use_cases: function のビジネスロジックを定義
    • delete.py
  • services: function で用いるサービスを定義
    • cloudwatch.py

おわりに

最後まで読んでいただきありがとうございます。 ご紹介したツールを活用することで、皆さんのシステム監視の負荷が軽減できたら幸いです。

それではまた!