ストーリー
佐
佐藤CTO
オブザーバビリティの3本柱を学んだ。その中核となるメトリクス基盤 — Prometheus と Grafana の実践的な使い方を掘り下げよう
佐
佐藤CTO
Prometheusは単にメトリクスを集めるだけではない。PromQLという強力なクエリ言語と、Recording Rules/Alerting Rulesによる効率的な運用が真の武器だ
Prometheusアーキテクチャ
コンポーネント
graph LR
subgraph Ecosystem["Prometheus Ecosystem"]
Targets["Targets<br/>(scrape)"] -->|pull| Prom
Pushgateway["Pushgateway<br/>(短命ジョブ)"] -->|push| Prom
SD["Service Discovery<br/>(K8s, DNS)"] --> Prom
subgraph Prom["Prometheus Server"]
TSDB["TSDB<br/>(時系列DB)"]
PromQL["PromQL Engine"]
AlertRules["Alert Rules"]
end
PromQL --> Grafana["Grafana"]
AlertRules --> AM["Alertmanager"]
end
classDef source fill:#6c757d,stroke:#495057,color:#fff
classDef prom fill:#e94560,stroke:#c23050,color:#fff
classDef output fill:#0d6efd,stroke:#0a58ca,color:#fff
class Targets,Pushgateway,SD source
class TSDB,PromQL,AlertRules prom
class Grafana,AM output
Kubernetes上でのPrometheus構成
# prometheus-config.yaml (ConfigMap)
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
# Recording Rules と Alerting Rules
rule_files:
- '/etc/prometheus/rules/*.yml'
scrape_configs:
# Kubernetes Pods の自動検出
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: (.+)
replacement: ${1}
# Node Exporter
- job_name: 'node-exporter'
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: replace
target_label: __address__
replacement: ${1}:9100
# kube-state-metrics
- job_name: 'kube-state-metrics'
static_configs:
- targets: ['kube-state-metrics:8080']
PromQL応用
高度なクエリパターン
# 1. サービス別のエラーバジェット消費率
(
1 - (
sum by (service) (increase(http_requests_total{status!~"5.."}[30d]))
/
sum by (service) (increase(http_requests_total[30d]))
)
) / 0.001 * 100
# → 各サービスの30日間エラーバジェット消費率(%)
# 2. エラー率の急激な変化(前の時間帯と比較)
(
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
)
/
(
sum(rate(http_requests_total{status=~"5.."}[5m] offset 1h))
/
sum(rate(http_requests_total[5m] offset 1h))
)
# → 1時間前と比較したエラー率の倍率
# 3. Apdex スコア(ユーザー満足度の簡易指標)
# Satisfied: < 300ms, Tolerating: < 1200ms, Frustrated: >= 1200ms
(
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m]))
+
sum(rate(http_request_duration_seconds_bucket{le="1.2"}[5m]))
-
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m]))
) / (2 * sum(rate(http_request_duration_seconds_count[5m])))
# → 0〜1のApdexスコア(0.94以上が "Excellent")
# 4. 予測クエリ(線形回帰で将来の値を予測)
predict_linear(
node_filesystem_avail_bytes{mountpoint="/"}[6h],
3600 * 24 * 7 # 7日後を予測
)
# → 7日後のディスク空き容量を予測
# 5. トップN(エラー率が高い上位5エンドポイント)
topk(5,
sum by (handler) (rate(http_requests_total{status=~"5.."}[1h]))
/
sum by (handler) (rate(http_requests_total[1h]))
)
Recording Rules
# recording-rules.yml
groups:
- name: sli_recording_rules
interval: 30s
rules:
# 可用性SLI(各ウィンドウ)
- record: sli:http_availability
expr: |
sum(rate(http_requests_total{status!~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
# レイテンシSLI(p99)
- record: sli:http_latency_p99
expr: |
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m]))
by (le, service)
)
# エラーバジェット消費率
- record: slo:error_budget_consumption
expr: |
(1 - sli:http_availability) / 0.001
# バーンレート(各ウィンドウ)
- record: slo:burn_rate:1h
expr: |
(
1 - (
sum(rate(http_requests_total{status!~"5.."}[1h])) by (service)
/
sum(rate(http_requests_total[1h])) by (service)
)
) / 0.001
- record: slo:burn_rate:6h
expr: |
(
1 - (
sum(rate(http_requests_total{status!~"5.."}[6h])) by (service)
/
sum(rate(http_requests_total[6h])) by (service)
)
) / 0.001
Grafanaベストプラクティス
ダッシュボード設計原則
| 原則 | 説明 |
|---|
| 目的を明確にする | 誰が、何のために見るダッシュボードか |
| 5秒ルール | 5秒で状況を把握できること |
| ドリルダウン可能 | 概要→詳細へ辿れるリンク構成 |
| 閾値を表示 | SLO目標線、アラート閾値を明示 |
| テンプレート変数 | 環境、サービス、時間範囲を切り替え可能に |
テンプレート変数の活用
{
"templating": {
"list": [
{
"name": "service",
"type": "query",
"query": "label_values(http_requests_total, service)",
"refresh": 2,
"multi": true
},
{
"name": "environment",
"type": "custom",
"options": [
{ "text": "Production", "value": "production" },
{ "text": "Staging", "value": "staging" }
]
},
{
"name": "slo_target",
"type": "custom",
"current": { "text": "99.9%", "value": "0.999" },
"options": [
{ "text": "99%", "value": "0.99" },
{ "text": "99.9%", "value": "0.999" },
{ "text": "99.95%", "value": "0.9995" }
]
}
]
}
}
Prometheus運用のTips
| カテゴリ | Tips |
|---|
| カーディナリティ | ラベル値の組み合わせ爆発に注意(user_id等をラベルにしない) |
| 保持期間 | ローカルストレージは15日程度、長期保存はThanos/Cortex |
| Recording Rules | 重いクエリは事前計算してRecording Ruleに |
| アラート | Alertmanager でグルーピング・抑制・通知ルーティング |
| フェデレーション | 複数Prometheusをフェデレーションで統合 |
| バックアップ | TSDB のスナップショットを定期的に取得 |
まとめ
| ポイント | 内容 |
|---|
| Prometheusアーキテクチャ | Pull型、TSDB、Service Discovery、Alertmanager |
| PromQL応用 | エラーバジェット計算、Apdex、predict_linear、topk |
| Recording Rules | 重いクエリを事前計算して効率化 |
| Grafana設計 | 5秒ルール、ドリルダウン、テンプレート変数 |
| 運用Tips | カーディナリティ管理、長期保存、フェデレーション |
チェックリスト
次のステップへ
次は「分散トレーシング」を学びます。マイクロサービス間のリクエストフローを追跡するための技術を深掘りしましょう。
推定読了時間: 40分