ElastiCacheのイベントをDatadogやLambdaを使ってSlack通知
はじめに
Amazon ElastiCacheでは再起動やフェイルオーバーが発生すると、イベントとして記録されます。
マネジメントコンソールでは、ElastiCache > イベント
で以下の通り、記録されたイベントを確認できます。
こうしたElastiCacheに関するイベントをSlackに通知する方法について、色々と試したので記載します。
Slack通知方法
今回、試した方法は以下の4つです。
方法 | コメント |
---|---|
DatadogのAWS Integration -> Datadog Monitor -> Slack | 通知までに数分時間がかかる |
ElastiCache -> SNS -> Datadog Monitor -> Slack | - DatadogのAPIキーの扱いに難あり - イベントをフィルタできない |
ElastiCache -> SNS -> Chatbot -> Slack | そもそも通知不可 |
ElastiCache -> SNS -> Lambda -> Slack | - 即時に通知可 - イベントのフィルタが可能 |
監視全般をDatadogで行なっていることを前提とし、前半の2つの方法では極力Datadogに情報を集約しようとしています。
後半の2つの方法ではDatadog集約にこだわらずにSlack通知する方法を試しています。
1. DatadogのAWS Integration -> Datadog Monitor -> Slack
DatadogのAWS Integrationを有効にしていると、ElastiCacheのイベントは自動的にDatadogに連携されます。
以下はDatadogで、Monitors > New Monitor > Event
と選択した時の画面ですが、ElastiCacheのイベントが表示されていることがわかります。
このようなイベントを検知してSlack通知するために、Datadogで以下の新規Monitorを作成します。
-
Match events containing
をfailover
とする -
from
をAmazon ElastiCache
とする -
tag
をsource_identifier:{ElastiCacheの名前}
とする - 通知先をSlackとする
Monitor作成後、検証として手動でElastiCacheのフェイルオーバーを発生させます。
以下は手動フェイルオーバー直後にマネジメントコンソールで確認したElastiCacheのイベントです。
そして、このフェイルオーバーイベントはDatadogのMonitorで検知され、DatadogからSlackには以下のように通知されました。
しかし、ElastiCacheのイベント発生時刻(23:43)とSlackの投稿日時(23:51)を比較するとわかりますが、Slack通知されたのは、フェイルオーバー発生から約8分後でした。
DatadogのAWS Integrationでは、確かにElastiCacheのイベントが自動連携されるのですが、Datadog側への反映には数分の時間がかかるようです。
そのため、DatadogのMonitorによる検知もその分だけ遅れ、結果としてSlack通知のタイミングもフェイルオーバー発生から数分経過後となってしまいました。
2. ElastiCache -> SNS -> Datadog Monitor -> Slack
ElastiCacheでは連携先のSNSトピックを指定することが可能であり、SNSを介してイベントを様々な先に通知できます。
ここではElastiCacheの連携先SNSの通知先をDatadogのエンドポイントとし、さらにDatadog MonitorからSlack通知してみます。
まず、スタンダードタイプのSNSトピックを作成します。
SNSトピックのアクセスポリシーは以下の通りとします。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "SNS:Publish",
"Resource": "{自身のSNSトピックARN}",
"Condition": {
"StringEquals": {
"AWS:SourceOwner": "{自身のAWSアカウントID}"
}
}
}
]
}
次にこのSNSトピックに対し、サブスクリプションを作成します。
サブスクリプションのプロトコルはHTTPSを選択し、エンドポイントはDatadogの公式ドキュメントに記載されている
https://app.datadoghq.com/intake/webhook/sns?api_key=<API KEY>
とします(DatadogのリージョンがUSの場合)。
DatadogのAPIキーは、https://app.datadoghq.com/account/settings#api より取得します。
以上により、ElastiCacheで発生したイベントがSNS経由でDatadogに反映されるようになります。
以下はDatadogで、Monitors > New Monitor > Event
と選択した時の画面ですが、ElastiCacheのイベントがSNS経由で反映されていることがわかります。
こうしたSNSによる通知をDatadogのMonitorで検知してSlack通知するために、Datadogにて以下の新規Monitorを作成します。
-
Match events containing
は空欄とする(空欄にした理由は後述) -
from
をAmazon SNS
とする -
tag
をtopic:{SNSトピックのの名前}
とする - 通知先をSlackとする
Monitor作成後、改めて検証として手動でElastiCacheのフェイルオーバーを発生させると、Datadogはこれを検知し、Slackに以下の通知を行いました。
ただ、この方法は、SNSサブスクリプションのエンドポイント欄にDatadogのAPIキーを秘匿せずに設定することとなるので、APIキーを参照可能な人間を限定したい場合には適しません。
また、今回Datadog Monitorで以下のようなJSONから特定のイベント種類だけをフィルタする方法がわかりませんでした。
{
"ElastiCache:イベント名": "ElastiCache名"
}
そのため、Match events containing
を空欄としたのですが、結果としてあらゆるElastiCacheイベントがSlack通知されることとなっており、実用性に欠けたものとなってしまっていました。
3. ElastiCache -> SNS -> Chatbot -> Slack
この経路でのSlack通知はできませんでした。
AWS Chatbotは、ElastiCacheのイベントには対応していないようで、Chatbotの部分は後述するLambdaを使う必要があります。
(もし仮にChatbotがイベントのフィルタリングも含めてElastiCacheに対応していたとすれば、Lambdaのソースコードを管理せずに済むという利点が考えられます)
4. ElastiCache -> SNS -> Lambda -> Slack
この経路では、Lambdaのソースコードを管理する必要はあるものの、特に問題なくSlack通知することができます。
以下はPythonによるLambdaのコード例です。今回、イベント種類の絞り込み処理は割愛していますが、そうしたコードを追加すれば任意のイベントのみを通知可能かと思います。
なお、SlackのWebhook URLはあらかじめパラメータストアに格納しておき、そのパラメータストアのパスは環境変数から取り出すようにしています。
import boto3
import json
import os
import urllib.request
def lambda_handler(event, context):
ssm = boto3.client('ssm')
ssm_res = ssm.get_parameter(
Name = os.environ['PARAMETER_STORE_PATH_WEBHOOK_URL'],
WithDecryption = True
)
url = ssm_res['Parameter']['Value']
data = {
'text': event['Records'][0]['Sns']['Message']
}
headers = {
'Content-Type': 'application/json',
}
req = urllib.request.Request(url, json.dumps(data).encode(), headers)
with urllib.request.urlopen(req) as res:
res_body = res.read().decode()
print(res_body)
パラメータストアを参照するので、Lambdaに割り当てられたIAMロールでは以下の権限を追加で付けるようにします。
// 略
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole",
"ssm:GetParameter"
],
"Resource": "*"
}
// 略
このコードをLambdaにデプロイ後、手動でElastiCacheのフェイルオーバーを発生させると、SNS経由で起動したLambdaはSlackに対して以下の通知を行いました。
(ひとつの通知にまとまっているように見えますが、実際は3回に分けて通知されます)
ElastiCacheのイベント欄で表示されるイベント発生時刻と比較しても、即時に通知できていることがわかります。
終わりに
以上、ElastiCacheのイベントをSlackに通知する方法複数の検証でした。
実用性の面では、最後に紹介したElastiCache -> SNS -> Lambda -> Slack
が一番良さそうです。
本記事が参考になれば幸いです。
Discussion