Prometheus実践ガイド - メトリクス収集とアラート入門

intermediate | 60分 で読める | 2026.04.10

公式ドキュメント

このチュートリアルで学ぶこと

  • ✓ Prometheusのアーキテクチャと概念
  • ✓ Dockerでのセットアップ
  • ✓ Node Exporter / アプリからのメトリクス公開
  • ✓ PromQLの基本
  • ✓ 記録ルール (Recording Rules) とアラート
  • ✓ Alertmanagerとの連携

前提条件

  • Linux / コマンドラインの基礎
  • Docker と Docker Compose の基礎
  • HTTP / JSON の基本
  • 監視・オブザーバビリティの基本概念

基本概念

ポイント: PrometheusはPull型モデルを採用しており、監視対象のサービスにPrometheus自身がアクセスしてメトリクスを取得します。Push型と異なり、監視対象側にエージェントを常駐させる必要がありません。

Prometheusは以下の特徴を持つオープンソース監視システムです。

  • Pull型モデル (Prometheus がターゲットをスクレイプ)
  • 多次元データモデル (メトリクス名 + ラベル)
  • PromQL という強力なクエリ言語
  • ローカル時系列DB (TSDB)
  • サービスディスカバリ対応

メトリクスの種類

  • Counter: 単調増加 (リクエスト総数, エラー総数)
  • Gauge: 増減する値 (CPU使用率, メモリ, キュー長)
  • Histogram: レイテンシ等の分布 (bucket)
  • Summary: Histogramと類似、クライアント側で計算

プロジェクトのセットアップ

mkdir prometheus-demo && cd prometheus-demo
touch docker-compose.yml prometheus.yml alert.rules.yml alertmanager.yml

docker-compose.yml

services:
 prometheus:
 image: prom/prometheus:latest
 container_name: prometheus
 command:
 - "--config.file=/etc/prometheus/prometheus.yml"
 - "--storage.tsdb.path=/prometheus"
 - "--web.enable-lifecycle"
 volumes:
 - ./prometheus.yml:/etc/prometheus/prometheus.yml
 - ./alert.rules.yml:/etc/prometheus/alert.rules.yml
 - prom_data:/prometheus
 ports:
 - "9090:9090"

 node_exporter:
 image: prom/node-exporter:latest
 container_name: node_exporter
 ports:
 - "9100:9100"

 alertmanager:
 image: prom/alertmanager:latest
 container_name: alertmanager
 volumes:
 - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
 ports:
 - "9093:9093"

volumes:
 prom_data:

Step 1: 基本的な prometheus.yml

global:
 scrape_interval: 15s
 evaluation_interval: 15s

alerting:
 alertmanagers:
 - static_configs:
 - targets: ["alertmanager:9093"]

rule_files:
 - "alert.rules.yml"

scrape_configs:
 - job_name: "prometheus"
 static_configs:
 - targets: ["localhost:9090"]

 - job_name: "node"
 static_configs:
 - targets: ["node_exporter:9100"]

 - job_name: "app"
 metrics_path: "/metrics"
 static_configs:
 - targets: ["host.docker.internal:3000"]

起動:

docker compose up -d
# http://localhost:9090 でPrometheusのUI
# http://localhost:9100/metrics でNode Exporterの出力

Step 2: PromQL の基本

PromQLはPrometheus独自のクエリ言語で、メトリクスの集計・フィルタリング・演算を柔軟に行えます。

# 現在のCPU使用率 (各ノード)
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# メモリ使用率
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100

# リクエストの1分間スループット
rate(http_requests_total[1m])

# ステータスコード別の5xx比率
sum(rate(http_requests_total{status=~"5.."}[5m]))
 / sum(rate(http_requests_total[5m]))

# 上位5インスタンスのCPU
topk(5, 100 - rate(node_cpu_seconds_total{mode="idle"}[5m]) * 100)

Step 3: Node.jsアプリからメトリクスを公開

mkdir app && cd app
npm init -y
npm install express prom-client
// app/server.js
const express = require("express");
const client = require("prom-client");

const app = express();
const register = new client.Registry();
client.collectDefaultMetrics({ register });

const httpRequests = new client.Counter({
 name: "http_requests_total",
 help: "Total HTTP requests",
 labelNames: ["method", "route", "status"],
});
register.registerMetric(httpRequests);

const httpDuration = new client.Histogram({
 name: "http_request_duration_seconds",
 help: "HTTP request latency",
 labelNames: ["method", "route", "status"],
 buckets: [0.05, 0.1, 0.3, 0.5, 1, 2, 5],
});
register.registerMetric(httpDuration);

app.use((req, res, next) => {
 const end = httpDuration.startTimer({ method: req.method, route: req.path });
 res.on("finish", () => {
 httpRequests.inc({
 method: req.method,
 route: req.path,
 status: String(res.statusCode),
 });
 end({ status: String(res.statusCode) });
 });
 next();
});

app.get("/", (req, res) => res.send("hello"));
app.get("/slow", async (req, res) => {
 await new Promise((r) => setTimeout(r, 500));
 res.send("done");
});

app.get("/metrics", async (req, res) => {
 res.set("Content-Type", register.contentType);
 res.end(await register.metrics());
});

app.listen(3000, () => console.log("http://localhost:3000"));

起動後 http://localhost:3000/metrics でメトリクス出力を確認できます。

Step 4: 記録ルール

# alert.rules.yml 内で記録ルールも定義可能
groups:
 - name: recording.rules
 interval: 30s
 rules:
 - record: job:http_requests:rate5m
 expr: sum by (job) (rate(http_requests_total[5m]))

 - record: job:http_errors:ratio5m
 expr: |
 sum by (job) (rate(http_requests_total{status=~"5.."}[5m]))
 /
 sum by (job) (rate(http_requests_total[5m]))

実践メモ: 記録ルールで頻繁に使うクエリを事前計算しておくと、ダッシュボードの表示が高速になり、Prometheusの負荷も軽減されます。

Step 5: アラートルール

# alert.rules.yml (続き)
 - name: alerts
 rules:
 - alert: HighErrorRate
 expr: job:http_errors:ratio5m > 0.05
 for: 5m
 labels:
 severity: warning
 annotations:
 summary: "{{ $labels.job }} の 5xx 率が高い"
 description: "5分間の5xx比率が {{ $value | humanizePercentage }} を超えました"

 - alert: InstanceDown
 expr: up == 0
 for: 2m
 labels:
 severity: critical
 annotations:
 summary: "{{ $labels.instance }} がダウンしています"

 - alert: HighCPU
 expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
 for: 10m
 labels:
 severity: warning
 annotations:
 summary: "{{ $labels.instance }} のCPU使用率が85%超"

設定再読み込み:

curl -X POST http://localhost:9090/-/reload

Step 6: Alertmanager 設定

# alertmanager.yml
route:
 receiver: "default"
 group_by: ["alertname", "severity"]
 group_wait: 30s
 group_interval: 5m
 repeat_interval: 1h
 routes:
 - matchers:
 - severity="critical"
 receiver: "critical-receiver"

receivers:
 - name: "default"
 webhook_configs:
 - url: "http://example.com/webhook"
 send_resolved: true

 - name: "critical-receiver"
 webhook_configs:
 - url: "http://example.com/critical"
 send_resolved: true

inhibit_rules:
 - source_matchers:
 - severity="critical"
 target_matchers:
 - severity="warning"
 equal: ["alertname", "instance"]

完成: ダッシュボード用クエリ集

# サービスごとのQPS
sum by (job) (rate(http_requests_total[1m]))

# P95 レイテンシ
histogram_quantile(
 0.95,
 sum by (le, route) (rate(http_request_duration_seconds_bucket[5m]))
)

# メモリ上位コンテナ (kube state想定)
topk(10, container_memory_working_set_bytes{namespace!=""})

# ディスク残量 (10%未満)
(node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < 10

# 過去24hで一度でもdownしたインスタンス
max_over_time(up[24h]) == 0

注意: ハイカーディナリティ(ラベルの組み合わせ爆発)はPrometheusの最大の落とし穴です。ユーザーIDやリクエストIDなどの高基数値をラベルにしないことが鉄則です

よくあるエラーと対処

  1. “context deadline exceeded”
  • scrape_timeout を緩める、ターゲットの /metrics 応答を確認
  1. host.docker.internal が解決できない (Linux)
  • extra_hosts: “host.docker.internal:host-gateway” を追加
  1. TSDBの肥大化
  • —storage.tsdb.retention.time でリテンションを設定
  • 長期保存はリモートストレージ (Thanos, Mimir等)
  1. アラートが飛ばない
  • /alerts ページで PENDING → FIRING を確認
  • Alertmanager のログ、ネットワーク到達性を確認
  1. ハイカーディナリティ
  • ラベルにユーザーIDやリクエストIDを入れない
  • ラベルの組み合わせ爆発に注意

ベストプラクティス

ポイント: 4 Golden Signals(Latency, Traffic, Errors, Saturation)を軸に監視設計を行うことで、サービスの健全性を包括的に把握できます

  • 4 Golden Signals (Latency, Traffic, Errors, Saturation) を軸に設計
  • ラベル数は厳選しカーディナリティを抑制
  • アラートはアクションに繋がるものだけ (アラート疲れを防ぐ)
  • 記録ルールで高頻度クエリを事前計算
  • ダッシュボードはGrafanaで可視化
  • メトリクス、ログ、トレースの3本柱で相補的に監視

次のステップ

  • Grafana でのダッシュボード作成
  • Thanos / Mimir による長期保存とマルチクラスタ
  • kube-prometheus-stack (Helm) でKubernetesを監視
  • OpenTelemetry との統合
  • SLI/SLO 設計と Error Budget

ここまでの整理

PrometheusはPullベースで扱いやすく、PromQLの表現力が高く、エコシステムも充実しています。 Node Exporter とアプリのインストゥルメント、適切なアラート設計を組み合わせることで、 本番環境での異常を早期に検知できる監視基盤を構築できます。

FAQ

Q. Pull型とPush型、Prometheusはどちら? A. 基本はPull型です。Prometheus自身がターゲットに /metrics をスクレイプしに行きます。 バッチジョブ等のPushが必要な場合は Pushgateway を経由させます。

Q. 長期保存はどうする? A. Prometheus単体では長期保存に不向きです。Thanos / Mimir / Cortex などのリモートストレージ統合を 検討してください。

Q. Kubernetesで使うには? A. kube-prometheus-stack (Helmチャート) を使うと Prometheus, Alertmanager, Grafana, Node Exporter, kube-state-metrics などがワンセットで導入できます。

Q. ハイカーディナリティとは? A. ラベルの組み合わせ数が爆発的に増える状態です。ユーザーIDやリクエストIDなど高基数の値を ラベルにしないことが基本的な対策です。

チートシート

# Prometheus 2.x / PromQL
# https://prometheus.io/docs/prometheus/latest/querying/basics/

rate(metric[5m]) # 単位時間あたりの増加率 (Counter)
increase(metric[1h]) # 区間での増分
sum by (label) (expr) # ラベルでまとめて合計
avg / max / min / count # 集計関数
topk(n, expr) / bottomk(n, expr) # 上位/下位
histogram_quantile(0.95, sum by (le)(...)) # P95レイテンシ
up == 0 # ダウン中のインスタンス
absent(metric) # メトリクスが欠損

まとめ

この記事では、手順を追って動かしながら重要な確認ポイントを押さえることが大切です。まずは学習用の最小構成で動作確認し、本番利用する前にセキュリティ、権限、エラー処理、運用手順を見直してください。

参考リソース

補足: SLI/SLOの設計例

SREの実践では、Error Budgetをベースに運用判断を行うことが一般的です。 PromQLで以下のようにSLIを定義できます。

# 可用性SLI (成功率)
sum(rate(http_requests_total{status!~"5.."}[30d]))
 /
sum(rate(http_requests_total[30d]))

# レイテンシSLI (300ms以内の比率)
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[30d]))
 /
sum(rate(http_request_duration_seconds_count[30d]))

SLOを99.9% と置いた場合、Error Budget は 0.1% (30日で約43分) となります。 Budgetを消費しすぎたらリリース凍結、余裕があれば攻めた改善に回すといった運用判断が行えます。

バーンレートアラート

急激にBudgetを消費したときだけ通知する仕組みです。

- alert: HighErrorBurnRate
 expr: |
 (
 sum(rate(http_requests_total{status=~"5.."}[5m]))
 /
 sum(rate(http_requests_total[5m]))
 ) > (14.4 * 0.001)
 for: 2m
 labels:
 severity: critical
 annotations:
 summary: "エラーバーンレートが高い (2%ウィンドウ)"

14.4 は「30日で2%のBudgetを5分ウィンドウで消費する速度」の係数で、 Google SREブックで紹介されている典型的な値です。

← 一覧に戻る
PR
PR
PR
PR