vague memory

うろ覚えを無くしていこうともがき苦しむ人の備忘録

Datadog Monitor から Webhook で Lambda 起動

f:id:htnosm:20170219061829p:plain

前回 Datadog から SNS 経由で Lambda Function を起動を行いました。

別の方法を探してみた所、Webhook Integration が使えそうだったので試してみました。

1) API Gateway と Lambda Function を作成

API Gateway を trigger として Lambda Function を作成します。APIへは AccessKey認証 とします。

f:id:htnosm:20170219061830p:plain f:id:htnosm:20170220065001p:plain

今回使用した Lambda Function は、受け取った内容をそのまま Slack へポストするだけの物です。

2) CloudFront Distribution 作成

API Gateway の Endpoint をそのまま叩けば良いかと考えたのですが、Datadog の Webhook が SSLv3 を使用しているようで以下のようなエラーが発生します。

f:id:htnosm:20170219061832p:plain

Datadog 側での設定変更は無いようだったので、CloudFront を挟む事で回避させます。

Origin Domain Name へ API GatewayInvoke URL を入力します。 (Origin Path、Origin ID は自動的に入力されます。)

f:id:htnosm:20170219061833p:plain

また、AccessKey認証のため WhiteList Headers に x-api-key を設定します。

f:id:htnosm:20170219061834p:plain

3) Datadog Webhook Integration 設定

Integration → Webhooks → Configuration に CloudFrontのエンドポイントと API GatewayAPI Key を設定します。

f:id:htnosm:20170219061836p:plain

正常に登録できていれば、Monitor の Nortify 設定で Webhook: 〜 が選択できるようになります。

f:id:htnosm:20170219061835p:plain

実行例

Datadogのアラート発行をトリガーに、Lambda Function が起動した事を確認できます。

  • Lambda Function Log

f:id:htnosm:20170219061837p:plain

  • Slack

f:id:htnosm:20170219061838p:plain


CloudFront を介す必要がありますが、 メッセージのカスタマイズもある程度可能なため、 SNSでの通知より柔軟に処理設定できるのではないでしょうか。

Datadog MonitorからSNS経由でLambda起動

Datadog から SNS(Amazon Simple Notification Service) への通知ができるということで、 Datadog → SNS → Lambda → Slack で通知情報に+αで情報付与をしてみます。

f:id:htnosm:20170218155648p:plain

題材

Lambda で実行可能な物でしたら何でも良いのですが、常々不便を感じていた CloudFront のエラー通知で試してみました。

CloudFront で ErrorRate 上昇時に Datadog から Slack へ通知します。 これは Datadog の通常の機能(Metric Monitor)で実現できます。ですが、CloudFront の Tag は取得していないようで通知メッセージには DistributionId しか出力されません。

f:id:htnosm:20170218155640p:plain

DistributionId で判別するのは中々敷居が高いので CNAME と OriginName を後追いで付与します。

1) Monitor 通知先の作成

通知先として使用する Slack と SNS の設定です。
Datadog の Integration ページの Configuration 記載内容に沿って各種設定を行います。

1-1) Slack

Incoming WebHook を作成します。

Datadog 側への設定に Webhook URL が必要になりますので、Slack の Configure Apps に追加します。

f:id:htnosm:20170218155641p:plain f:id:htnosm:20170218155642p:plain

1-2) SNS

使用する SNS Topic を作成します。

例では dd-alert という名前で作成しました。

f:id:htnosm:20170218155643p:plain

通知先設定の確認

正常に登録できていれば Datadog の Monitor 作成画面で選択可能になります。

f:id:htnosm:20170218155644p:plain

2) Datadog Monitor の作成

Lambdaの関数を起動するトリガーとする Monitor を作成します。
例では 5xx Error Rate のメトリクスを使用しました。 尚、5xx Error Rate 等の未発生のメトリクスは Edit で選択できないので、初回は直接 Source に書く必要があるかもしれません。

通知先として作成した Slack Incoming WebHook と SNS topic の2つを指定します。

f:id:htnosm:20170218155645p:plain

avg(last_15m):max:aws.cloudfront.5xx_error_rate{*} by {distributionid} > 10
5xx Error Rate over {{#is_alert}}{{threshold}}%{{/is_alert}}{{#is_warning}}{{warn_threshold}}%{{/is_warning}}
{{^is_recovery}} @slack-notice @sns-dd-alert {{/is_recovery}}

3) Lamdba Function の作成

アラート通知が発生した際に実行したい関数を作成します。 Slack通知がメインとなるため cloudwatch-alarm-to-slack-python をベースに作成しました。 IAM role へは CloudFrontReadOnlyAccess を付与しています。

f:id:htnosm:20170218155646p:plain

Environment variables に作成した Slack Incoming WebHook と SNS topic を設定します。

f:id:htnosm:20170218155647p:plain

例ではSNSを受け取り、通知された DistributionId を基に CNAME と OriginDomainName を取得します。

実行例

アラート発生した場合に通知される内容の例です。 タイミングにより通知される順序は前後します。

f:id:htnosm:20170218165648p:plain

f:id:htnosm:20170218165647p:plain


今回題材にした CloudFront の名称取得はその内 Datadog 側で対応してくれそうですが、
アラート受けてから別に確認していた情報を付与、実行していた処理を自動実行させる等、 色々と応用が効きそうです。

Datadog Monitorで復旧通知を行わない方法

DatadogのMonitorでの通知設定で復旧(Recovery)通知を行わない方法です。

f:id:htnosm:20160121024220j:plain

template variables 内に通知先を設定する

f:id:htnosm:20160121024221p:plain

通知先を含めて {{#is_alert}}{{/is_alert}} もしくは {{^is_recovery}}{{/is_recovery}} 内に記載 します。

言われてみればなるほどなのですが、しばらくこの発想に至らず、復旧通知は必須なのかと誤解していました。
以下誤解していた理由(言い訳)です。

例文を見ただけではわからなかった

f:id:htnosm:20160121024223p:plain

初期表示状態の例文を見て、 {{#is_alert}}|{{#is_recovery}}を使って、異常時と復旧時の通知メッセージを変える物と認識しました。 (そのような使い方ももちろん可能です)

通知先指定時に末尾に設定される

f:id:htnosm:20160121024222p:plain

このような感じで(3)のアラート文面を書いた後に(4)の通知先を設定すると、アラート文面の末尾に通知先が追記されます。

f:id:htnosm:20160121024219p:plain

そのため、変数({{#is_alert}}{{/is_alert}}など)の中に通知先を入れられると考えませんでした。

尚、ドキュメント内にも通知先をtemplate variables内に設定する例はありませんでした。


■い頭は●くしないといけないと思いました。

AWS RDSイベント通知を受け取る

追記

よく質問されるので追記。

DatadogにはAWSで発生したイベントを拾ってくれる機能がありますが、RDSのイベントは含まれていません。

投稿時点の話で、現在はRDSイベントもDatadog上で取得できます。 f:id:htnosm:20180304095322p:plain


RDSのイベント通知機能としてEvent Subscriptionがあり、イベント発生時に任意のメールアドレスに通知ができます。

f:id:htnosm:20151122161333p:plain

メールのアラート受信は埋もれやすいので、DatadogとSlackへ通知します。
基本的にはメール送信による投稿が可能なサービスへの連携が可能と思います。

目次


RDSイベント通知

設定すると以下の様なFailover等のイベント発生時に設定したメールアドレス宛に通知してくれます。

f:id:htnosm:20151122152043p:plain

RDSイベント通知設定

f:id:htnosm:20151122152044p:plain

AWSマネジメントコンソールのRDSダッシュボードから EventSubscription -> CreateEventSubscription

f:id:htnosm:20151122152045p:plain

  • Name
    • イベント通知名称
    • ちなみにアンダースコア(_)は使用不可
  • Send notifications to

"create topic"リンククリックで、メールアドレスを入力できるようになるので、通知したい宛先を入力します。
Datadog、Slackへの通知に使用するメールアドレス取得方法は後述します。

f:id:htnosm:20151122152046p:plain

Datadogへ通知

DatadogにはAWSで発生したイベントを拾ってくれる機能がありますが、 RDSのイベントは含まれていません。

f:id:htnosm:20151122152052p:plain

Datadogにメールによる投稿を行うことで、Eventsへ出力させます。

Datadogメールアドレス払い出し

Integrations -> APIs

f:id:htnosm:20151122152047p:plain

Create API Email

f:id:htnosm:20151122152048p:plain

メールアドレス(event-XXXXX@dtdg.co)が払い出されます。

Datadog上でConfirm

RDSイベント通知設定にメールアドレスを登録するとConfirmationのメールが届きます。
Datadogの場合はEvents画面上で参照できます。

f:id:htnosm:20151122152049p:plain

Confirm subscriptionのリンクをクリックし、認証を完了します。

f:id:htnosm:20151122152050p:plain

イベント発生時には以下の様なメッセージが通知されます。

f:id:htnosm:20151122152051p:plain

Slackへ通知

Slackメールアドレス払い出し

Integrations -> Email

f:id:htnosm:20151122152053p:plain

Create an Email Integration

f:id:htnosm:20151122152054p:plain

メールアドレス(xxxxx@XXXXX.slack.com)が払い出されます。
投稿したいチャンネル、アイコン等を設定します。

f:id:htnosm:20151122152055p:plain

Slack上でConfirm

RDSイベント通知設定にメールアドレスを登録するとConfirmationのメールが届きます。
Slackの場合は以下のようなメッセージが届きます。

f:id:htnosm:20151122152056p:plain

Confirm subscriptionのリンクをクリックし、認証を完了すると、以下の様なメッセージが通知されます。

f:id:htnosm:20151122152057p:plain


まとめ

クリティカルなイベントは標準でアカウント宛に通知してくれても良いのではと思いました。
まだまだ根強いですが、Eメールでアラート受信の運用は止めたいです。

以下、余談です。 DatadogにEventをトリガーにアラート通知する機能があります。が、
フィルタが正常に起動しなかったり、1分単位で発生したイベントを掴めなかったりと、現時点では少々挙動が怪しいです。
サポートさんへissueを挙げてますので修正されることを期待します。

Datadog からデータ出力を試してみる

モニタリングクラウドサービス Datadog からメトリクス(データ)を取得して、テキスト出力をしてみます。 値の一覧を見る画面は用意されていませんのでAPIを使用します。

シェルスクリプト(sh)での例文が出ているのでそちらを使用します。その他にPython,Rubyのリファレンスが記載されています。

Application/API Key の取得

メニューからAPIsをクリック→API発行画面でApplicationKeyを発行できます。

f:id:htnosm:20150924015840p:plain f:id:htnosm:20150924015849p:plain

クエリストリングの取得

データ取得用のqueryが必要になるので、既存グラフから拝借します。 今回はDatadogAgentで取得できるnginxのrequest_per_sの値を取得します。

f:id:htnosm:20150924020234p:plain

グラフのJSONの"q"部分をパラメータとして使用します。

      "q": "max:nginx.net.request_per_s{example} by {name}",

データ値一覧の取得

Referenceページの QUERY TIME SERIES POINTS を使用します。

  • from/to はUNIXTIMEで指定
  • queryにJSONから取得した"q"の内容(半角スペースを除外)を指定
#!/bin/sh

api_key=取得したAPIキー
app_key=取得したアプリケーションキー
to_time=$(date +%s) # UNIXTIME指定
from_time=$(date -v -20M +%s) # UNIXTIME指定

curl -G \
    "https://app.datadoghq.com/api/v1/query" \
    -d "api_key=${api_key}" \
    -d "application_key=${app_key}" \
    -d "from=${from_time}" \
    -d "to=${to_time}" \
    -d "query=max:nginx.net.request_per_s{example}by{name}"
  • 出力例

日時と値がタイムスタンプ(UNIXTIME)順に出力されます。

{"status": "ok", "res_type": "time_series", "series": [{"metric": "nginx.net.request_per_s", "attributes": {}, "display_name": "nginx.net.request_per_s", "unit": [null, null], "pointlist": [[1442528400000.0, 0.21052631735801697], [1442528410000.0, 0.21052631735801697],
・・・略・・・
[1442529580000.0, 23.615476608276367], [1442529590000.0, 22.850000381469727]], "end": 1442529599000, "interval": 10, "start": 1442528400000, "length": 120, "aggr": "max", "scope": "name:sververXX,example", "expression": "max:nginx.net.request_per_s{name:sververXX, example}"}], "from_date": 1442528400000, "group_by": ["name"], "to_date": 1442529600000, "query": "max:nginx.net.request_per_s{example}by{name}", "message": ""}

データ値一覧の取得(csv変換)

jqでcsv形式に変換し、時系列に並べます。上記の結果をoutput.jsonへ出力した前提です。

jq -r '.series[] | { scope: .scope ,pointlist: .pointlist[] } | [.scope ,.pointlist[0] ,.pointlist[1]] | @csv' output.json | sort -t ',' -k 1,3

うーん・・・美しくない・・・。

  • 出力例
"name:sververXX,example",1442528400000,0.21052631735801697
"name:sververXX,example",1442528410000,0.21052631735801697
"name:sververXX,example",1442528420000,0.21052631735801697
"name:sververXX,example",1442528430000,0.1875
・・・略・・・
"name:sververXX,example",1442529570000,24.380952835083008
"name:sververXX,example",1442529580000,23.615476608276367

きっと便利なツールなどが既に公開されていたりするのでしょうが、 環境を選ばないのでシェルスクリプトでの出力をとりあえず試してみました。

Datadog nginx Integration を試す

※画像と内容は一切関係ありません

dog2.jpg

Datadogのnginxインテグレーション設定を試してみます。

と言っても下記ページ通りで簡単に取得できます。

取得できるメトリクスは以下になります。

nginx.net.connections
nginx.net.reading
nginx.net.request_per_s
nginx.net.waiting
nginx.net.writing

nginx stub status 有効化

今回の環境は CentOS 6.7 に公式サイトから nginx をインストールしています。

# nginxインストール
$ sudo rpm -Uvh "http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm"
$ sudo yum install nginx
# stub_statusモジュールの導入確認
$ nginx -V |& grep http_stub_status_module 
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_spdy_module --with-cc-opt='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

設定ファイルを変更します。ローカルホストからのみアクセスを受け付けるよう設定しています。(設定箇所はお好みで)

$ sudo vi /etc/nginx/conf.d/default.conf
・・・略・・・
# nginx_status有効化(許可IPの設定)
    location /nginx_status {
        stub_status on;
        access_log  off;
        allow 127.0.0.1;
        deny  all;
    }
・・・略・・・
# nginx再起動
$ sudo service nginx restart
# nginx_status確認
$ curl http://localhost/nginx_status
Active connections: 1
server accepts handled requests
 23296 23296 23432
Reading: 0 Writing: 1 Waiting: 0

DatadogAgent nginxインテグレーション有効化

DatadogAgentは既に導入済みの前提です。exampleファイルをコピーしてnginx.yamlを作成します。(タグ付け等はお好みで)

# exampleファイルコピー
$ sudo cp -p /etc/dd-agent/conf.d/nginx.yaml.example /etc/dd-agent/conf.d/nginx.yaml 
$ sudo vi /etc/dd-agent/conf.d/apache.yaml
init_config:

instances:
  - nginx_status_url: http://localhost/nginx_status/
    tags:
       - env:production
# DatadogAgent再起動
$ sudo service datadog-agent restart

DatadogAgent再起動後にinfoで確認し、以下の様な出力があれば有効化されています。

# nginx Integration有効化確認
$ sudo service datadog-agent info
・・・略・・・
    nginx
    -----
      - instance #0 [OK]
      - Collected 7 metrics, 0 events & 2 service checks
・・・略・・・

Datadogメトリクス確認

Datadog上でメトリクスが取得できていることが確認できます。

  • Add Graph

Datadog_add_graph_nginx.png

Integration Dashboard

Datadog_IntegrationDashboards_nginx.png

NGINX-Metrics

Datadog_nginxMetrics.png

NGINX-Openview

Datadog_nginxOpenView.png


Datadog Apache Integration を試す

※画像と内容は一切関係ありません

dog.jpg

DatadogApacheインテグレーション設定を試してみます。

と言っても下記ページ通りで簡単に取得できます。留意点としてはExtendedStatusの有効化をすること位かと思います。

取得できるメトリクスは以下になります。

apache.net.bytes
apache.net.bytes_per_s
apache.net.hits
apache.net.request_per_s
apache.performance.busy_workers
apache.performance.cpu_load
apache.performance.idle_workers
apache.performance.uptime

Apache mod_status 有効化

CentOS 6.7 でrpmからインストールした場合、モジュールは既に導入済みとなっています。

$ apachectl -V
Server version: Apache/2.2.15 (Unix)
$ apachectl -M
・・・略・・・
 status_module (shared)
・・・略・・・

設定ファイルを変更します。ローカルホストからのみアクセスを受け付けるよう設定しています。

$ sudo vi /etc/httpd/conf/httpd.conf
・・・略・・・
# mod_statusモジュール読み込み
LoadModule status_module modules/mod_status.so
・・・略・・・
# ExtendedStatus有効化(コメントアウトを外す)
ExtendedStatus On
・・・略・・・
# server-status有効化(コメントアウトを外し、許可IPの設定)
<Location /server-status>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
</Location>
・・・略・・・
# Apache再起動
$ sudo service httpd restart
# server-status確認
$ curl http://localhost/server-status
<html><head>
<title>Apache Status</title>
</head><body>
<h1>Apache Server Status for localhost</h1>

<dl><dt>Server Version: Apache/2.2.15 (Unix) DAV/2 PHP/5.6.13</dt>
<dt>Server Built: Aug 24 2015 17:52:49
・・・略・・・

DatadogAgent Apacheインテグレーション有効化

DatadogAgentは既に導入済みの前提です。exampleファイルそのままの内容を使用します。(タグ付け等はお好みで)

# exampleファイルコピー
$ sudo cp -p /etc/dd-agent/conf.d/apache.yaml.example /etc/dd-agent/conf.d/apache.yaml 
$ sudo cat /etc/dd-agent/conf.d/apache.yaml
init_config:

instances:
  - apache_status_url: http://localhost/server-status?auto
    # apache_user: example_user
    # apache_password: example_password
    # tags:
    #   - optional_tag
# DatadogAgent再起動
$ sudo service datadog-agent restart

DatadogAgent再起動後にinfoで確認し、以下の様な出力があれば有効化されています。

# ApacheIntegration有効化確認
$ sudo service datadog-agent info
・・・略・・・
    apache
    ------
      - instance #0 [OK]
      - Collected 8 metrics, 0 events & 2 service checks
・・・略・・・

Datadogメトリクス確認

Datadog上でメトリクスが取得できていることが確認できます。

  • Add Graph

Datadog_add_graph.png

Integration Dashboard Apache-Openview

Datadog_IntegrationDashboards.png

Datadog_ApacheOpenView.png