Prometheusを「ただの監視ツール」で終わらせるな:高負荷環境を制するアーキテクチャの極意
多くのエンジニアがPrometheusを導入し、数ヶ月後に直面する壁がある。それは「Cardinality(カーディナリティ)の爆発」と「スクレイピング遅延」だ。データが増えるほど、Prometheusはメトリクスを保存するだけのブラックホールと化し、クエリはタイムアウトし、アラートは沈黙する。
本稿では、Prometheusを単なるツールとしてではなく、分散システムの心臓部として極限までチューニングするための「現場の暗黙知」を伝授する。
—
1. 殺人的なボトルネックの正体:メモリとTSDBの相関
Prometheusのボトルネックは、多くの場合CPUではなくメモリとディスクI/Oの競合に集約される。
- メモリの罠: Prometheusはインメモリでインデックス(転置インデックス)を保持する。メトリクスの系列数(Series)が数百万を超えると、`Go`のGC(ガベージコレクション)が暴走し、メモリを食いつぶす。
- ディスクI/Oの悲劇: 書き込みはTSDBのWAL(Write Ahead Log)経由で行われる。高負荷時にスクレイピング間隔が短すぎると、ディスクの書き込み待ちが発生し、それがスクレイピングのタイムアウトを誘発するという「負の連鎖」が始まる。
アーキテクトの助言: 常に `prometheus_tsdb_head_series` メトリクスを監視せよ。これが1,000万を超えたら、単体構成でのスケーリングは限界だ。即座に「Federation」か「Thanos/Cortex」への移行を検討すべきだ。
—
2. scrape_interval と timeout:生存のための黄金比
多くの現場で `scrape_interval` をデフォルトの15秒に放置している。これは罪に近い。
- 原則: インターバルは「本当に必要な解像度」まで引き延ばせ。1分間隔でも十分なメトリクスは山ほどある。
- タイムアウトの罠: `scrape_timeout` はインターバルより短く設定せよ。さもなくば、スクレイピングのオーバーラップが発生し、スクレイパーが飽和する。
効率的なスクレイピング設定の例
scrape_configs:
- job_name: ‘high-priority-microservices’
scrape_interval: 15s
scrape_timeout: 10s # インターバルの2/3以下を推奨
metrics_path: /metrics
# 接続の再利用を意識し、keep-aliveを有効にする
honor_labels: true
—
3. relabel_configs:ゴミを捨て、命を拾う
Prometheusのメモリ消費は、取り込むメトリクスの数に比例する。開発者が意図せず出す「IDを含むメトリクス(例: `user_id`, `request_id`)」は、カーディナリティを爆発させる癌だ。
これを防ぐ唯一の防御壁が `relabel_configs` によるドロップ戦略である。
scrape_configs:
- job_name: ‘kubernetes-pods’
relabel_configs:
# 不要なメトリクスを物理的に取り込まない
- source_labels: [__name__]
regex: ‘go_.|process_.’ # 言語ランタイムの低価値メトリクスは捨てる
action: drop
# ラベルの正規化(カーディナリティ抑制)
- source_labels: [__meta_kubernetes_pod_label_component]
target_label: component
極意: 「全てのメトリクスを保存する」という考えを捨てよ。本当に必要なのは、「SLI(Service Level Indicators)を計算するために最低限必要な系列」だけだ。
—
4. Federation:水平スケールのための奥義
単一のPrometheusで数万ノードを監視しようとするな。それは設計の敗北だ。役割に応じて役割を分散させる「Federation」こそが、スケーラビリティの鍵となる。
- Leaf Prometheus: 特定のクラスタやリージョンに配置し、局所的なスクレイピングを担当。
- Global Prometheus: Leafから集約された重要なメトリクスのみを「フェデレーション」として吸い上げる。
Global Prometheus側の設定
scrape_configs:
- job_name: ‘federate’
scrape_interval: 1m
honor_labels: true
metrics_path: ‘/federate’
params:
‘match[]’:
- ‘{__name__=~”job:.”}’ # 集約されたメトリクスのみを抽出
static_configs:
- targets: [‘leaf-prometheus-01:9090’]
—
5. エンジニアへのラスト・アドバイス:自動化と監視の監視
手動で設定を書き換えるのは、レガシーな運用だ。
1. Prometheus Operatorの採用: K8s環境であれば、CRDベースの管理は必須。`ServiceMonitor` を使い、開発者がメトリクスを取り込みたい時に「自動的に設定が生成される」パイプラインを構築せよ。
2. APIによる動的制御: 負荷が高い時は `http://
3. カーディナリティの可視化: 定期的に以下のクエリを実行し、どのラベルがメモリを食っているか特定せよ。
ラベル別の系列数ランキング
topk(10, count by (__name__) ({__name__=~”.+”}))
結論:
Prometheusを極めるということは、メトリクスを「増やす」ことではない。「不要なものを削ぎ落とし、本質的なシグナルだけを高速に抽出する」という引き算の哲学を実践することだ。
君たちが構築する監視システムが、障害の予兆を静かに、かつ確実に捉えるものになることを期待している。さあ、今すぐ不要な `relabel_configs` を書きに行こう。