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

intermediate | 60分 で読める | 2026.04.10

公式ドキュメント

この記事の要点

• Prometheusのアーキテクチャとメトリクス収集の仕組み
• PromQLの基本クエリとアラートルールの設定方法
• Alertmanagerとの連携によるインシデント通知

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

  • ✓ 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 応答を確認
  2. host.docker.internal が解決できない (Linux)

    • extra_hosts: “host.docker.internal:host-gateway” を追加
  3. TSDBの肥大化

    • —storage.tsdb.retention.time でリテンションを設定
    • 長期保存はリモートストレージ (Thanos, Mimir等)
  4. アラートが飛ばない

    • /alerts ページで PENDING → FIRING を確認
    • Alertmanager のログ、ネットワーク到達性を確認
  5. ハイカーディナリティ

    • ラベルにユーザーIDやリクエストIDを入れない
    • ラベルの組み合わせ爆発に注意

ベストプラクティス

ポイント: 4 Golden SignalsLatency, 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ブックで紹介されている典型的な値です。

この技術を体系的に学びたいですか?

未来学では東証プライム上場企業のITエンジニアが24時間サポート。月額24,800円から、退会金0円のオンラインIT塾です。

メールで無料相談する
← 一覧に戻る