この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
データアナリティクス事業本部の鈴木です。
今回はCloudWatchアラームの状態遷移が起きた際に日本語の件名・本文のメールをSNSから送信する方法を調べました。また、構成をデプロイできるようCloudFormationテンプレートを作成したのでご紹介します。
やりたかったこと
CloudWatchアラームがアラーム状態に遷移した時に、日本語の件名・本文のメールをSNSから送信したいです。
例えば以下のような通知です。
調べていたところ、以下の二つの記事がとても参考になり、組み合わせてCloudFormationテンプレートにしてみました。
構成
CloudWatchアラームがアラーム状態に遷移するイベントをEventBridgeで検知し、SNSでメール通知します。SNSをEventBridgeのターゲットに直接指定すると件名が指定できないので、Step Functionsを介して呼び出します。[2]
作成したテンプレート
今回は、SQSでデッドレターキューを運用しているとして、キューにメッセージが入った際の通知を想定します。
以下のような構成です。
分かりやすさのため、まずデッドレターキューのテンプレートを記載します。
sample-dlq.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: SQS Standard Queue
Parameters:
QueueName:
Description: Name for queue
Type: String
Resources:
################################
# イベント作成用のサンプルのリソース #
################################
## SQSキュー
SQSQueue:
Type: AWS::SQS::Queue
Properties:
MessageRetentionPeriod: 1209600
QueueName: !Sub ${QueueName}
VisibilityTimeout: 120
続いて、今回作成した通知用のテンプレートです。
email-notification.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Alarm & SNS notification
Parameters:
SNSTopicName:
Description: SNSTopicName for Alarm
Type: String
NotificateDestinationEmail:
Description: Destination Email for SNS
Type: String
QueueName:
Description: Name for queue
Type: String
Resources:
#################
# 通知用のリソース #
#################
## CloudWatch アラーム
SQSAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub ${QueueName}-alerm
ComparisonOperator: GreaterThanThreshold
DatapointsToAlarm: 1
EvaluationPeriods: 1
Threshold: 0
Namespace: AWS/SQS
Dimensions:
- Name: QueueName
Value: !Sub ${QueueName}
MetricName: ApproximateNumberOfMessagesVisible
Period: 60
Statistic: Maximum
TreatMissingData: notBreaching
## 件名カスタマイズ用のステートマシン
SNSStateMachine:
Type: "AWS::StepFunctions::StateMachine"
Properties:
DefinitionString: !Sub |-
{
"StartAt": "PublishSns",
"States": {
"PublishSns": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish",
"Parameters": {
"TopicArn": "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${SNSTopicName}",
"Message.$": "$.message",
"Subject.$": "$.subject"
},
"End": true
}
}
}
RoleArn: !GetAtt [ PublishRole, Arn ]
## SNSトピック
SnsTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: !Sub ${SNSTopicName}
Subscription:
- Endpoint: !Sub ${NotificateDestinationEmail}
Protocol: email
## EventBridge
AlarmEvent:
Type: AWS::Events::Rule
Properties:
Description: String
EventPattern: !Sub |
{
"source": ["aws.cloudwatch"],
"detail-type": ["CloudWatch Alarm State Change"],
"resources": [{"prefix": "arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:${QueueName}-alerm"}],
"detail": {"state": {"value": ["ALARM"]}}
}
Targets:
- Arn: !Ref SNSStateMachine
Id: step-function
RoleArn: !GetAtt [ StateMachineExecuteRole, Arn ]
InputTransformer:
InputPathsMap:
"Account": "$.account"
"AlarmName": "$.detail.alarmName"
"MetricsName": "$.detail.configuration.metrics[0].metricStat.metric.name"
"Reason": "$.detail.state.reason"
"Time": "$.time"
InputTemplate: |
{
"subject": "デッドレターキューにメッセージが入りました",
"message": "AWSアカウントID: \"<Account>\" \n 発生時間(GMT): \"<Time>\" \n 発生アラーム名: \"<AlarmName>\" \n 発生メトリクス: \"<MetricsName>\" \n\n 理由: \"<Reason>\""
}
# Role
PublishRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- states.amazonaws.com
Action: "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: SNSPublish
PolicyDocument:
Statement:
- Effect: Allow
Resource:
- !Ref SnsTopic
Action:
- sns:Publish
StateMachineExecuteRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- events.amazonaws.com
Action: "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: StateMachineExecute
PolicyDocument:
Statement:
- Effect: Allow
Resource:
- !Ref SNSStateMachine
Action:
- states:StartExecution
テンプレート作成時のポイントは以下になります。
- アラームの設定を修正することで、監視対象のメトリクスや状態に遷移する条件を調整することができます。今回は作成しておいたSQSのキューの
ApproximateNumberOfMessagesVisible
メトリクスを見るように設定しています。(24〜36行目) - 通知先の設定はSNS Topicの
Subscription
にて行います。今回はパラメータで渡した1つのEmailを設定するようにしています。(65〜67行目) - EventBridgeのルールの
EventPattern
で監視対象のリソースとイベント内容を指定しています。(74〜80行目) - 日本語の件名およびメッセージはEventBridgeのルールの
InputTemplate
にて設定しています。Step Functionsを挟んだ場合、本文で改行したい場合はテンプレートの文字列に\n
を入れることで改行ができました。(92〜96行目)
やってみる
1. CloudFormationでデプロイする
上記のテンプレートをCloudFormationからデプロイしておきます。
デプロイが完了すると各リソースが作成されます。また、SNSからメール通知されるアドレスに、サブスクリプションの承認依頼メールが届くので、承認しておきます。
例えば、作成したアラームは以下のようになっており、これがアラーム状態になると、EventBridge以降が稼働してメール送信までを行います。
EventBridgeのルールの画面からは、ターゲットおよび入力トランスフォーマーの設定が期待通りにできていることが分かります。
2. アラーム状態に遷移させてメール通知する
アラームをアラーム状態に遷移させて、メールが飛ぶことを確認します。
まず、作成したキューをコンソールから選択します。
メッセージを送受信
を開きます。
適当なメッセージをキューに送信しておきます。
しばらくして、アラームがアラーム状態になることを確認します。
SNSトピックに登録したメールを確認すると、通知が飛んできていることを確認できました。
最後に
今回はCloudWatchアラームの状態遷移と関連づけて日本語の件名・本文のメールをSNSから送信する方法を調べ、その構成とCloudFormationテンプレート例をご紹介しました。
実際の運用では、通知を日本語で行いたいケースが多々あると思いますが、EventBridgeルールの入力トランスフォーマーに日本語のテンプレートを設定しておき、Step Functionsを介してSNSに渡すことで簡単に日本語のメールが設定できるのはとてもよいですね。
参考になりましたら幸いです。
参考
CloudFormation以外でのデプロイ方法や、各機能の詳細も分かるので、ぜひ併せてご確認ください。