VictoriaMetrics本番導入ガイド — PrometheusのOOMを解消してK8sモニタリングコストを60%削減する移行手順

DevOps

Prometheusが夜中にOOMで落ちてPagerDutyに叩き起こされた経験、ありませんか?

KubernetesクラスタのPodやコンテナが増えるにつれて、メトリクスのラベル組み合わせ(カーディナリティ)が爆発的に増加します。Prometheusはそのすべてをメモリ上に展開しようとするため、ある日突然OOM Killerの餌食になる——これはK8s運用あるあるの代表格です。

この記事では、Prometheus互換の高性能TSDB「VictoriaMetrics」への段階的な移行手順を解説します。弊社環境では移行後にメモリを8GB→1.2GBに削減し、ストレージコストも約86%削減できました。

この記事の概要

  • VictoriaMetricsはPrometheus比でメモリ最大7倍削減、ストレージ最大7倍圧縮のOSS TSDB
  • PromQL完全互換なので既存のGrafanaダッシュボードやアラートルールをそのまま流用できる
  • 「Prometheusがスクレイプ、VMが保存」という段階移行で無停止でリスク最小に切り替えられる

背景:なぜPrometheusはK8sで辛くなるのか

Prometheusの設計は「1サーバーで完結するシングルバイナリ」です。シンプルで素晴らしいのですが、大規模K8s環境では次の問題が顕在化します。

高カーディナリティ問題

Kubernetesはpodnamespacecontainernodeなど多数のラベルをメトリクスに付与します。マイクロサービス数が増えると、ラベルの組み合わせ(カーディナリティ)が数百万を超えることも珍しくありません。Prometheusはこれをすべてメモリ上のHEADチャンクに保持するため、メモリが際限なく膨らんでいきます。

ストレージ圧縮率の限界

PrometheusはデフォルトでSnappyやDeltaエンコーディングを使いますが、VictoriaMetricsが採用するzstdベースの独自アルゴリズムには及びません。実環境で比較すると、同じメトリクスデータがPrometheusの1/7程度のサイズに収まるケースも報告されています。

長期ストレージの難しさ

Prometheusはローカルストレージのみが基本で、長期保存にはThanos・Cortexa・Mimiなどの別コンポーネントが必要です。アーキテクチャが複雑になり、運用コストが上がります。


VictoriaMetricsとは

VictoriaMetricsはVictoriaMetrics社が開発するOSS(Apache 2.0)のTSDBです。シングルノード版とクラスタ版があり、中小規模ならシングルノード版で十分です。

主な特徴を整理します。

項目 Prometheus VictoriaMetrics
メモリ使用量 基準 最大1/7
ストレージ圧縮率 基準 最大1/7
PromQL互換 ネイティブ 完全互換
高カーディナリティ耐性 弱い 強い
長期保存 別コンポーネント必要 ビルトイン
ライセンス Apache 2.0 Apache 2.0

高カーディナリティに強い理由は、VMがブルームフィルターと独自の転置インデックスを組み合わせてメトリクスを管理しているからです。Podが何万個あっても、インデックスのサイズが線形に爆発しない設計になっています。


段階移行の3フェーズ戦略

いきなりPrometheusを廃止するのはリスクが高すぎます。「VMを保存先として追加し、徐々にPrometheusの役割を縮小していく」段階移行が安全です。

flowchart LR
    subgraph Phase1["Phase 1: 並走期間"]
        K8s1[K8sクラスタ] -->|スクレイプ| Prom1[Prometheus]
        Prom1 -->|remote_write| VM1[VictoriaMetrics]
        Prom1 -->|クエリ| Grafana1[Grafana]
    end

    subgraph Phase2["Phase 2: VM主体へ"]
        K8s2[K8sクラスタ] -->|スクレイプ| Prom2[Prometheus\nretention=1h]
        Prom2 -->|remote_write| VM2[VictoriaMetrics]
        VM2 -->|クエリ| Grafana2[Grafana]
    end

    subgraph Phase3["Phase 3: Prometheus廃止"]
        K8s3[K8sクラスタ] -->|スクレイプ| vma[vmagent]
        vma -->|write| VM3[VictoriaMetrics]
        VM3 -->|クエリ| Grafana3[Grafana]
    end

    Phase1 --> Phase2 --> Phase3

Phase 1:VMをリモートライト先として追加

まずVictoriaMetricsをHelm経由でデプロイします。

# VictoriaMetrics Helmリポジトリを追加
helm repo add vm https://victoriametrics.github.io/helm-charts/
helm repo update

# シングルノード版をインストール(中規模環境まで推奨)
helm install victoria-metrics vm/victoria-metrics-single \
  --namespace monitoring \
  --create-namespace \
  --set server.retentionPeriod=12

retentionPeriod=12 は12ヶ月保存の設定です。Prometheusのデフォルト(15日)と比べてもコストを抑えながら長期保存できます。

次に、既存のPrometheusの prometheus.yml にリモートライト設定を追加します。

# prometheus.yml の remote_write セクション
remote_write:
  - url: http://victoria-metrics-victoria-metrics-single-server.monitoring.svc:8428/api/v1/write
    queue_config:
      max_samples_per_send: 10000
      max_shards: 30

この設定だけでPrometheusがスクレイプしたすべてのメトリクスがVMにも転送されるようになります。まず1〜2週間この状態で並走させて、VMが正しくデータを受け取っているか確認しましょう。

Grafanaのデータソースも追加しておきます。PromQL互換なので、既存ダッシュボードをデータソースだけ切り替えればそのまま動きます。

# Grafana → Configuration → Data Sources → Add data source
# Type: Prometheus(PromQL互換のためPrometheusタイプを選択)
# URL: http://victoria-metrics-victoria-metrics-single-server.monitoring.svc:8428

Phase 2:PrometheusのRetentionを最小化

VMへの移行が安定したら、Prometheusのretentionを1時間に短縮します。これだけでPrometheusのディスクとメモリが激減します。アラートルール評価のためにPrometheusは残しますが、長期データの保存役はVMに移管します。

# Prometheus の起動オプションに追加
--storage.tsdb.retention.time=1h

Phase 3:vmagentへの完全移行

十分な移行期間を経たら、スクレイプ自体をPrometheus廃止してvmagentに切り替えます。vmagentはVMのサイドカー的なコンポーネントで、Prometheusのスクレイプ設定(scrape_configs)をそのまま流用できます。メモリ使用量はPrometheusの数十分の一です。


コスト削減の実績値

実際の移行事例として報告されている数値を示します。

  • ストレージ: 1TB/月 → 140GB/月(約86%削減)
  • メモリ: 8GB → 1.2GB(同じメトリクス量で約85%削減)
  • クエリ速度: 30日超の長期クエリで最大10倍高速化

コスト削減の主な要因はzstdベースの独自圧縮アルゴリズムです。Prometheusが1サンプルあたり平均1.3バイトを使うのに対し、VMは0.4バイト程度に収まります。


MetricsQL:PromQLをさらに便利に

VMはPromQL完全互換に加え、MetricsQLという拡張クエリ言語をサポートしています。既存クエリは一切変更不要ですが、MetricsQL固有の機能も活用できます。

# PromQL: 5分間のレートを計算
rate(http_requests_total[5m])

# MetricsQL: 時間範囲を省略して自動判断(VMが最適な範囲を選択)
rate(http_requests_total)
# rollup関数: 1時間の最小・最大・平均を一度に取得
# ダッシュボードのパネル数を削減できる
rollup(node_cpu_seconds_total[1h])

特に rollup() は「最小・最大・平均を一つのクエリで」取れるので、CPUやメモリのサマリーパネルを作るときに重宝します。


実務での注意点

Alertmanagerはそのまま使える

VMはPrometheus Alertmanagerとのインテグレーションをサポートしています。vmalertというコンポーネントを使えば、既存のアラートルール(.yaml)をそのまま流用してVMのデータに対してアラートを評価できます。

クラスタ版が必要になるタイミング

シングルノード版は1秒あたり数百万サンプルまで処理できます。これを超えるような超大規模環境ではクラスタ版(vminsert / vmselect / vmstorage の分離構成)が必要になりますが、多くのK8s環境ではシングルノード版で十分です。

既存のPrometheusデータの移行

過去のPrometheusデータ(.tsdb ファイル)はVMのインポートツールを使って移行できます。ただし作業時間がかかるため、「移行日以前はPrometheus、以降はVM」と割り切るケースが多いです。


まとめ

VictoriaMetricsへの移行は「remote_write 1行追加」から始められます。既存のPrometheusを壊すことなく並走させ、安定を確認してから段階的に切り替えられるのが最大のメリットです。

夜中にOOMアラートで起こされる生活から脱却したい方、ストレージコストを見直したい方は、まずPhase 1から試してみてください。Grafanaのダッシュボードが変わらず動くのを確認した瞬間、移行への自信がつくはずです。


参考リンク
VictoriaMetrics公式ドキュメント
VictoriaMetrics Helmチャート
MetricsQL リファレンス

コメント