Prometheus Pushgateway: バッチジョブ監視を1秒も逃さない究極のテクニック

Monitoring tutorial - IT technology blog
Monitoring tutorial - IT technology blog

なぜPrometheusのプルモデルはバッチジョブに弱いのか?

Prometheusを扱ったことがあれば、その核心的なメカニズムがプルモデル(Pull model)であることをご存知でしょう。サーバーが定期的にエクスポーターを訪問してデータを収集する仕組みです。しかし、システムに「短命な」タスクが登場すると問題が発生します。例えば、3秒で終わるログのクリーンアップJobや、午前2時に1分足らずで完了するデータベースのバックアップスクリプトなどです。

以前、バックアップジョブが失敗しているにもかかわらず、Grafanaが正常(緑色)を示し続けていたことに頭を抱えたことがありました。理由は極めて単純です。Prometheusはデフォルトで15〜30秒ごとにスクレイプ(scrape)します。もしジョブが2つのスクレイプサイクルの間に開始して終了(あるいはクラッシュ)してしまった場合、Prometheusにとっては、そのジョブは存在しなかったも同然なのです。

Prometheus Pushgatewayは、このギャップを埋めるために誕生しました。これを中間的な「メールボックス」と考えてください。Prometheusが取りに来るのを待つ代わりに、短命なジョブは自らPushgatewayにメトリクスを投げ込んで終了します。Prometheusは、単にこの「メールボックス」に立ち寄ってデータを回収すればいいのです。

短命なジョブを監視する3つの方法:どれを選ぶべきか?

Pushgatewayを選択する前に、いくつかの方法を試して比較した結果がこちらです:

  • スクレイプ間隔(Scrape Interval)を1秒に設定する: 一見良さそうですが、サーバーのCPU負荷が激増します。実際、ジョブが0.5秒で終わる場合、依然として50%の確率でデータを見逃すリスクがあります。
  • 専用のエクスポーターを立てる: わずか10行のBashスクリプトに対しては、あまりにも大掛かりです。メトリクスを公開するためだけに、Webサービスを常時稼働させる必要があります。
  • Pushgatewayを使用する: 最も最適なソリューションです。スクリプトにシンプルな curl コマンドを1つ追加するだけで、データがダッシュボードに反映されます。

警告:6ヶ月の実戦投入で見えた「落とし穴」

Pushgatewayは非常に強力ですが、魔法の杖ではありません。200以上のCronJobを半年間運用してみて、いくつかの致命的な弱点に気づきました。

メリット

  • 圧倒的な柔軟性: シェルスクリプトからJavaまで、HTTPリクエストを送れるものであれば何でも対応可能です。
  • 「クリーン」なジョブ: 実行が終われば終了し、ジョブ実行サーバーのポートやリソースを維持する必要がありません。

デメリットとリスク(要注意)

  • 単一障害点(Single point of failure): Pushgatewayがダウンすると、すべてのバッチジョブがレーダーから消えます。Pushgateway自体の監視を厳重に行う必要があります。
  • 「Stale metrics」の罠: これが最も厄介です。Pushgatewayはデータを自動的に削除しません。今日ジョブが status=1(成功)を報告し、明日ジョブが実行されなかったとしても、Pushgatewayはその「1」を保持し続けます。Prometheusは、すべてが正常であると誤報を出し続けます。
  • up メトリクスの欠如: Node Exporterのように up 関数を使ってジョブの死活監視を行うことはできません。

5分で完了するPushgatewayの構築

OSを汚さずにPushgatewayを導入するには、Dockerを使用するのが最速です。

1. Docker Composeでの起動

最小構成の docker-compose.yml を作成します:

services:
  pushgateway:
    image: prom/pushgateway:v1.9.0
    container_name: pushgateway
    ports:
      - "9091:9091"
    restart: always

docker-compose up -d を実行し、ブラウザで http://your-ip:9091 にアクセスして管理画面を確認します。

2. 実際のスクリプトからデータを送信する

容量500GBのデータベースバックアップスクリプトがあると仮定し、その容量と状態を監視します。

Bashの例(curlを使用)

# 詳細なラベル付きでメトリクスをプッシュ
cat <<EOF | curl --data-binary @docs/ITFROMZERO-AutoContent-Documentation.md http://localhost:9091/metrics/job/backup_db/instance/prod_server
# HELP db_backup_size_bytes バックアップファイルの容量
# TYPE db_backup_size_bytes gauge
db_backup_size_bytes 536870912000
# HELP db_backup_status 1=成功, 0=失敗
db_backup_status 1
EOF

Pythonの例(prometheus_clientを使用)

from prometheus_client import CollectorRegistry, Gauge, push_to_gateway

registry = CollectorRegistry()
g = Gauge('job_last_success_time', 'ジョブが正常に実行されたUnixタイムスタンプ', registry=registry)
g.set_to_current_time()

# ゲートウェイにメトリクスをプッシュ
push_to_gateway('localhost:9091', job='daily_report', registry=registry)

3. Prometheusのスクレイプ設定

prometheus.yml の修正を忘れないでください。標準的な設定は以下の通りです:

scrape_configs:
  - job_name: 'pushgateway'
    honor_labels: true
    static_configs:
      - targets: ['localhost:9091']

ヒント: honor_labels: true を必ず設定してください。これがないと、苦労して設定したラベルがPushgatewayのデフォルトラベルで上書きされてしまいます。

運用における教訓

ダッシュボードに「騙されない」ために、次の2つの黄金律を守ってください:

常に成功時のタイムスタンプを使用する: 0か1のステータスだけを見るのではなく、job_last_success_unixtime というメトリクスを追加で送信してください。Grafanaでは、time() - job_last_success_unixtime という式を使います。この数値が24時間を超えていれば、昨夜のバックアップジョブに何か異変があったことが確実に分かります。

定期的なクリーンアップ: ランダムなIDなどの動的なラベルを生成するジョブの場合、Pushgatewayのデータは急速に膨れ上がり、数GBのRAMを消費する可能性があります。不要になったメトリクスをクリーンアップするために、DELETE APIを呼び出すスクリプトを用意しましょう。

# 使用しなくなったジョブのデータを完全に削除
curl -X DELETE http://localhost:9091/metrics/job/backup_db

この構成を導入してから、夜中にログを確認したり、各サーバーにSSHでログインしたりする必要がなくなりました。朝、のんびりとコーヒーを飲みながらダッシュボードを眺めるだけで、システム全体の健康状態が把握できます。重要なCronJobを多数管理しているなら、今すぐ導入をお勧めします!

Share: