初めに
こんにちは.自分ごとですが,最近AlertManagerを触る機会が多かったのですが,その際にアラートのグループ化とその方法について学んだのでまとめておきます.他の記事を見ても実際に通知されたアラートを交えながら話している人少ないので,誰かの助けになるといいです!
Alertのグループ化とは?
今回はAlertを通知するための専用コンポーネントである,AlertManagerを用いて解説しますね.グループ化とは通知されたアラートをまとめる設定のことを言います.これだけ聞くと何を言っているのかよくわからないと思いますので例を出して説明します.
例えば,監視対象としてAからDがあるとします.Blackbox exporterはAからDに対してICMPの疎通確認の監視を行います.PrometheusはBlackbox exporterから監視結果を取得します.監視対象AからDが何かしらの影響で疎通確認できない場合,Prometheusがアラートを出し,それをAlertManagerに通知するように依頼します.
ここでAlertManagerの出番です.通知されたアラートはグループ化なしの場合,1件の通知にまとまって通知されます.また,グループ化している場合,監視対象AとB,監視対象CとDごとに分けることができます.
あとは実行例と設定をそれぞれ見てみましょう.
環境
今回は以下の構成で環境を作成します.監視対象と監視サーバを含めて合計6台です.
監視対象(Kubernetesクラスタ)
- Master
- CPU(4GB)
- Memory(4GB)
- Storage(30GB)
- Worker(1~3)
- CPU(4GB)
- Memory(4GB)
- Storage(30GB)
監視サーバ(Kubernetesクラスタ)
- Master
- CPU(4GB)
- Memory(4GB)
- Storage(30GB)
- Worker(1~3)
- CPU(4GB)
- Memory(4GB)
- Storage(30GB)
ソフトウェア
- AlertManager
- Prometheus
- Blackbox-exporter
設定
以下に設定項目は全て載せておきます.
https://github.com/cdsl-research/Prometheus-tmp-cdsl
まずはどの監視対象を監視するかの設定です.
prometheus-configmap2.yaml
- job_name: 'ICMP-Black-box-test1'
scrape_interval: 1m
metrics_path: /probe
params:
module: [icmp]
static_configs:
- targets:
- outside-prometheus-ml5
- outside-prometheus-wc1
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: monitoring-master-ml:30000
- job_name: 'ICMP-Black-box-test2'
scrape_interval: 1m
metrics_path: /probe
params:
module: [icmp]
static_configs:
- targets:
- outside-prometheus-wc2
- outside-prometheus-wc3
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: monitoring-master-ml:30000
こんな感じで設定します.あとはPrometheusでアラートを出す設定です.
test-alert.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: test-alert-rule
namespace: monitoring
data:
test-alert.yml: |-
groups:
- name: Traffic-Check
rules:
### ICMP
- alert: ICMP-Check
annotations:
description: "Instance {{$labels.instance}}"
runbook_url: https://runbooks.prometheus-operator.dev/runbooks/alertmanager/alertmanagerfailedreload
summary: "ICMP not connect"
expr: probe_success{job=~"ICMP-Black-box-test1|ICMP-Black-box-test2"}
for: 3m
labels:
severity: critical
今回はテストでアラートを出すだけなので,exprの部分はprobe_successだけ入れて比較演算子入れません.
これで準備完了です.あとは,アラートを分割するだけです.
通知の仕方を変更してみる
AlertManagerの設定は以下のようにしておきましょう.
alertmanager-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: alertmanager
data:
config.yml: |-
global:
resolve_timeout: 1m
slack_api_url: https://hooks.slack.com/services/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
inhibit_rules:
- equal:
- namespace
- alertname
source_matchers:
- severity = critical
target_matchers:
- severity =~ warning|info|attention
- equal:
- namespace
- alertname
source_matchers:
- severity = warning
target_matchers:
- severity = info
- equal:
- namespace
source_matchers:
- alertname = InfoInhibitor
target_matchers:
- severity = info
- target_matchers:
- alertname = InfoInhibitor
receivers:
- name: "null"
- name: slack
slack_configs:
- channel: '#monitoring-alert-v2' # 通知を送信するSlackのチャンネル
send_resolved: true
text: |-
{{ range .Alerts }}
*アラート:* {{ .Labels.alertname }}
*概要:* {{ if .Annotations.summary }}{{ .Annotations.summary }}{{ else }}概要なし{{ end }}
*ランブック:* {{ if .Annotations.runbook_url }}{{ .Annotations.runbook_url }}{{ else }}https://github.com/prometheus-operator/runbooks/{{ end }}
*重大度:* {{ .Labels.severity }}
*詳細情報:*
• *alertname:* {{ .Labels.alertname }}
• *instance:* {{ if .Labels.instance }}{{ .Labels.instance }}{{ else }}N/A{{ end }}
• *job:* {{ if .Labels.job }}{{ .Labels.job }}{{ else }}N/A{{ end }}
• *description:* {{ if .Annotations.description }}{{ .Annotations.description }}{{ else }}説明なし{{ end }}
{{ end }}
title: '[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] 監視イベント通知'
route:
group_interval: 3m
group_wait: 3m
group_by:
#- alertname # 'alertname'でグループ化
#- instance # 'instance'でもグループ化
#- severity
#- job
repeat_interval: 12h
receiver: "slack" # デフォルトレシーバを "slack" に設定
routes:
- match:
alertname: DeadMansSwitch
receiver: "null"
- receiver: slack # Slackへの通知
continue: true # Slackへ通知後も続行しない
ここで大事になるのがgroup_byの設定です.これを使うと何によってアラートを分割して通知するかを設定できます.
では,ここに何も入れない上記の設定では何が通知されるでしょう?
答えはこうです.1件のアラート通知に全ての対象がまとめて入っています.
でもこれではみにくいですよね.ではこうしてみましょう.
group_by:
#- alertname # 'alertname'でグループ化
#- instance # 'instance'でもグループ化
#- severity
- job
Jobごとにグループ化するとどうなるでしょうか?
こんな感じでアラートが2つのJobに分かれて通知されています.これを使うとアラートを見やすくすることができますね.
最後に
アラートの通知は障害発生時に発生箇所を特定することの手助けになりますが,逆に多くなってしまうとどの対象からアラートが通知されているかわからない原因になってしまいます.それを避けるためにもこのようなグループ化の設定を入れて普段から分けておくといいと思います.勉強中なので今後も発信していきます.