Datadogのアラート時の対応をRundeckで自動化する

# やりたかったこと
datadogのMonitorsで閾値超過時にアラートをslackに通知しているが、対応方法が決まっているものがある。
そういうものはトイルになるので、自動化したかった。

# 構成

全体の構成としては、下図のようなものになる。
DatadogでGKEをモニタリングしており、Monitorによるアラート発報時にwebhookにてRUNDECKのJOBを実行する。
なお、RUNDECKはCloudArmorにてSourceIPを制限している。

![Datadogのアラート時の対応をRundeckで自動化する (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/2c99c1bd-7c2f-8177-c290-a63a7c69cc4c.png)


# しくみを作る

## CloudArmorにDatadog webhookのSourceIPを許可する

[公式ドキュメント](https://docs.datadoghq.com/ja/api/latest/ip-ranges/)通り、datadogの各サービスのsource ipは取得できる。

```shell
curl -X GET "https://ip-ranges.datadoghq.com/" \
-H "Content-Type: application/json"
```

今回は以下のように`webhooks`のみを取得し、CloudArmorに追加しておく

```shell
curl -X GET "https://ip-ranges.datadoghq.com/" \
-H "Content-Type: application/json" \
| jq '.webhooks'
```

## rundeck側で実施するjobを作成する

取り敢えず、適当にjobを追加しておく
![スクリーンショット 2021-03-20 20.35.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/c607c6c5-6b73-1485-fa09-fadbc9cdc33e.png)

追加したjobの Workflowには 引数に `${option.raw}`を追加する。この`raw`にdatadogのアラートの詳細情報(Payload)が乗ってくる。

![スクリーンショット 2021-03-21 9.25.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/63208243-f5bf-036e-d520-63aefd742c21.png)


## rundeck側でwebhookの設定をする

以下からwebhookを追加する

![Rundeck 2021-03-20 20-31-43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/316f6c8b-a4d8-3cca-bd1c-470608e13740.png)

webhookの詳細を追加する。
先程追加したjobを指定し、
[datadogのドキュメント](https://docs.datadoghq.com/ja/integrations/rundeck/#%E3%82%B3%E3%83%B3%E3%83%95%E3%82%A3%E3%82%AE%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)にも記載されているが、`-raw ${raw} -event_type ${data.event_type}` をoptionに追加しておく。
この`raw`にdatadogのアラートの詳細情報(Payload)が乗ってくる。

![スクリーンショット 2021-03-20 20.38.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/3e5251a2-e7c3-bb68-c96b-b9a1670b32d1.png)

webhookを保存すると、Post URLが発行される。

![Rundeck 2021-03-20 20-42-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/111b3d19-a6db-b554-7010-11e0ab28fd7d.png)

## datadog側でwebhookの設定をする

Integrations -> `webhook` で検索

![スクリーンショット 2021-03-20 21.12.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/6821aaff-3459-713b-e827-1d7da3c8a0da.png)

`Webhooks Integration` の Webhooks から `+ New`

![スクリーンショット 2021-03-21 8.58.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/8fa8a12a-d5ac-7ff6-49cc-c244ca0e060b.png)

適当にNameを入れて、 URL には rundeck 側で発行された Post URL 記載する。
このPayloadに記載されたものが rundeck側で設定した raw に乗ってくる。
デフォルトでは `"alert_scope": "$ALERT_SCOPE"`が無いが、アラートの条件がほしかったので追加しておく。
その他、追加できるものは[公式ドキュメント](https://docs.datadoghq.com/ja/integrations/webhooks/#%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95)に記載されている。

![スクリーンショット 2021-03-21 10.09.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/63ee3229-164d-2965-40a4-f7abcb351ded.png)

## datadogのアラート設定

Monitors にてアラートを設定する
以下はKubernetesのPVCのディスク使用率が80%になったらアラートとしている。

![スクリーンショット 2021-03-21 10.02.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/17461b5b-e6a7-afeb-46a2-6754e4cc8482.png)


アラート時にwebhookを呼び出したいので、以下を入れておく

```
{{#is_alert}}
@webhook-test-webhook 
{{/is_alert}}
```

## アラートの確認

Test NotificationでNotificationをテストする
![Monitors | Datadog 2021-03-21 10-12-22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/da6c5826-fd84-f77f-996a-9aa63bfad40a.png)

rundeck側でjobが実行されている。

![✅ [OK] Rundeck - test-job : Execution at 1:10 AM by admin 2021-03-21 10-14-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33101/bb4d90a7-cebe-e908-7859-9698d9c1a8dd.png)

ユースケースに応じて、このPayloadからイジイジしてシェルスクリプトを作る
`alert_scope`を付加しておくと以下の感じでいじるときに便利だったから追加しておいた

```shell
echo $1 | jq 

TARGET=`echo $1 | jq '.alert_scope' | sed 's/"//g'`
echo debugging target alert_scope is ${TARGET}

# Namespaceとかpod名がどの順番で来てもいいようにしておく
NAMESPACE="hoge"
POD_NAME="fuga"
for i in $(echo $TARGET | sed "s/,/ /g")  # カンマ区切りを先ずバラす
  do 
    echo debugging for_statement index is "$i"
    if [ `echo $i | grep 'namespace:'` ] ; then # namespace名を取得する
      NAMESPACE=$(echo $i | cut -d ":" -f2)
    elif [ `echo $i | grep 'pod_name:'` ] ; then # pod名を取得する
      POD_NAME=$(echo $i | cut -d ":" -f2)
    fi

 done

echo The target namespace is $NAMESPACE
echo The target pod_name is $POD_NAME 

sudo gcloud container clusters get-credentials クラスタ名 --zone asia-northeast1-a --project プロジェクト名
sleep 2
sudo kubectl exec pod -n $NAMESPACE $POD_NAME -- やりたい処理

```