Cloud Spannerの裏側:リソース使用量メトリクスパイプラインの深層と実戦的キャパシティ設計
こんにちは。テックリードの私だ。
今日のコードレビュー、あるいはアーキテクチャレビューで、またこんな質問を受け流したのではないか?
> 「SpannerのCPU使用率がスパイクしたんですけど、アラートが発報されるまでにタイムラグがあるのはなぜですか?あと、このメトリクスってどこからどうやって取られているんですか?」
Google Cloud Spannerは「ほぼ無限のスケール」と「強整合性」を両立させた怪物的なデータベースだが、その内部で稼働するメトリクス収集・集約パイプラインの挙動を正確に理解しているエンジニアは、意外と少ない。
リファレンスをただ引き写したような「Cloud Spannerはマネージドなので自動で監視できます」といったお遊戯レベルの説明は、ここでは一切しない。今回は、各Spannerノードの深部から、Cloud Monitoring、そして我々のダッシュボードやアラートに届くまでの「メトリクスパイプラインの全経路」を解剖し、現場の設計にどう活かすべきかをロジカルに伝授しよう。
—
1. メトリクスパイプラインの全体像:エッジからクラウド監視への旅
Spannerのノード(正確にはスプリットをホストするタスク群)は、常に膨大な量のテレメトリーデータを生成している。CPU、メモリ(B-treeキャッシュのヒット率やアロケーション)、ストレージ、そしてトランザクションのレイテンシや競合状況だ。
これらが監視システムに集約されるまでの経路は、ざっくりと以下の4階層に分かれる。
[ Spanner Node (Split / Paxos Group) ]
│
▼ (1. インプロセス・テレメトリー収集: 数秒周期)
[ ローカル・モニタリングエージェント / ブルドーザー ]
│
▼ (2. ストリーミング / プル型アグリゲーション)
[ グローバル・テレメトリー・コレクター群 ]
│
▼ (3. Cloud Monitoring 時系列DBへの書き込み)
[ Cloud Monitoring API / Time Series Store ]
│
▼ (4. 評価・可視化)
[ Alerting Policies / Grafana / Cloud Console ]
① インプロセス・テレメトリー収集(数秒周期)
各Spannerのプロセス内部では、C++ / GoベースのランタイムがCPUサイクル、メモリプール、ストレージI/O(Colossus基盤との通信)をミリ秒単位でフックしている。このデータは、そのまま外部に垂れ流されるわけではない。パフォーマンスペナルティを最小限にするため、一度ローカルのメモリ上のアグリゲータに溜め込まれる。
② ローカルエージェントからコレクターへ
Spannerはマルチテナントかつ分散配置された Borg(Google内部のオーケストレータ)のコンテナ上で動いている。各ノードのサイドカー的役割を持つモニタリングエージェントが、数秒〜数十秒の粒度でメトリクスをスクレイピング(あるいはプッシュ)し、Googleのインフラストラクチャ共通のテレメトリーパイプラインへと流し込む。
③ Cloud Monitoringへの流し込み
ここで重要な事実がある。Cloud Monitoringで我々が目にするメトリクスは、完全なリアルタイム(0秒遅延)ではない。
内部パイプラインでのバッチ集約、転送、時系列データベース(TSDB)へのインデックス作成のプロセスを経るため、一般的に30秒〜1分程度の遅延(Lag)が存在する。
—
2. 実務で知るべき「メトリクスの罠」とパフォーマンス上の注意点
このパイプライン構造を理解していないと、現場で痛い目を見る。テックリードとして、以下の3つの「罠」をチームに叩き込んでおいてほしい。
罠A:高負荷時の「メトリクス遅延・欠損」の可能性
CPU使用率が95%を超え、ノードが過負荷(Overloaded)に陥ったとき何が起きるか?
当然、Spannerの処理エンジンがリクエストの処理で手一杯になる。それに伴い、モニタリングエージェントがメトリクスを収集・送信するリソースすら圧迫され、メトリクス自体の遅延が拡大したり、一時的にデータが間引かれたりすることがある。「最も監視したい瞬間に、メトリクスが正確に見えない」という分散システムのジレンマだ。
> 【対策】
> CPU使用率が100%に張り付くのを待つのではなく、`High Priority CPU` が 65%〜70% を超えた段階でスケールアウト(ノード追加)またはクエリ最適化のシグナルとせよ。限界ギリギリを攻める設計はアマチュアのやることだ。
罠B:高カーディナリティの罠(Custom Metrics / SQL Insights)
Spannerの標準メトリクス(`cpu/utilization`など)は最適化されているが、Query Insightsなどでクエリごとの統計を扱う際、開発者がやってはいけないのが「プレースホルダーを使わずにリテラル値を埋め込んだクエリを大量発行する」ことだ。
これにより、監視基盤側のカーディナリティ(種類の数)が爆発し、メトリクスパイプライン自体が目詰まりを起こすか、コストが跳ね上がる。
> 【対策】
> アプリケーション層でのSQLパラメータ化は、データベースのプランキャッシュを守るだけでなく、監視パイプラインの崩壊を防ぐためにも必須である。
—
3. 堅牢な設計パターン:アラートとオートスケーリングのベストプラクティス
では、このメトリクスパイプラインの特性を踏まえ、本番環境でどういう設計をすべきか。具体的な指針を示す。
① アラート評価期間(Duration)のチューニング
Cloud Monitoringでアラートを設定する際、次のような設定をしていないか?
> 「CPU使用率 > 80% が 1分間 続いたらPagerDutyを鳴らす」
これは悪手だ。Spannerのメトリクスパイプラインの収集遅延(数十秒)と、ガベージコレクションや一時的なスプリットの移動に伴う一時的なスパイクを考慮すると、誤検知(False Positive)の嵐になる。
【推奨する設計】
Terraformでのアラートポリシー定義イメージ(抜粋)
condition {
display_name = “Spanner High CPU Utilization”
condition_threshold {
filter = “resource.type = \”spanner_instance\” AND metric.type = \”spanner.googleapis.com/instance/cpu/utilization\””
duration = “300s” # 最低でも5分間の継続を見る
comparison = “COMPARISON_GT”
threshold_value = 0.75
aggregations {
alignment_period = “60s”
per_series_aligner = “ALIGN_MEAN”
cross_series_reducer = “REDUCE_MAX”
}
}
}
`duration = “300s”`(5分) とし、一過性のスパイクを無視して「真の負荷トレンド」を捉えるのがプロの技だ。
② カスタムヘルスチェックとの併用
Cloud Monitoringのメトリクスを待つまでもない致命的な障害(コネクション枯渇やデッドロックの連鎖など)に備えるため、アプリケーション層から `SELECT 1` などを定期発行する外形監視や、Spannerのトランザクションエラーレート(`api/request_count` の ABORTED ステータス監視)を並行して走らせよ。
—
4. チーフアーキテクトからのメッセージ
Cloud Spannerのメトリクスパイプラインは、Googleの巨大なインフラの恩恵を受けつつも、物理的なネットワークやCPUの制約から完全に自由ではない。
「メトリクスが画面に出ているからリアルタイムなのだ」という素朴な信仰を捨て、「データが生成され、エージェントを経由し、TSDBに集約されるまでにラグと負荷のトレードオフが存在する」という裏側のメカニズムをコードと設計に落とし込んでほしい。
確度の高いメトリクス監視こそが、夜中の不毛なアラート起因の叩き起こしを防ぎ、真にスケールするシステムを作り上げる。
次の設計レビューでは、君たちがこの知見をベースにした美しいアーキテクチャを持ち寄ることを期待している。
コメント