- はじめに
- Prometheusアラートルールの作成
- アラートルールのテスト
- Alertmanager設定の詳細
- PagerDutyとSlackの統合
- Grafana Alertingとの比較
- Alert Fatigue防止戦略
- 失敗事例と復旧手順
- 運用時の注意事項
- 参考資料

はじめに
モニタリングシステムを構築してダッシュボードを作ったからといって、オブザーバビリティが完成するわけではない。ダッシュボードは人が能動的に確認しなければならないが、アラートはシステムが異常状態を検知したときに適切な人へ適時に通知する。真のオブザーバビリティはメトリクス収集から始まり、アラートパイプラインで完成する。
Google SRE出身のRob Ewaschukは「My Philosophy on Alerting」で2つの中心的な原則を提示している。第一に、原因(Cause)ではなく症状(Symptom)にアラートを設定せよ。ディスク使用率80%のような原因ベースのアラートより、「ユーザーリクエストのエラー率が1%を超える」のような症状ベースのアラートのほうが、実際のユーザー影響をより正確に反映する。第二に、すべてのアラートは即座の行動を引き起こさなければならない。アラートを受け取っても「あとで見ればいい」なら、そのアラートは存在する理由がない。
この記事では、Prometheusのアラートルール(Alerting Rules)作成、Alertmanagerのルーティングツリー設計、PagerDutyとSlackの統合、Alert Fatigue防止戦略まで、プロダクションのアラートパイプライン構築の全過程を扱う。
Prometheusアラートルールの作成
alerting rulesの構造
Prometheusのアラートルールは5つの主要フィールドで構成される。
- alert: アラートの一意な名前
- expr: PromQL式。結果が空ベクタでなければアラートが発生する
- for: pending状態を維持する待機時間。一時的なスパイクをフィルタリングする
- labels: アラートに追加されるラベル。severity、teamなどルーティングに使われる
- annotations: アラートの説明やRunbook URLなど、人のためのメタデータ
pending vs firing の状態遷移
アラートは3つの状態を循環する。inactiveは条件が満たされていないデフォルト状態だ。expr条件が初めて満たされるとpending状態に入り、forで指定した時間だけ継続して条件が満たされるとfiring状態へ遷移してAlertmanagerへ送信される。for期間の途中で条件が解消されると再びinactiveに戻る。
keep_firing_forの活用
Prometheus 2.42から導入された keep_firing_for フィールドは、間欠的なメトリクス(intermittent metric)に有用だ。例えばバッチジョブのメトリクスがジョブ完了後に消えるとアラートも即座に解消されるが、keep_firing_for を設定するとメトリクスが消えたあとも指定した時間だけfiring状態を維持し、オンコールエンジニアが確認する時間を確保できる。
基本のインフラアラートルール
CPU、メモリ、ディスクに対する基本のアラートルールだ。症状ベースのアラートが優先だが、インフラ資源の枯渇は依然として監視すべき主要な原因指標だ。
groups:
- name: infrastructure-alerts
interval: 30s
rules:
# CPU使用率が5分間80%以上継続
- alert: HighCpuUsage
expr: |
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
team: infra
annotations:
summary: 'CPU使用率が高い'
description: 'インスタンス {{ $labels.instance }} のCPU使用率が {{ $value | printf "%.1f" }}% です。'
runbook_url: 'https://wiki.internal/runbook/high-cpu'
# メモリ使用率が90%を超過
- alert: HighMemoryUsage
expr: |
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90
for: 5m
labels:
severity: warning
team: infra
annotations:
summary: 'メモリ使用率が高い'
description: 'インスタンス {{ $labels.instance }} のメモリ使用率が {{ $value | printf "%.1f" }}% です。'
# ディスクが24時間以内に枯渇する予測
- alert: DiskWillFillIn24Hours
expr: |
predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}[6h], 24*3600) < 0
for: 10m
labels:
severity: critical
team: infra
annotations:
summary: 'ディスクが24時間以内に枯渇する予測'
description: 'インスタンス {{ $labels.instance }} のマウントポイント {{ $labels.mountpoint }} が24時間以内に枯渇すると予測されます。'
runbook_url: 'https://wiki.internal/runbook/disk-full'
SLOベースのburn rateアラートルール
Google SRE Workbookが提案するMulti-Window Multi-Burn-Rateのアラート方式だ。エラーバジェットの消費速度(burn rate)を基準に、速い消費と遅い消費をそれぞれ検知して対応の緊急度を差別化する。
groups:
- name: slo-burn-rate-alerts
rules:
# エラー率のRecording Rule(事前計算)
- record: slo:http_error_rate:ratio_rate5m
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
- record: slo:http_error_rate:ratio_rate30m
expr: |
sum(rate(http_requests_total{status=~"5.."}[30m])) by (service)
/
sum(rate(http_requests_total[30m])) by (service)
- record: slo:http_error_rate:ratio_rate1h
expr: |
sum(rate(http_requests_total{status=~"5.."}[1h])) by (service)
/
sum(rate(http_requests_total[1h])) by (service)
- record: slo:http_error_rate:ratio_rate6h
expr: |
sum(rate(http_requests_total{status=~"5.."}[6h])) by (service)
/
sum(rate(http_requests_total[6h])) by (service)
# SLO 99.9%(エラーバジェット 0.1%)
# 速い消費: 5m/30mウィンドウ、burn rate 14.4x → 1時間以内にバジェットを消費する速度
- alert: SloHighBurnRate
expr: |
slo:http_error_rate:ratio_rate5m{service="api-gateway"} > (14.4 * 0.001)
and
slo:http_error_rate:ratio_rate30m{service="api-gateway"} > (14.4 * 0.001)
for: 2m
labels:
severity: critical
slo: 'availability'
window: 'fast'
annotations:
summary: 'SLOの速い消費を検知 - 即時対応が必要'
description: 'api-gatewayのエラーバジェットが1時間以内に消費される速度で減少しています。'
# 遅い消費: 1h/6hウィンドウ、burn rate 6x → 4時間以内にバジェットを消費する速度
- alert: SloMediumBurnRate
expr: |
slo:http_error_rate:ratio_rate1h{service="api-gateway"} > (6 * 0.001)
and
slo:http_error_rate:ratio_rate6h{service="api-gateway"} > (6 * 0.001)
for: 5m
labels:
severity: warning
slo: 'availability'
window: 'slow'
annotations:
summary: 'SLOの遅い消費を検知 - 調査が必要'
description: 'api-gatewayのエラーバジェットが4時間以内に消費される速度で減少しています。'
上記のルールで中心となるのは2つのウィンドウをAND条件で結合することだ。短いウィンドウ(5m)だけを見ると一時的なスパイクに反応し、長いウィンドウ(30m)だけを見ると検知が遅くなる。2つのウィンドウが同時に条件を満たすときだけ発火させて精度を高める。
アラートルールのテスト
promtoolを活用した単体テスト
アラートルールをプロダクションへデプロイする前に必ずテストしなければならない。promtoolは仮想の時系列データを入力し、特定の時点でアラートが期待どおり発火するかを検証する。
# alert_test.yaml
rule_files:
- infrastructure_alerts.yaml
evaluation_interval: 1m
tests:
# テスト1: CPU 80%以上が5分継続したらfiring
- interval: 1m
input_series:
- series: 'node_cpu_seconds_total{mode="idle",instance="node1:9100",cpu="0"}'
values: '0+0.15x20' # 毎分0.15秒のidle = 使用率85%
- series: 'node_cpu_seconds_total{mode="idle",instance="node1:9100",cpu="1"}'
values: '0+0.15x20'
alert_rule_test:
# 4分時点: pending状態であるべき (for: 5m 未充足)
- eval_time: 4m
alertname: HighCpuUsage
exp_alerts: []
# 6分時点: firing状態であるべき
- eval_time: 6m
alertname: HighCpuUsage
exp_alerts:
- exp_labels:
severity: warning
team: infra
instance: 'node1:9100'
exp_annotations:
summary: 'CPU使用率が高い'
# テスト2: メモリが90%未満ならアラートなし
- interval: 1m
input_series:
- series: 'node_memory_MemAvailable_bytes{instance="node1:9100"}'
values: '2147483648x10' # 2GB available
- series: 'node_memory_MemTotal_bytes{instance="node1:9100"}'
values: '8589934592x10' # 8GB total = 使用率75%
alert_rule_test:
- eval_time: 10m
alertname: HighMemoryUsage
exp_alerts: []
CI/CDでのアラートルール検証の自動化
アラートルールファイルをGitで管理し、CIパイプラインで自動検証する。構文エラー、PromQL式のエラー、テスト失敗をデプロイ前に捕捉できる。
# 構文検証
promtool check rules infrastructure_alerts.yaml
promtool check rules slo_alerts.yaml
# 単体テストの実行
promtool test rules alert_test.yaml
# Alertmanager設定の検証
amtool check-config alertmanager.yaml
# CIパイプラインの例 (GitHub Actions)
# jobs:
# validate-alerts:
# steps:
# - name: Check alert rules syntax
# run: promtool check rules rules/*.yaml
# - name: Run alert rule tests
# run: promtool test rules tests/*.yaml
# - name: Check Alertmanager config
# run: amtool check-config alertmanager.yaml
Alertmanager設定の詳細
ルーティングツリー(routing tree)の設計
Alertmanagerのルーティングはツリー構造で動作する。最上位のrouteはすべてのアラートのデフォルト受信者を定義し、下位のrouteがラベルマッチングを通じてアラートを適切なチャネルへ分岐させる。continue: true を設定するとマッチしたあとも同一レベルの次のルーティングルールを評価し続けるため、1つのアラートを複数の受信者へ届けられる。
group_by は同じラベル値を持つアラートを1つのグループにまとめる。例えば group_by: [alertname, cluster] と設定すると、同じアラート名で同じクラスタから発生したアラートが1つのアラートメッセージにまとめて配信される。これにより100個のPodで同時に発生したOOMKilledアラートが、100個の個別メッセージではなく1つのグループメッセージとして届く。
# alertmanager.yaml
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.internal:587'
smtp_from: 'alertmanager@company.com'
route:
receiver: default-slack
group_by: [alertname, cluster, namespace]
group_wait: 30s # 最初のアラート受信後、グループ化のための待機
group_interval: 5m # 既存グループに新しいアラートが追加されたときの再送間隔
repeat_interval: 4h # 同一アラートの繰り返し送信間隔
routes:
# Criticalアラート → PagerDuty (即時ページング)
- match:
severity: critical
receiver: pagerduty-critical
group_wait: 10s
repeat_interval: 1h
continue: true # Slackにも同時送信
# Criticalアラート → Slack criticalチャネル (同時送信)
- match:
severity: critical
receiver: slack-critical
# SLO関連アラート → SREチーム専用チャネル
- match_re:
alertname: '^Slo.*'
receiver: slack-sre-slo
group_by: [alertname, service]
# インフラチームのアラート
- match:
team: infra
receiver: slack-infra
group_by: [alertname, instance]
# バックエンドチームのアラート
- match:
team: backend
receiver: slack-backend
group_by: [alertname, service, namespace]
# Watchdogアラート (Alertmanagerの正常動作確認用)
- match:
alertname: Watchdog
receiver: 'null'
repeat_interval: 24h
Inhibition Rulesによる下位アラートの抑制
Inhibition Rulesは特定のアラートが発火している間、関連する下位アラートを抑制する。例えばノード自体がダウンすれば、そのノードのすべてのPodアラートは不要だ。インフラレベルの障害が発生したときに、それによって連鎖的に発生する数十個の下位アラートを抑制し、アラートの氾濫を防ぐ。
# alertmanager.yaml (inhibition section)
inhibit_rules:
# ノードダウン時に該当ノードのすべての下位アラートを抑制
- source_matchers:
- alertname = NodeDown
target_matchers:
- severity =~ "warning|info"
equal: [instance]
# クラスタレベルの障害時に個別サービスのアラートを抑制
- source_matchers:
- alertname = ClusterUnreachable
target_matchers:
- severity =~ "warning|critical"
equal: [cluster]
# Criticalがfiring中なら同一アラートのWarningを抑制
- source_matchers:
- severity = critical
target_matchers:
- severity = warning
equal: [alertname, cluster, namespace]
# 大規模障害時にSLOアラートを抑制 (インフラレベルの問題であるため)
- source_matchers:
- alertname =~ "NodeDown|ClusterUnreachable"
target_matchers:
- alertname =~ "^Slo.*"
equal: [cluster]
Silencesによるメンテナンス時のアラート停止
計画的なメンテナンス時には関連アラートを一時的に停止できる。amtool CLIまたはAlertmanager UIからSilenceを作成する。Silenceはラベルマッチャで適用範囲を指定し、有効期限を過ぎると自動的に解除される。
# amtoolでSilenceを作成 (2時間、特定クラスタのアラートを停止)
amtool silence add \
--alertmanager.url=http://alertmanager:9093 \
--author="sre-team" \
--comment="Planned maintenance: k8s cluster upgrade" \
--duration=2h \
cluster="production-us-east-1"
# 有効なSilenceの一覧確認
amtool silence query --alertmanager.url=http://alertmanager:9093
# Silenceの解除
amtool silence expire --alertmanager.url=http://alertmanager:9093 <silence-id>
PagerDutyとSlackの統合
複数受信者の設定
重大度に応じてアラートを別のチャネルへルーティングすることが中心となる。CriticalアラートはPagerDutyを通じてオンコールエンジニアへ即座にページングし、WarningアラートはSlackチャネルへ届けて勤務時間内に調査させる。
# alertmanager.yaml (receivers section)
receivers:
# デフォルト受信者: Slack generalチャネル
- name: default-slack
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00/B00/XXXXX'
channel: '#alerts-general'
send_resolved: true
title: '{{ if eq .Status "firing" }}FIRING{{ else }}RESOLVED{{ end }} - {{ .CommonLabels.alertname }}'
text: >-
*Severity:* {{ .CommonLabels.severity | toUpper }}
*Cluster:* {{ .CommonLabels.cluster }}
*Namespace:* {{ .CommonLabels.namespace }}
{{ range .Alerts }}
- *{{ .Labels.instance }}*: {{ .Annotations.description }}
{{ end }}
# PagerDuty Critical受信者
- name: pagerduty-critical
pagerduty_configs:
- service_key_file: '/etc/alertmanager/secrets/pagerduty-service-key'
severity: '{{ .CommonLabels.severity }}'
description: '{{ .CommonAnnotations.summary }}'
details:
firing: '{{ .Alerts.Firing | len }}'
resolved: '{{ .Alerts.Resolved | len }}'
cluster: '{{ .CommonLabels.cluster }}'
namespace: '{{ .CommonLabels.namespace }}'
runbook_url: '{{ .CommonAnnotations.runbook_url }}'
# Slack Criticalチャネル (PagerDutyと同時送信)
- name: slack-critical
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00/B00/YYYYY'
channel: '#alerts-critical'
send_resolved: true
color: '{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}'
title: 'CRITICAL: {{ .CommonLabels.alertname }}'
text: >-
*Status:* {{ .Status | toUpper }}
{{ range .Alerts }}
- {{ .Annotations.description }}
Runbook: {{ .Annotations.runbook_url }}
{{ end }}
# SRE SLO専用チャネル
- name: slack-sre-slo
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00/B00/ZZZZZ'
channel: '#sre-slo-alerts'
send_resolved: true
title: 'SLO Alert: {{ .CommonLabels.alertname }}'
text: >-
*Service:* {{ .CommonLabels.service }}
*Window:* {{ .CommonLabels.window }}
{{ range .Alerts }}
- {{ .Annotations.description }}
{{ end }}
# インフラチームのチャネル
- name: slack-infra
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00/B00/INFRA'
channel: '#team-infra-alerts'
send_resolved: true
# バックエンドチームのチャネル
- name: slack-backend
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00/B00/BACKEND'
channel: '#team-backend-alerts'
send_resolved: true
# Null受信者 (Watchdogなど不要なアラートを吸収)
- name: 'null'
PagerDuty Events API v2を使う場合は routing_key と service_key_file を適切に選択しなければならない。service_key_file はファイルベースで秘密鍵を注入するため、Kubernetes Secretと連携しやすい。Slack Incoming Webhookはチャネルごとに別々のWebhook URLを作成し、受信者ごとに異なるチャネルへ届ける。
Grafana Alertingとの比較
Grafana 9以降でUnified Alertingが導入され、Grafana自体でもアラートルールを管理できるようになった。2つのシステムの特性を比較し、環境に合った選択をすべきだ。
| 項目 | Prometheus Alertmanager | Grafana Unified Alerting |
|---|---|---|
| データソース | Prometheus専用 | 複数データソース (Loki、Tempo、SQLなど) |
| ルール管理 | YAMLファイル (GitOps親和) | UIまたはProvisioning API |
| ルーティング | ツリーベースの精密ルーティング | ポリシーベースのルーティング (Notification Policies) |
| 評価エンジン | Prometheusサーバ内蔵 | Grafanaサーバまたは外部Ruler |
| HA対応 | Gossipプロトコル内蔵 | Grafana HAに依存 |
| テストツール | promtool (CLIベース) | UIプレビュー、APIベース |
| 成熟度 | 非常に高い (10年以上) | 成長中 (Grafana 9+以降) |
| 拡張性 | Thanos/Cortex Ruler連携 | Mimir Ruler連携 |
| エコシステム | 豊富なコミュニティルール | Grafanaエコシステム統合 |
ハイブリッドアプローチ戦略
実務では2つのうち1つだけを選ぶより、ハイブリッドなアプローチが効果的だ。
- Prometheus Alertmanager: インフラメトリクス、SLOベースのアラート、高い信頼性が求められる主要アラート
- Grafana Unified Alerting: ログベースのアラート (Loki)、トレースベースのアラート (Tempo)、ビジネスメトリクスのアラート (SQLデータソース)
- 共通のAlertmanager: Grafanaのアラートも外部Alertmanagerへルーティングして統合管理が可能
Grafanaから外部Alertmanagerを接続すると、Grafanaの多様なデータソース対応とAlertmanagerの強力なルーティング/グループ化を同時に活用できる。
Alert Fatigue防止戦略
アラート疲れの原因と症状
Alert Fatigue(アラート疲れ)は、過剰なアラートによってオンコールエンジニアの注意が分散し、結局は重要なアラートまで無視するようになる現象だ。PagerDutyの2024 State of Digital Operationsレポートによると、オンコールエンジニアが1日平均10件以上のアラートを受け取ると対応品質が急激に低下する。
アラート疲れの主な原因は以下のとおりだ。
- 過剰な原因ベースのアラート: CPU 60%、70%、80%のそれぞれにアラートを設定した場合
- しきい値の未調整: デフォルト値のまま使用し、正常な変動にも反応する
- group_byの未設定: 同一障害で数十個の個別アラートが発生する
- 自動復旧する一時的な現象: 再起動で解決するOOMに毎回アラートを出す
- 業務時間を考慮しないアラート: 深夜3時にWarningアラートでページング
信号対雑音比(SNR)の改善
すべてのアラートは次の質問を通過しなければならない。
- このアラートを受け取ったら即座に行動すべきか。
- このアラートはユーザーに影響を与える症状を示しているか。
- このアラートがなければどんなリスクがあるか。
- このアラートに対する明確なRunbookが存在するか。
1つでも「いいえ」なら、そのアラートは削除するかダッシュボードのパネルへ移すべきだ。
アラート優先度体系: P1-P4
| 優先度 | 定義 | アラートチャネル | 対応時間 | 例 |
|---|---|---|---|---|
| P1 (Critical) | サービス全面障害またはデータ損失のリスク | PagerDutyで即時ページング | 5分以内 | API全体のダウン、データベース障害 |
| P2 (High) | 部分障害または性能の深刻な低下 | PagerDuty + Slack | 30分以内 | 特定エンドポイントのエラー率急増 |
| P3 (Warning) | 潜在的な問題、調査が必要 | Slackチャネル | 営業日基準4時間 | ディスク使用率の増加傾向 |
| P4 (Info) | 参考情報 | Slackまたはダッシュボードのみ | 次のスプリント | 証明書が30日以内に期限切れ |
週次アラートレビューのプロセス
毎週チーム単位で過去1週間のアラートをレビューする。
- 定量分析: 総アラート数、severity別の分布、チーム別の分布、MTTRの測定
- 誤検知の分類: 各アラートが実際に行動を引き起こしたかを確認
- しきい値の調整: 誤検知が繰り返されるアラートのしきい値またはfor期間を調整
- ルールの整理: 3週連続で無視されたアラートは削除候補
- 文書化: 調整内容とその根拠を記録
Cloudflareのアラート可観測性の事例
Cloudflareは「Alerts Observability」という概念を導入し、アラート自体を観察の対象とした。アラートの発火頻度、応答時間、自動解消率、エスカレーション率をダッシュボードで可視化し、それを基にアラート品質を継続的に改善している。アラートシステムに対するメタモニタリングが、Alert Fatigueを体系的に管理する鍵だ。
失敗事例と復旧手順
事例1: group_byの誤設定によるアラートの氾濫
状況: group_byを [alertname] だけに設定した状態で、100ノードのDiskWillFillIn24Hoursアラートが同時に発火した。すべてのノードのアラートが1つのグループにまとめられて単一のアラートしか送信されず、個別ノードの情報が欠落して対応が不可能だった。
原因: group_by に instance ラベルを含めなかったため、すべてのノードのアラートが1つに統合された。
解決: group_by: [alertname, instance] へ変更し、ノードごとに別々のアラートグループが生成されるよう修正した。ただし、group_byにラベルを多く含めすぎるとグループが過度に細分化され、逆の問題(アラートの氾濫)が発生しうるため、適切なバランスが必要だ。
事例2: PagerDutyルーティングの漏れによる障害の未検知
状況: 新しいマイクロサービスをデプロイしたが、そのサービスのアラートに team: payments ラベルが欠落していた。ルーティングルールにマッチせずデフォルト受信者(Slack generalチャネル)にのみ配信され、決済サービスの障害が30分間検知されなかった。
原因: サービスのデプロイ時にアラートルールのラベル検証プロセスがなかった。
解決: CIパイプラインにラベル検証ステップを追加し、すべてのアラートルールに team、severity ラベルが必ず含まれるよう強制した。amtoolを活用したルーティングシミュレーションをデプロイ前チェックに含めた。
# amtoolでルーティング経路をシミュレーション
amtool config routes test \
--config.file=alertmanager.yaml \
--tree \
severity=critical team=payments alertname=HighErrorRate
# 想定される出力: pagerduty-critical → slack-critical
# team=payments ラベルがない場合: default-slack (警告が発生)
復旧手順のチェックリスト
アラートパイプラインの障害時に段階的に確認する項目だ。
- Alertmanagerクラスタの状態確認:
amtool cluster show - 現在有効なアラートの確認: Alertmanager UIまたは
amtool alert query - Silence状態の確認: 意図しないSilenceが有効になっていないか
- Prometheusアラートルールの評価状態: Prometheus UIのAlertsタブでエラーを確認
- ネットワーク接続: PrometheusからAlertmanagerへの通信を確認
- 受信者の接続: PagerDuty API、Slack Webhookの応答を確認
- 設定ファイルの整合性:
amtool check-config alertmanager.yaml
運用時の注意事項
アラートルールの命名規約
一貫した命名はルーティングルールの作成とダッシュボードのフィルタリングに不可欠だ。次の規約を推奨する。
| パターン | 説明 | 例 |
|---|---|---|
| 対象 + 症状 | 何がどんな状態か | HighCpuUsage, DiskWillFillIn24Hours |
| SLO接頭辞 | SLO関連アラートの区別 | SloHighBurnRate, SloLatencyBudgetExhausted |
| サービス接頭辞 | サービス固有のアラート | ApiGatewayHighLatency, PaymentServiceDown |
PascalCaseを使い、アラート名だけで何が問題なのかを把握できるようにする。「Alert1」「Check5」のような意味のない名前は禁止する。
ラベルの標準化とガバナンス
すべてのアラートルールに含めるべき必須ラベルを定義する。
| ラベル | 必須かどうか | 説明 | 許容値 |
|---|---|---|---|
| severity | 必須 | アラートの重大度 | critical, warning, info |
| team | 必須 | 担当チーム | infra, backend, frontend, data, sre |
| service | 推奨 | 関連サービス | サービスディスカバリの名前と一致 |
| slo | 任意 | SLO関連かどうか | availability, latency |
ラベル値は必ず列挙型で管理すべきで、自由テキストを許すとルーティングルールが複雑になり管理が不可能になる。OPA(Open Policy Agent)やCIパイプラインでラベルスキーマを検証する方法が効果的だ。
定期的なアラート監査(audit)
四半期ごとに全アラートルールに対する監査を実施する。
- 有効なアラート数の推移: アラート数が継続的に増えているならルールの整理が必要
- 誤検知率の測定: firing後5分以内に自動resolveされたアラートの割合
- 応答率の測定: アラート発火後に実際の対応が行われた割合
- オーナーの確認: すべてのアラートルールに担当チームが指定されているか
- Runbookの接続: すべてのCritical/Warningアラートにrunbook_urlがあるか
監査結果を基にルールを整理し、不要なアラートを削除し、しきい値を調整する。アラートルールはコードと同じく、継続的な保守が必要な生きた資産だ。