Skip to content
Published on

[Prometheus] アーキテクチャ内部分析:ソースコードレベルディープダイブ

Authors

1. 概要

PrometheusはCNCF卒業プロジェクトであり、クラウドネイティブ環境のデファクトスタンダードモニタリングシステムです。この記事では、Prometheusサーバーの内部アーキテクチャをソースコードレベルで分析し、各コンポーネントの相互作用とライフサイクル管理について解説します。

PrometheusメインサーバーはGo言語で書かれており、cmd/prometheus/main.goがエントリーポイントです。サーバーは複数の独立したコンポーネントで構成され、各コンポーネントは別々のgoroutineグループで実行されます。

2. メインサーバーコンポーネント

2.1 全体アーキテクチャ

Prometheusサーバーは以下のコアコンポーネントで構成されます:

                    +-----------------+
                    |   Web UI/API    |
                    +--------+--------+
                             |
              +--------------+--------------+
              |              |              |
     +--------v---+  +------v------+  +----v-------+
     | Scrape     |  | Rule        |  | Notifier   |
     | Manager    |  | Manager     |  | (Alertmgr) |
     +--------+---+  +------+------+  +----+-------+
              |              |              |
              +--------------+--------------+
                             |
                    +--------v--------+
                    |     TSDB        |
                    +-----------------+
                             |
                    +--------v--------+
                    | Discovery       |
                    | Manager         |
                    +-----------------+

2.2 コンポーネント別役割

Scrape Manager: ターゲットからメトリクスを収集するコアエンジンです。Discovery Managerからターゲットリストを受け取り、各ターゲットに対するスクレイピングループを管理します。

TSDB(Time Series Database): 時系列データの保存とクエリを担当します。WAL、Head Block、Persistent Blockで構成される階層的ストレージです。

Rule Manager: Recording RuleとAlerting Ruleを定期的に評価します。評価結果はTSDBに記録されるか、Notifierに転送されます。

Notifier: アクティブなアラートをAlertmanagerに転送するコンポーネントです。

Web UI/API: HTTPサーバーとして、PromQLクエリエンドポイント、管理API、組み込みUIを提供します。

Discovery Manager: 様々なサービスディスカバリソースからターゲットを発見し、Scrape Managerに転送します。

3. Goroutineモデルとライフサイクル管理

3.1 Actor/Run Groupパターン

Prometheusはoklog/runライブラリのRun Groupパターンを使用してコンポーネントのライフサイクルを管理します。各コンポーネントは2つの関数で登録されます:

// 各コンポーネントは(execute, interrupt)ペアで登録
g.Add(
    func() error {
        // execute: コンポーネントのメインロジック実行
        return component.Run(ctx)
    },
    func(err error) {
        // interrupt: 終了時のクリーンアップ
        component.Stop()
    },
)

Run Groupのコア動作原理:

  1. すべてのコンポーネントのexecute関数が同時に開始されます
  2. いずれかのexecute関数がエラーを返すか終了すると、他のすべてのコンポーネントのinterrupt関数が呼ばれます
  3. すべてのexecute関数が返るまで待機します

このパターンはgraceful shutdownを自然に実装します。例えばSIGTERMを受信するとシグナルハンドラのexecuteが返り、それに伴い他のすべてのコンポーネントが順次終了します。

3.2 主要Goroutineグループ

main goroutine
  |
  +-- Signal Handler goroutine
  +-- Scrape Discovery Manager goroutine
  +-- Notify Discovery Manager goroutine
  +-- Scrape Manager goroutine
  +-- Rule Manager goroutine
  +-- TSDB goroutine
  +-- Web Handler goroutine
  +-- Notifier goroutine
  +-- Remote Storage goroutine

各goroutineは独立して実行され、チャネルや同期プリミティブを通じて通信します。

3.3 コンポーネント初期化順序

初期化は依存関係の順序に従って進行します:

  1. TSDB初期化: ストレージが最初に準備される必要があります
  2. Discovery Manager開始: ターゲット検索が開始されます
  3. Scrape Manager開始: Discovery Managerのターゲットを受信してスクレイピングを開始します
  4. Rule Manager開始: ルール評価を開始します
  5. Notifier開始: アラート送信を準備します
  6. Web Handler開始: HTTPサーバーが最後に起動してリクエストを受信します

4. 設定リロードメカニズム

4.1 リロードトリガー

Prometheusは2つの方法で設定をリロードできます:

SIGHUPシグナル: OSシグナルによるリロード

kill -HUP $(pidof prometheus)

HTTP API: --web.enable-lifecycleフラグ有効化時に使用可能

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

4.2 リロードプロセス

設定リロードはreloadConfig関数で処理されます。全体フローは以下の通りです:

1. SIGHUP受信または/-/reload呼び出し
2. prometheus.ymlファイルパース
3. 設定のバリデーション
4. 各コンポーネントに新設定を伝播:
   a. Remote Storage設定更新
   b. Notifier設定更新
   c. Discovery Manager設定更新
   d. Scrape Manager設定更新
   e. Rule Manager設定更新
   f. Web Handler設定更新
5. リロード成功/失敗メトリクス更新

4.3 コンポーネント別リロード動作

Scrape Manager: 既存のスクレイピングプールと新設定の差分を計算します。変更されたジョブのみ再生成し、変更のないジョブはそのまま維持して不要な中断を最小化します。

Rule Manager: すべてのルールグループを再生成します。既存ルールの状態(アラート状態など)を新ルールに復元します。

Discovery Manager: 新しいサービスディスカバリ設定を適用します。変更のないプロバイダは再利用します。

Notifier: Alertmanagerエンドポイント設定を更新します。

4.4 リロード失敗時の処理

設定ファイルのパースやバリデーションに失敗した場合、リロードは中断され既存の設定が維持されます。リロード失敗はprometheus_config_last_reload_successfulメトリクスで監視できます:

prometheus_config_last_reload_successful == 0

5. ターゲットディスカバリパイプライン

5.1 全体フロー

ターゲットが発見されてスクレイピングされるまでの全パイプライン:

Service Discovery Provider
        |
        v
Discovery Manager (target groups)
        |
        v
Scrape Manager (apply relabel_configs)
        |
        v
Scrape Pool (per job)
        |
        v
Scrape Loop (per target)
        |
        v
HTTP GET /metrics
        |
        v
TSDB Appender

5.2 Discovery Manager

Discovery Managerは複数のサービスディスカバリプロバイダを統合管理します:

kubernetes_sd_config --|
consul_sd_config    --|-->  Discovery Manager  -->  Target Groups Channel
file_sd_config      --|
static_config       --|

各プロバイダは別のgoroutineで実行され、ターゲットグループの変更をチャネルで転送します。Discovery Managerはこれを収集してScrape Managerに転送します。

プロバイダの更新は一定時間(デフォルト5秒)バッファリングされた後、一括転送されます。これにより頻繁な変更が発生してもScrape Managerに過度な負荷がかかりません。

5.3 Scrape Manager

Scrape ManagerがDiscovery Managerからターゲットグループを受信すると:

  1. 各scrape jobに対応するScrape Poolを検索します
  2. 新しいターゲットにrelabel_configsを適用します
  3. リラベリング結果に従いターゲットを保持または削除します
  4. 新ターゲットのScrape Loopを生成します
  5. 消失したターゲットのScrape Loopを終了します

5.4 Scrape Pool

Scrape Poolは同一scrape jobに属するターゲットのグループです。各Poolは以下を管理します:

  • アクティブターゲットリスト
  • ドロップされたターゲットリスト(デバッグ用)
  • 共通スクレイピング設定(間隔、タイムアウト、メトリクスパスなど)

5.5 Scrape Loop

各ターゲットに対して1つのScrape Loopがgoroutineとして実行されます:

Scrape Loopサイクル:
1. scrape_interval待機
2. HTTP GETリクエスト送信(scrape_timeout以内)
3. レスポンスパース(Prometheus Exposition Format)
4. metric_relabel_configs適用
5. TSDBにサンプル記録
6. upメトリクス更新(1=成功、0=失敗)
7. scrape_duration_secondsなど内部メトリクス更新
8. 1に戻る

6. HTTPクライアント設定とTLS

6.1 HTTPクライアント構成

各スクレイピングターゲットのHTTPクライアントはscrape job設定に従って構成されます:

scrape_configs:
  - job_name: 'secure-targets'
    scheme: https
    tls_config:
      ca_file: /path/to/ca.pem
      cert_file: /path/to/cert.pem
      key_file: /path/to/key.pem
      insecure_skip_verify: false
    basic_auth:
      username: admin
      password_file: /path/to/password
    authorization:
      type: Bearer
      credentials_file: /path/to/token

6.2 TLS設定

Prometheusは様々なTLS設定をサポートします:

  • CA証明書: サーバー証明書検証用
  • クライアント証明書: mTLS(相互TLS)認証用
  • サーバー名検証: server_nameフィールドでSNI設定
  • 証明書自動更新: ファイルベースの資格情報は定期的に再読み込み

6.3 認証メカニズム

Prometheusは複数の認証方式をサポートします:

  • Basic Auth: ユーザー名/パスワードベース
  • Bearer Token: OAuth2トークンなど
  • OAuth2 Client: クライアント資格情報フローサポート
  • AWS SigV4: AWSサービスアクセス用

資格情報ファイル(password_file、credentials_fileなど)は各スクレイピングサイクルごとに再読み込みされるため、ファイルを更新すればPrometheus再起動なしに資格情報を変更できます。

7. 内部メトリクス

7.1 主要セルフモニタリングメトリクス

Prometheusは自身の動作を監視するための様々な内部メトリクスを公開します:

スクレイピング関連:

  • prometheus_target_scrape_pool_targets: 各スクレイピングプールのターゲット数
  • prometheus_target_scrapes_exceeded_sample_limit_total: サンプル制限超過回数
  • scrape_duration_seconds: スクレイピング所要時間
  • scrape_samples_scraped: スクレイピングされたサンプル数

TSDB関連:

  • prometheus_tsdb_head_series: Head Blockの時系列数
  • prometheus_tsdb_head_samples_appended_total: 追加されたサンプル数
  • prometheus_tsdb_compactions_total: コンパクション実行回数
  • prometheus_tsdb_wal_corruptions_total: WAL破損回数

ルール評価関連:

  • prometheus_rule_evaluation_duration_seconds: ルール評価所要時間
  • prometheus_rule_group_last_duration_seconds: 最後のルールグループ評価時間

設定関連:

  • prometheus_config_last_reload_successful: 最後のリロード成功可否
  • prometheus_config_last_reload_success_timestamp_seconds: 最後の成功時刻

7.2 パフォーマンスチューニング指標

本番環境でモニタリングすべき重要指標:

1. スクレイピング遅延: scrape_duration_seconds > scrape_interval
   - スクレイピングが設定間隔より長くかかるとデータ欠損の可能性

2. 時系列カーディナリティ: prometheus_tsdb_head_series
   - 急激な増加はカーディナリティ爆発のシグナル

3. ルール評価遅延: prometheus_rule_group_last_duration_seconds > evaluation_interval
   - ルール評価が間隔を超えるとアラート遅延が発生

4. WALサイズ: prometheus_tsdb_wal_segment_current
   - 異常に大きなWALはコンパクション問題のシグナル

8. Prometheus Operatorとの統合

8.1 Prometheus Operatorアーキテクチャ

Kubernetes環境ではPrometheusは主にPrometheus Operatorを通じてデプロイされます:

Prometheus Operator
  |
  +-- watches Prometheus CRD
  |     |
  |     +-- generates prometheus.yml
  |     +-- manages StatefulSet
  |
  +-- watches ServiceMonitor CRD
  |     |
  |     +-- converts to scrape_configs
  |
  +-- watches PodMonitor CRD
  |     |
  |     +-- converts to scrape_configs
  |
  +-- watches PrometheusRule CRD
        |
        +-- converts to rule files

8.2 Config Reloaderサイドカー

Prometheus Operatorはconfig-reloaderサイドカーコンテナを使用して設定変更を自動検知し、Prometheusにリロードリクエストを送信します:

1. OperatorがConfigMap/Secretを更新
2. Config Reloaderがマウントされたファイル変更を検知
3. /-/reload POSTリクエスト送信
4. Prometheusが新設定を適用

このサイドカーはinotify(Linux)ベースでファイル変更を監視し、定期的なポーリングもフォールバックとして実行します。

9. パフォーマンス最適化のヒント

9.1 スクレイピング最適化

  • scrape_interval調整: メトリクス変化速度に合った間隔設定。短すぎると負荷増加、長すぎると精度低下
  • sample_limit設定: ターゲット別最大サンプル数制限でカーディナリティ爆発防止
  • metric_relabel_configs: 不要なメトリクスをスクレイピング後に即座に削除

9.2 TSDB最適化

  • --storage.tsdb.min-block-duration: Head Blockの最小保持時間(デフォルト2h)
  • --storage.tsdb.max-block-duration: ブロックの最大サイズ(デフォルト時間の10%または31日)
  • --storage.tsdb.wal-compression: WAL圧縮有効化でディスクI/Oを削減

9.3 クエリ最適化

  • --query.max-concurrency: 同時クエリ数制限(デフォルト20)
  • --query.timeout: クエリタイムアウト設定(デフォルト2分)
  • --query.max-samples: クエリあたりの最大サンプル数制限(デフォルト5千万)

10. まとめ

Prometheusサーバーの内部アーキテクチャは、Goの並行性モデルを活用したクリーンな設計を示しています。Run Groupパターンによるライフサイクル管理、チャネルベースのコンポーネント間通信、パイプライン形式のデータフローが核心です。

次の記事ではTSDBの内部構造をより深く分析します。WALのセグメント構造、チャンクエンコーディング、ブロックコンパクションアルゴリズムなどをソースコードレベルで解説する予定です。