[Datadog]IntegrationがないツールでもDatadogからアラート通知したい


はじめに

こんにちは、なじむです。
今回はこれまでのCFnの記事からは離れて、Datadog Advent Calendar 2019の12/20(金)分の記事です。DatadogにはたくさんのIntegrationがありますが、たまに無いものもあります。「えーイベントの通知は全部Datadogでやりたい」という時に使えるかもしれない「なんちゃってIntegration」です。今回はコンテナセキュリティツールであるSysdigを使用します。

やりたいこと

障害発生時の運用として以下を考えていました。

障害発生時に確認するサイト(ダッシュボード)はDatadogに一本化したい!

いくつかの監視ツールを使用していると「ホスト障害の時はDatadogを見る」、「コンテナ障害の時はSysdigを見る」というように障害の起きた個所で見るべきサイトが異なってしまう場合があります。その運用だと負荷が高くなったり(特に夜間の寝ぼけた時はミスしやすい…)、後でイベントの一覧を見るときに見るべきサイトを間違えたりするため、最初に見るべきサイトはDatadogに統一したいと考えました。

前提

以下の環境を想定しています。

  • DatadogでSNS Integrationを有効にしていること
  • アラートを検知した場合の通知先(今回はSysdigの通知先)でSNSが使用できること

実装の流れ

通知までの大きな流れとしては以下です(絵を描けば良かった…)

  1. Sysdigでアラート発生→SNSにアラートを通知
  2. SNSでDatadogのイベントを作成
  3. 作成されたイベントを基にDatadogのMonitorをトリガー→メールやチャットに通知

実装方法

今回の肝は「SNSでDatadogのイベントを作成」のため、その方法を書いていきます。やり方は2つ考えました。SNS Integrationを使用した簡易な方法と、Lambdaを使用した柔軟な通知が行う方法です。

  1. SNS Integrationを使用する方法
  2. Lamdbdaを使用する方法

SNS Integrationを使用する方法

この方法はとても簡単で、以下の手順を実施すれば実現可能です。

  1. SNSトピックを作成する(参考:Sysdig公式
  2. SNSサブスクリプションを作成する(参考:Datadog公式

サンプルコード(CloudFormation)

ではいつも通りCloudFormationでSNSを設定していきます。

---
AWSTemplateFormatVersion: 2010-09-09
Description: SNS - post Datadog event from sysdig

#------------------------------
# Parameters: Set your argv.
#------------------------------
Parameters:
  DatadogWebhookURL:
    Type: String
    Description: Datadog webhook URL (ex. https://app.datadoghq.com/intake/webhook/sns?api_key=xxxxxxxxx)

#------------------------------
# Resources: Your resource list
#------------------------------
Resources:
  # SNS Resource
  ## Topic
  SNSTopic:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: sysdig2datadog # ここは任意の名前に変更してください
      Subscription:
      - Endpoint: !Ref DatadogWebhookURL
        Protocol: https
      TopicName: sysdig2datadog # ここは任意の名前に変更してください

  ## TopicPolicy
  SNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        {
          "Version": "2008-10-17",
          "Id": "__default_policy_ID",
          "Statement": [
            {
              "Sid": "__default_statement_ID",
              "Effect": "Allow",
              "Principal": {
                "AWS": "*"
              },
              "Action": [
                "SNS:GetTopicAttributes",
                "SNS:SetTopicAttributes",
                "SNS:AddPermission",
                "SNS:RemovePermission",
                "SNS:DeleteTopic",
                "SNS:Subscribe",
                "SNS:ListSubscriptionsByTopic",
                "SNS:Publish",
                "SNS:Receive"
              ],
              "Resource": {"Ref": "SNSTopic"},
              "Condition": {
                "StringEquals": {
                  "AWS:SourceOwner": {"Ref": "AWS::AccountId"}
                }
              }
            },
            {
              "Sid": "__console_pub_0",
              "Effect": "Allow",
              "Principal": {
                "AWS": [
                  "273107874544"
                ]
              },
              "Action": "SNS:Publish",
              "Resource": {"Ref": "SNSTopic"}
            }
          ]
        }
      Topics: 
      - !Ref SNSTopic

実行結果

SNSトピック、SNSサブスクリプションができました。

動作確認

実際にSysdigでアラートを検知して、それがDatadogで表示されるかを確認してみましょう。

  1. Sysdigでアラートを出力する
    Sysdigにはテストアラートを発生させる機能があるので、今回はこの機能を使用してテストアラートをSNSに通知します。

  2. Datadog側で正常にアラートを受け取ったことを確認。めでたし!

Lamdbdaを使用する方法

メッセージ内容をより詳細にカスタマイズしたい場合はhttps(webhook)ではなく、Lambdaを使用してカスタマイズしてください。Lambdaを使用すると細かいパラメータ(アラートタイプや件名、メッセージの内容等)が指定できるのがとても良いです。

サンプルコード(lambda)

簡単なコード(python3)としては以下のようになります。APIKEYなどはLambdaの環境変数から引っ張ってきています。

from datadog import initialize, api
import os

APIKEY = os.environ['APIKey']
APPKEY = os.environ['APPKey']

options = {
  'api_key': APIKEY,
  'app_key': APPKEY
}

initialize(**options)

def lambda_handler(event, context):
  title      = event['Records'][0]['Sns']['Subject']
  text       = event['Records'][0]['Sns']['Message']
  alert_type = 'error'
  tags       = ['source:sysdig']

  api.Event.create(title=title, text=text, alert_type=alert_type, tags=tags)

まとめ

「何かあったら先ずはDatadogを見る!」とした場合、Integrationがない時は自分でイベントを作成して通知できるよ、という記事でした。
DatadogはIntegrationが豊富で、機能もどんどん追加されています。そして何といっても安い。Freeプランもあるため、個人で触ってみるのが気軽にできるのも良いですね。
書いた後で、SNSじゃなくてもDatadogのAPIが叩ければ良いので「SNSが使用できること」が前提じゃなくても良いよなぁと思いました。ただ、お手軽に実装する場合はSNS Integrationを使うと楽かなと思います。
何かの参考になれば幸いですノシ