#概要
CloudWatch メトリクスアラームを使用し AWS リソースの監視を開始する上で、通知を Google Chat にも投稿する必要が出てきたため、Lambda ファンクションを使用し、 SNS をトリガーにして Google Chat 連携を行いました。
本記事では、AWS CDK を利用して SNS トピックの作成 および、lambda リソースの作成を行い、 SNS のテストトピックを発行し、 Google Chatに通知が来るまで確認してみたいと思います。
実際の運用では、監視対象の CloudWatch メトリクスアラーム と 上記で作成した SNSトピックの紐付けを行うことで、アラーム発砲から Google Chat 通知までの一連の流れを実現することができます。
#前提
・ Goole Chatのチャットルームを作成し、Webhook の URLを取得している
・ AWS CDK デプロイ環境が整っている
AWS CDK にて SNS/Lambda リソースの作成
実装は以下になります。
CDK context を利用して、 Webhook の URL を渡してあげて、 Lambda の環境変数に展開しています。。
import * as cdk from "@aws-cdk/core";
import * as sns from "@aws-cdk/aws-sns";
import * as iam from "@aws-cdk/aws-iam";
import * as lambda from "@aws-cdk/aws-lambda";
import * as subscriptions from "@aws-cdk/aws-sns-subscriptions";
export class DevopsAlarmStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const webhookURL = this.node.tryGetContext("webhookURL") || "";
// lambda用ロール作成
const lambdaIamRole = new iam.Role(
this,
"test-iam-role-for-lambda-devops-alarm",
{
roleName: "test-iam-role-for-lambda-devops-alarm",
assumedBy: new iam.ServicePrincipal("lambda.amazonaws.com"),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName(
"service-role/AWSLambdaBasicExecutionRole"
),
],
}
);
// SNS トピック作成
const myTopic = new sns.Topic(this, "test-alarm-topic", {
displayName: "test-alarm-topic",
topicName: "test-alarm-topic",
});
// 通知用 lambda 作成
const myFunction = new lambda.Function(
this,
"test-lambda-alarm-handler",
{
code: lambda.Code.fromAsset("../src", {
exclude: ["*.ts", "cdk.out"],
}),
handler: "AlarmHandler.handler",
functionName: "test-lambda-alarm-handler",
runtime: lambda.Runtime.NODEJS_12_X,
role: lambdaIamRole,
environment: {
HANGOUT_WEBHOOK_URL: `${webhookURL}`,
},
}
);
// SNS と lambda の紐付け
myTopic.addSubscription(new subscriptions.LambdaSubscription(myFunction));
}
}
Lambda 内関数の実装
Lambda 内の実装は以下になります。
Lambda で展開された環境変数から HANGOUT_WEBHOOK_URL を取得し、利用しています。
SNS から渡ってきたイベントを、見やすいように整形して、Google Chat Webhook API を利用し、通知してあげます。
const fetch = require("node-fetch");
const webhookURL = process.env.HANGOUT_WEBHOOK_URL;
export const handler = async (event: any) => {
const text = get_text(get_message_from_event(event));
console.log(text);
await fetch(webhookURL, {
method: "POST",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
body: JSON.stringify({
text: text,
}),
}).then((response: any) => {
console.log(response);
});
};
function get_message_from_event(event: any) {
return JSON.parse(event.Records[0].Sns.Message);
}
function get_text(message: any) {
const alarm_name = "AlarmName" in message ? message["AlarmName"] : "";
const old_state = "OldStateValue" in message ? message["OldStateValue"] : "";
const new_state = "NewStateValue" in message ? message["NewStateValue"] : "";
const new_state_reason =
"NewStateReason" in message ? message["NewStateReason"] : "";
return (
"*" +
alarm_name +
":* " +
old_state +
" ⟶ " +
new_state +
"\n```" +
new_state_reason +
"```"
);
}
SNS テストトピックの発行
AWS コンソールにて下記の json メッセージを発行します。
[Amazon SNS] - [トピック] - [上記のCDKにて作成したトピックを選択] - [メッセージの発行]
{
"AlarmName": "sample-error",
"AlarmDescription": "sampleでエラーが発生しました。",
"AWSAccountId": "xxxxxxxxxxxx",
"NewStateValue": "ALARM",
"NewStateReason": "Threshold Crossed: 1 datapoint [2.0 (29/11/17 01:09:00)] was greater than or equal to the threshold (1.0).",
"StateChangeTime": "2017-11-29T01:10:32.907+0000",
"Region": "Asia Pacific (Tokyo)",
"OldStateValue": "OK",
"Trigger": {
"MetricName": "sample-metric",
"Namespace": "LogMetrics",
"StatisticType": "Statistic",
"Statistic": "SUM",
"Unit": null,
"Dimensions": [],
"Period": 60,
"EvaluationPeriods": 1,
"ComparisonOperator": "GreaterThanOrEqualToThreshold",
"Threshold": 1,
"TreatMissingData": "- TreatMissingData: NonBreaching",
"EvaluateLowSampleCountPercentile": ""
}
}
※ サンプルのJSONデータは、https://qiita.com/onooooo/items/f59c69e30dc5b477f9fd を参考にさせていただきました。
Google Chat での確認
Google Chat に以下のような形で、通知を取得することができました。
#まとめ
AWS CDK を利用して SNS トピックの作成 および、lambda リソースの作成を行い、 SNS のテストトピックを発行し、 Google Chatに通知が来るまでを確認してみました。普段 Google Chat を利用されている方は、AWSリソースに何か生じた際にすぐ通知が来てくれるので便利だと思います。