PagerDuty連携をクイック作成リンクから簡単にできるようにしてみた

2024.06.10

現在運用保守チームでは、PagerDutyを活用してアラート発報にすぐに気づけるような仕組みを作っています。

今回はPagerDutyとアラート連携を行うためのLambda関数を作成してくれる、クイック作成リンクを作りました。クイック作成リンクを開くとCloudFormationのスタック作成ページに飛びます。パラメータを入力、展開するだけでLambda関数が作られて、アラートがPagerDutyに連携されます。

PagerDutyとは

最初に、PagerDutyが何か知らない人からすると、なぜアラートをPagerDutyに連携するのか分かりづらいと思うのでPagerDutyの主な機能を簡単に紹介します。

PagerDutyはインシデント管理ができるSaaSです。

アラートをPagerDutyに連携することで、インシデント作成が行われます。PagerDuty上から各インシデントごとに発生日時や担当者、現在のステータス(発報済み、確認済み, 解決済み)が見れます。インシデント発生時に担当者に通話してくれたり、担当者が反応しない場合は次の担当者に通話してくれたりします。また同じ特定のアラートに関してはアラートを飛ばさないようにするといった設定もできます。

PagerDutyのスマホアプリもあるので、スマホからエラー内容を確認できたり、ステータスの更新もできます。

PagerDuty連携について

自分たちが運用保守するプロジェクトで、よくあるアラート発報の構成は以下のようなものです。ここまでの構成は開発段階ですでに他の方が作ってくれています。

サーバーサイドでエラーが発生 → 

CloudWatch Logsにエラーログを吐く → 

メトリクスフィルターに引っかかる → 

AWS SNSでトピック作成 → Slack通知

今回このような構成に対して、PagerDuty連携のためLambda関数を追加します。

AWS SNSでトピック作成 → 

Lambda関数を起動して、PagerDutyのAPI呼び出し new → 

PagerDutyでインシデント作成

このLambda関数では、エラーの発生日時を元にCloudWatchからエラーログの取得をしてくれます。PagerDutyのAPI呼び出し時にログも連携してくれるので、PagerDuty上からエラーログが見れます。

またサーバーサイドのログ出力でLambda PowerToolsが使われている場合はトレースしたエラーログを取得するようしました。function_request_idを使ったログ検索をしています。この場合はエラーと関連する一連のログをPagerDuty上から確認できます。Lambda PowerToolsが使われていない場合はメトリクスフィルターに引っかかったログのみを取得しています。

あるユーザーがAPIを呼び出して、Lambdaが起動

受け取ったリクエスト内容をログ出力

DBからユーザー情報取得してログ出力

外部API呼び出しでリクエスト、レスポンス内容をログ出力

Lambdaが終了

この間に吐かれたログには同じfunction_request_idが付与され、一連のログとしてトレースできます。

Lambdaで動かしているスクリプトについては、以下のリンクから見れます。 https://github.com/shogo0421/pagerduty-lambda-cfn/blob/main/handler/src/index.ts

クイック作成リンク

クイック作成リンクとは、ブラウザで開くとCloudFormationのスタック作成ページに飛ぶことができるリンクです。予めS3に配置したcfnテンプレートを元にスタック作成ができます。

これまで上記の構成を追加するために、自分たちが保守する各プロジェクトごとにcdkのコードを追加する作業をしていました。

追加していたコードの内容は

  • Lambda上で実行するスクリプトを追加
  • PagerDuty連携のためのLambda作成
  • LambdaにCloudWatchからログ取得する権限を追加
  • SNSトピックにサブスクリプションを追加してLambdaを呼び出す

とかです。

これをテンプレート化してしまえば、プロジェクトごとにコードを追加する必要が無くて楽かもとか、PagerDutyを知らない人でもこの作業が簡単に出来そう、と思いクイック作成リンクを作りました。

以下のリンクを開いて、PagerDutyを導入したいAWS環境の権限を持ったロールに切り替えます。

https://ap-northeast-1.console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/create/review?templateURL=https://quick-create-cfn-template.s3.ap-northeast-1.amazonaws.com/PagerdutyLambdaCdkStack.template.json&stackName=PagerdutyLambdaCdkStack

エラー発報用のSNSトピックのARNと、PagerDutyのインテグレーションのキーとURLを入力して、作成ボタンを押せば導入できます。

またクイック作成リンクの末尾にクエリパラメータを追加すると、各パラメータが最初から入力された状態になります。([~]の角括弧も含め消して、各パラメータに置換。)

https://ap-northeast-1.console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/create/review?templateURL=https://quick-create-cfn-template.s3.ap-northeast-1.amazonaws.com/PagerdutyLambdaCdkStack.template.json&stackName=PagerdutyLambdaCdkStack
&param_pagerDutyIntegrationKey=[~]
&param_pagerDutyIntegrationUrl=[~]
&param_errorTopicArn=[~]

エラー発報用トピックのARNはAWS環境から確認

PagerDutyのインテグレーションのキーとURLはPagerDutyから確認

動作確認

うまくアラートがPagerDuty連携できているか確認するため、CloudWatch Logs上に手動でイベントログを作成して、アラートを発生させます。

  1. CloudWatch Logsを開いて、エラー発報用のメトリクスフィルターが設定されたロググループを選択
  2. 適当なログストリームを開いて「ログイベントを作成」を選択
  3. 「test ERROR」などメトリクスフィルターに引っかかる文字を含むログを作成
    (ERRORとErrorなど大文字と小文字でメトリクスフィルターの設定と違っていても反応しないので注意)
  4. 数分(メトリクス生成の時間間隔分)待つとPagerDuty上でインシデント作成される
    PagerDutyのスマホアプリを入れていると通知が来る

cfnテンプレートについて

クイック作成リンクを作るに当たって、S3に配置したcfnテンプレートは、CDKから生成しました。そのCDKプロジェクトのコードについては以下のリポジトリから確認できます。

https://github.com/shogo0421/pagerduty-lambda-cfn

S3に配置しているcfnテンプレートの内容は以下で見れます

https://quick-create-cfn-template.s3.ap-northeast-1.amazonaws.com/PagerdutyLambdaCdkStack.template.json

面倒な点

デプロイできるリージョンについて

クイック作成リンクを使ってLambda関数をデプロイする場合、cfnテンプレートの他に、Lambda関数のスクリプト(ビルド生成物)もs3バケットに配置しないといけません。この時、Lambdaのデプロイ先のリージョンと、Lambdaのスクリプトが配置されたs3バケットのリージョンが、一致していないとデプロイに失敗します。そのため普段よく利用する2つのリージョン(東京、大阪)のS3には、スクリプトのビルド生成物を配置しています。しかし、それ以外のリージョンでは今回のクイック作成リンクは使えず、追加で作業が必要です。使うためには他のリージョンにもバケットの作成とビルド生成物の配置をします。今のところ頻繁に利用するリージョンが増えるわけではないので、そこまで支障をきたしませんが面倒です。

Lambda PowerToolsに依存

今回のPagerDuty連携用Lambdaが、CloudWatch Logsからエラーと関連した一連のログ取得をしてくれるのは、Lambda PowerToolsが導入されている場合のみです。それ以外の場合は、メトリクスフィルターに引っかかったログのみが取得されます。バックエンドがEC2の時など、Lambda PowerToolsを使わないことは結構多いです。毎回トレースしたエラーログまで表示できると不具合の調査がしやすく便利です。

補足

複数のAWS環境からログ取得してくるLambdaを共通基盤的に一つだけ作ることも考えましたが、一つのLambdaがクロスアカウントでログ取得することになります。Lambdaに必要最小限の権限のみを持たせることを考えると、同じ処理をするLambdaでも各環境ごとに作った方が良いと思いました。