はじめに
私の参画している現場では数百台規模のハイブリッドクラウド環境(オンプレ+AWS)で広告配信基盤を運用しています。既にメトリクス基盤はVictoriaMetricsで運用していましたが、ログ基盤はELK Stack、トレースは未導入という状態でした。
本記事では、ELK StackからVictoriaLogsへの移行と、VictoriaTracesの新規導入を同時に行い、OSSだけでメトリクス・ログ・トレースの可観測性3本柱を統一した事例を紹介します。
こんな環境・課題を持つ方に刺さる記事です
- EC2ベースでサービスを運用しているが、Datadog等のSaaSはコスト的に厳しい
- ELK Stackを使っているが、JVMの運用に疲弊している
- メトリクスはPrometheus/VictoriaMetricsで取れているが、ログとトレースが弱い
- コンテナ環境(ECS/EKS)でも、サイドカーやDaemonSetでログ・トレースを収集しているが、バックエンドのコストを下げたい
- 「Datadogは高い、でもCloudWatch Logsだけでは物足りない」というジレンマを抱えている
VictoriaLogs/Tracesはsystemdでもコンテナでも動作するGoバイナリなので、EC2直接運用でもK8s上のPodとしても同じように使えます。本記事ではsystemdでの構成例を紹介しますが、Helmチャートも公式で提供されておりK8s環境への適用も容易です。
なぜ移行したか
ELK Stack(Elasticsearch 7.13)には以下の課題がありました。
- JVMヒープ管理の煩雑さ: GCチューニングやヒープサイズの調整が定期的に必要
- 設定変更がAPI経由のみ: Elasticsearch独自のREST APIでしか設定変更ができず、IaCとの相性が悪い
- 構成のいびつさ: master+replicaの3台クラスタだが、masterしかELBからログを受け取っておらず、インスタンスタイプも不均一
- 用途の限定: 変更監査ログの収集にしか使われておらず、Grafanaのデータソースとして活用されていなかった
SaaS(Datadog Logs/APM)を選ばなかった理由
数百台規模の環境でDatadog Logsを導入すると、インジェスト量とリテンションのコストが膨大になります。概算で月額数百万円規模。一方、VictoriaLogsはOSSでライセンスコストゼロ、かつGoバイナリで省リソース動作するため、EC2 2台分のインフラコストのみで済みます。
また、既にVictoriaMetricsでメトリクス基盤を運用しており、同じVictoria製品群で統一することで以下のメリットがありました。
- 運用ノウハウの共有(設定体系、バイナリ管理、バックアップ方式が同じ)
- Grafanaデータソースとしての統合(メトリクス・ログ・トレースを横断クエリ可能)
- JVMが不要(Goバイナリのため、ヒープ管理から完全に解放)
アーキテクチャ設計
全体構成
┌─────────────────────────────────────────────────┐
│ NLB │
│ (logs.example.com / traces.example.com) │
└──────────┬──────────────────────┬───────────────┘
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ EC2 #1 │ │ EC2 #2 │
│ │ │ │
│ ┌─────────┐ │ │ ┌─────────┐ │
│ │ vmauth │ │ │ │ vmauth │ │
│ └────┬────┘ │ │ └────┬────┘ │
│ │ │ │ │ │
│ ┌────▼────┐ │ │ ┌────▼────┐ │
│ │vlinsert │ │ │ │vlinsert │ │
│ │vlselect │ │ │ │vlselect │ │
│ │vlstorage│ │ │ │vlstorage│ │
│ └─────────┘ │ │ └─────────┘ │
│ │ │ │
│ ┌─────────┐ │ │ ┌─────────┐ │
│ │vtinsert │ │ │ │vtinsert │ │
│ │vtselect │ │ │ │vtselect │ │
│ │vtstorage│ │ │ │vtstorage│ │
│ └─────────┘ │ │ └─────────┘ │
└─────────────┘ └─────────────┘
VictoriaLogs クラスタ構成
VictoriaLogsはクラスタモードで動作し、3つのコンポーネントに分離されます。
| コンポーネント | 役割 | ポート |
|---|---|---|
| vlinsert | ログの書き込み受付 | 9481 |
| vlselect | ログのクエリ処理 | 9471 |
| vlstorage | ログの永続化 | 9491 |
| vmauth | ルーティング(insert/selectの振り分け) | 8427 |
vmauth がフロントに立ち、パスベースでリクエストを振り分けます。
# vmauth-config.yml
unauthorized_user:
url_map:
# 書き込み系(jsonline, loki, elasticsearch bulk等)
- src_paths:
- "/insert/.*"
url_prefix:
- "http://node1:9481/"
- "http://node2:9481/"
# 読み取り系(Grafana, Web UI, API)
- src_paths:
- "/select/.*"
url_prefix:
- "http://node1:9471/"
- "http://node2:9471/"
VictoriaTraces 同居構成
VictoriaTracesも同じクラスタ構成(vtinsert/vtselect/vtstorage)で、VictoriaLogsと同一EC2上に同居させています。
| コンポーネント | 役割 | ポート |
|---|---|---|
| vtinsert | トレースの書き込み受付(OTLP互換) | 10481 |
| vtselect | トレースのクエリ処理 | 10471 |
| vtstorage | トレースの永続化 | 10491 |
FQDNの分離による拡張性の担保
同一NLB・EC2に同居させていますが、FQDNは分離しています。
-
logs.example.com→ VictoriaLogs(vmauth経由) -
traces.example.com→ VictoriaTraces(vtinsert直接)
将来的にトラフィックが増加した場合、FQDNの向き先を変えるだけでスケールアウトできる設計です。
実装のポイント
systemdネイティブ(K8s不採用の判断)
VictoriaLogs/TracesはGoの単一バイナリで動作するため、systemdで十分にプロセス管理できます。
K8sを不採用とした理由:
- チームにK8s運用経験者が少なく、認知負荷が高い
- 人の入れ替わりが多い環境で、Goバイナリ+systemdのシンプルさを損なわない構成を優先
- VictoriaMetrics(メトリクス基盤)も同じsystemd構成で運用しており、運用体系を統一
# vlinsert.service
[Unit]
Description=VictoriaLogs vlinsert
After=network.target vlstorage.service
[Service]
Type=simple
ExecStart=/usr/local/bin/victoria-logs-prod \
-httpListenAddr=:9481 \
-storageNode=node1:9491,node2:9491 \
-select.disable
Restart=always
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
ログ→トレースの紐付け(TraceID)
アプリケーション側で構造化ログにTraceIDを埋め込むことで、Grafana上でログからトレースへのジャンプが可能になります。
{
"timestamp": "2026-05-28T10:00:00Z",
"level": "info",
"message": "request processed",
"trace_id": "abc123def456",
"service": "ad-server",
"duration_ms": 42
}
Grafana側でVictoriaLogsのデータソース設定に「Derived fields」を追加し、trace_id フィールドからVictoriaTracesへのリンクを生成します。これにより、ログの1行からワンクリックでトレースの詳細画面に遷移できます。
Grafanaでの統合
可観測性3本柱の統一
Grafanaのデータソースとして以下を登録:
| データソース | 製品 | 用途 |
|---|---|---|
| VictoriaMetrics | メトリクス | リソース使用率、SLI |
| VictoriaLogs | ログ | エラーログ、監査ログ |
| VictoriaTraces | トレース | リクエストの分散トレーシング |
これにより、1つのGrafanaダッシュボード上で:
- メトリクスの異常を検知 → 該当時間帯のログを確認 → トレースで原因箇所を特定
というシグナル間の相関分析がSaaSなしで実現できます。
SLO定義への活用
VictoriaTracesのデータを使って、サービスごとのレイテンシやエラー率をSLI(Service Level Indicator)として定義できます。Datadog APMと同等のSLO管理を、OSSの組み合わせで実現しています。
コスト比較
Before(ELK Stack)
| インスタンス | 台数 | 用途 | 月額概算 |
|---|---|---|---|
| t3.large(8GiB) | 1台 | Elasticsearch master | 約$67 |
| t3.small(2GiB) | 2台 | Elasticsearch replica | 約$34 |
| 合計 | 3台 | 約$101/月 |
※トレース基盤はなし
After(VictoriaLogs + VictoriaTraces)
| インスタンス | 台数 | 用途 | 月額概算 |
|---|---|---|---|
| t4g.medium(4GiB) | 2台 | VictoriaLogs + VictoriaTraces 同居 | 約$54 |
| 合計 | 2台 | 約$54/月 |
※ログ基盤に加えてトレース基盤も新規追加した上でこのコスト
削減効果
- インフラコスト: 約47%削減($101→$54/月、年間約$564削減)
- 機能面: トレース基盤を追加(ELK時代はログのみ → ログ+トレースの2本柱に)
- 運用コスト: JVMヒープ管理から完全に解放
つまり、コストを半減させながら、可観測性を大幅に強化したことになります。
Datadog Logs/APMとの概算比較
数百台規模で1日あたり数GBのログインジェストを想定すると、Datadog Logsだけで月額数十万〜数百万円規模になります。VictoriaLogs/Tracesであれば、EC2 2台分のコスト(月額約$54)で同等の機能を実現できます。
実際のリソース使用状況
t4g.medium(4GiB)での実測値:
- RAM Used: 約900MiB
- RAM Cache+Buffer: 約1.4GiB
- RAM Free: 約1.2GiB
Goバイナリの省メモリ性能により、実使用量は1GB未満に収まっています。t4g.small(2GiB)でも動作する可能性はありますが、ファイルシステムキャッシュの効きを考慮してmediumを選択しています。
まとめ
- ELK StackからVictoriaLogsへの移行により、JVMヒープ管理から解放され、運用がシンプルに
- VictoriaTracesの新規導入により、分散トレーシングを追加コストほぼゼロで実現
- Victoria製品群での統一により、メトリクス・ログ・トレースの3本柱をGrafana上で横断的に分析可能に
- SaaSに頼らず、OSSだけでフルスタックオブザーバビリティを安価に構築できることを実証
VictoriaLogs/Tracesはまだ日本語の情報が少ないですが、VictoriaMetricsを既に使っている環境であれば、運用体系を統一しつつ可観測性を大幅に強化できる選択肢です。