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


Motivation

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

AlertManagerとは

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

公式のチュートリアル

インストール

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

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']

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

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に下記のような通知が来る

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

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にてアラートを確認できる

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

試してない

参考資料類

AlertManager公式ドキュメント

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

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