Prometheusの裏にいるAlertManagerでTeamsにメッセージ送ってみる

# Motivation
Kubernetesを用いる際の監視ツールのデファクトとしてPrometheusがあるが、
Prometheusからアラートを飛ばす際にはAlertManagerというツールが動いている。
このAlertManagerの設定方法について調査し、Teamsに通知を飛ばしてみる。

# AlertManagerとは
Prometheusの裏で使われる、アラート管理・通知用のツールである。
Prometheusからアラートを受け取り、そのアラートについてsilencing(消音), inhibition(抑制), aggregation(集約)などを施した上で、Slackやメールなどに通知を送ることができる。


# 公式のチュートリアル

## インストール

下記サイトからビルド済みバイナリを取得

https://prometheus.io/download/

macの場合

```
wget https://github.com/prometheus/alertmanager/releases/download/v0.20.0/alertmanager-0.20.0.darwin-amd64.tar.gz
tar xzvf alertmanager-0.20.0.darwin-amd64.tar.gz
```





## 設定

デフォルトの設定

```
❯ cat alertmanager.yml 
global:
  resolve_timeout: 5m

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h
  receiver: 'web.hook'
receivers:
- name: 'web.hook'
  webhook_configs:
  - url: 'http://127.0.0.1:5001/'
inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'dev', 'instance']
```



メールに送るときの設定例

https://github.com/prometheus/alertmanager/blob/master/doc/examples/simple.yml



Slackに送る際の設定例

~~CHANNEL_NAME部分を送り先のSlackチャネルに変更~~
SlackのWebhook URLがそもそもチャネルに紐づいて作成されるため、URLを指定することで宛先が一意に特定される
そのため、CHANNEL_NAMEを指定するような下記の設定はではなく

```:間違った設定例
❯ cat alertmanager.yml
global:
  slack_api_url: '<SLACK_URL>'

route:
  receiver: 'slack'

receivers:
  - name: 'slack'
    slack_configs:
    - channel: '#<CHANNEL_NAME>'
```

以下のような設定をすることでSlackへWebhookが可能
また、複数の宛先を柔軟に増やしていくために、routes内で宛先ごとにどんなラベルを持つアラートを受信するか、を設定


```:設定例
global:
  resolve_timeout: 5m

route:
  receiver: default
  routes:
  - match:
      team: frontend
    group_by: [alertname, service]
    receiver: frontend
  - match:
      team: backend
    group_by: [alertname, service]
    receiver: backend

receivers:
- name: default
  slack_configs:
  - api_url: '<SLACK_URL>'
- name: frontend
  slack_configs:
  - api_url: '<SLACK_URL>'
- name: backend
  slack_configs:
  - api_url: '<SLACK_URL>'
```


## AlertManager起動

```
./alertmanager --config.file=alertmanager.yml
```



## Alert送信

### Slackにアラート送信

curlでダミーアラートを用意

```
❯ cat post_alert.sh  
curl http://localhost:9093/api/v1/alerts -H "Content-type: application/json" -X POST -d @- << EOF
[ 
  {
    "labels": {
      "team": "frontend",
      "alertname": "frontend error",
      "service": "myservice",
      "instance": "node1"
    },
    "annotations": {
      "summary": "寿司食べたい"
    },
    "generatorURL": "http://where-this-alert-from.local"
  }
]
EOF
```



ダミーアラートを発行

```
❯ sh post_alert.sh  
{"status":"success"}
```

Slackに下記のような通知が来る

<img width="942" alt="dummy_alert.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94861/bee096e6-c2ff-4a4e-fc23-317d83d04a7e.png">




リンクをクリックするとAlertManagerのUI上でアラートを確認できる

<img width="1426" alt="dummy_alert2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94861/28fab141-7158-db1d-227d-90685dcb6a2e.png">


### amtoolを使ったAlertの確認

下記のようにCLI経由でもアラートを確認することが可能

amtoolはalertmanagerバイナリと同じディレクトリに同梱されている

```
❯ amtool alert    
Labels                                Annotations       Starts At                Ends At                  Generator URL                       
alertname="重大なアラート" instance="node1"  summary="寿司食べたい"  2020-04-10 21:03:09 JST  2020-04-10 21:08:09 JST  http://where-this-alert-from.local  
```

### amtoolの設定

下記のようにreceiverやalertmanager.urlを指定することで、アラートの送り先を決定している

```
❯ cat $HOME/.config/amtool/config.yml 
# Define the path that `amtool` can find your `alertmanager` instance at alertmanager.url: "http://localhost:9093"

# Force amtool to give you an error if you don't include a comment on a silence
comment_required: true

# Set a default output format. (unset defaults to simple)
output: extended

# Set a default receiver
receiver: slack

alertmanager.url: http://localhost:9093
```

alertmanager.urlが指定されていない場合は、コマンドラインオプションとして指定するよう求められる

```
❯ amtool alert                        
amtool: error: required flag --alertmanager.url not provided
```



# 



# PrometheusアラートをTeamsに送信する方法

## prometheusの通知先にTeamsは存在しない

そのため、Prometheusのアラート形式をTeamsのCard形式に変換するサーバを中継することでこれを実現する



下記のリポジトリのprometheus-msteamsを利用する

```
https://github.com/bzon/prometheus-msteams
```



## TeamsエンドポイントをTeamsで作成しておく

こんな感じのやつ

```
https://outlook.office.com/webhook/XXXXXXXXXXXXXXXXXXXXX
```



## Prometheus-msteamsを実行

TEAMS_ENDPOINT部分を、先ほど控えたものに変更する

```
docker run -d -p 2000:2000 \
    --name="promteams" \
    -e TEAMS_INCOMING_WEBHOOK_URL="<TEAMS_ENDPOINT>" \
    -e TEAMS_REQUEST_URI=alertmanager \
    quay.io/prometheusmsteams/prometheus-msteams
```



## AlertManagerの通知先にmsteamsを加える

Alertmanager.yamlに下記のreceiverを追記

```
route:
  group_by: ['alertname']
  group_interval: 30s
  repeat_interval: 30s
  group_wait: 30s
  receiver: 'prometheus-msteams'

receivers:
- name: 'prometheus-msteams'
  webhook_configs: # https://prometheus.io/docs/alerting/configuration/#webhook_config 
  - send_resolved: true
    url: 'http://localhost:2000/alertmanager' # the prometheus-msteams proxy
```



amtoolのエンドポイントも変更しておく

```
❯ cat ~/.config/amtool/config.yml
# Define the path that `amtool` can find your `alertmanager` instance at alertmanager.url: "http://localhost:9093"

# Force amtool to give you an error if you don't include a comment on a silence
comment_required: true

# Set a default output format. (unset defaults to simple)
output: extended

# Set a default receiver
receiver: prometheus-msteams
alertmanager.url: http://localhost:9093
```



ダミーアラート送信

```
❯ sh post_alert.sh 
{"status":"success"}
```



Teamsにてアラートを確認できる

![teams_alert.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94861/97a8805d-6d5e-245a-1e8f-2f6236511fc9.png)




## 設定次第では、複数エンドポイントに送信できるらしい
試してない

https://lapee79.github.io/en/article/prometheus-alertmanager-with-msteams/



# 参考資料類



## AlertManager公式ドキュメント

https://prometheus.io/docs/alerting/overview/





## curlからAlertManagerにアクセスしてアラートを発生させる方法

https://www.techscore.com/blog/2017/12/18/prometheus-alermanager-api/



## alert manager用のCLIツール amtoolの紹介

https://qiita.com/sugitak/items/49f5cd93628564ac88f7