Skip to content
Published on

Observabilityデータパイプラインのコスト最適化:サンプリング・フィルタリング・ティアリング戦略

Authors
  • Name
    Twitter

はじめに

Observabilityのコストがクラウドインフラ支出の上位項目に浮上している。2025年のグローバルObservability市場は285億ドルを突破し、2026年末には341億ドルに達する見込みだ。マイクロサービスの普及に伴い、トレースが全体コストの60〜70%を占め、ログが20〜30%を占める状況では、データ量に比例してコストが急増する。

しかし、単にデータを削減すれば良いわけではない。重要なのはシグナルとノイズを分離し、コストを抑えつつObservabilityの品質を維持することだ。

本記事では、OpenTelemetry Collectorを中心としたテレメトリパイプラインのコスト最適化戦略を、実践的な設定例とチェックリスト付きで解説する。

コスト構造の分析

シグナル別コスト比率

シグナルコスト比率主なコスト要因最適化の難易度
トレース60〜70%高カーディナリティ、大容量ペイロード
ログ20〜30%非構造化データ、フルテキストインデクシング
メトリクス5〜15%タイムシリーズのカーディナリティ爆発
プロファイル1〜5%CPU/メモリプロファイルのデータサイズ

コスト発生ポイント

[生成] --> [収集/転送] --> [処理/加工] --> [インデクシング] --> [保存] --> [クエリ]
  |            |              |             |            |          |
 SDK       ネットワーク     Collector      バックエンド  ストレージ  コンピュート
 オーバーヘッド  帯域幅       CPU/メモリ     I/O         ディスク/S3  クエリコスト

最適化の原則は「パイプラインのできるだけ上流で不要なデータを除去する」ことだ。生成段階で除去すれば後続のすべてのコストを削減できる。

サンプリング戦略

Head Sampling vs Tail Sampling

項目Head SamplingTail Sampling
決定タイミングトレース開始時(SDK)トレース完了後(Collector)
コスト削減率高い(帯域幅も節約)中程度
データ品質低い(エラー漏れの可能性)高い(エラー/高レイテンシ100%保持)
実装の複雑さ低い高い(メモリ、ルーティング必要)
適用シナリオ非クリティカルサービス本番のコアサービス

Tail Sampling実践設定

# OpenTelemetry Collector - Tail Sampling設定
processors:
  tail_sampling:
    decision_wait: 30s
    num_traces: 100000
    expected_new_traces_per_sec: 1000
    policies:
      # エラーのあるトレースは100%保持
      - name: error-policy
        type: status_code
        status_code:
          status_codes:
            - ERROR

      # 500ms以上のレイテンシは100%保持
      - name: latency-policy
        type: latency
        latency:
          threshold_ms: 500

      # 決済・認証など重要サービスは100%保持
      - name: critical-service-policy
        type: string_attribute
        string_attribute:
          key: service.name
          values:
            - payment-service
            - auth-service

      # その他の正常トレースは5%のみ
      - name: normal-traffic-policy
        type: probabilistic
        probabilistic:
          sampling_percentage: 5

2-Tier Collectorアーキテクチャ

本番環境でTail Samplingを安定的に運用するには、Agent CollectorとGateway Collectorを分離する構成が必須だ。

[サービス] --OTLP--> [Agent Collector (DaemonSet)]
                          |
                    トレースIDベースルーティング
                          |
                    [Gateway Collector] --> [Tempo/Jaeger]
                    (Tail Sampling実行)

ログフィルタリングパイプライン

レベルベースフィルタリング

本番環境でDEBUG/TRACEレベルのログをCollectorでドロップすると、通常30〜50%のログ量を削減できる。

processors:
  # DEBUG/TRACEログのドロップ
  filter/drop-debug:
    error_mode: ignore
    logs:
      log_record:
        - 'severity_number < SEVERITY_NUMBER_INFO'

  # ヘルスチェックログのドロップ
  filter/drop-healthcheck:
    error_mode: ignore
    logs:
      log_record:
        - 'IsMatch(body, ".*GET /health.*")'
        - 'IsMatch(body, ".*GET /readyz.*")'
        - 'IsMatch(body, ".*kube-probe.*")'

  # 不要な属性の除去でペイロード削減
  transform/reduce-attributes:
    error_mode: ignore
    log_statements:
      - context: log
        statements:
          - delete_key(attributes, "log.file.path")
          - delete_key(attributes, "log.iostream")
          - truncate_all(attributes, 256)
          - limit(attributes, 20)

フィルタリング効果の測定

# Collector内部メトリクスでフィルタリング効果を測定
RECEIVED=$(curl -s http://localhost:8888/metrics | \
  grep 'otelcol_receiver_accepted_log_records' | \
  awk '{sum += $2} END {print sum}')

EXPORTED=$(curl -s http://localhost:8888/metrics | \
  grep 'otelcol_exporter_sent_log_records' | \
  awk '{sum += $2} END {print sum}')

if [ "$RECEIVED" -gt 0 ]; then
  DROP_RATE=$(echo "scale=2; (1 - $EXPORTED / $RECEIVED) * 100" | bc)
  echo "受信ログ: $RECEIVED"
  echo "送信ログ: $EXPORTED"
  echo "ドロップ率: ${DROP_RATE}%"
fi

メトリクスカーディナリティ管理

カーディナリティ爆発はObservabilityコストを予測不能にする主要因だ。

危険なパターンと対策

危険パターン対策
ユーザーIDをラベルに使用user_id="u12345"ラベル除去、ログ/トレースに移動
リクエストパスの原文path="/api/users/12345"パス正規化 path="/api/users/:id"
Pod名pod="web-7f8c9-xk2m"Deployment名のみ使用
エラーメッセージ全文error="Connection refused: 10.0.1.42"エラーコードで分類

Collector側でのカーディナリティ制御

processors:
  # メトリクス属性の変換でカーディナリティを制御
  transform/normalize-url:
    error_mode: ignore
    metric_statements:
      - context: datapoint
        statements:
          - replace_pattern(attributes["url.path"], "^/api/users/[^/]+", "/api/users/:id")
          - replace_pattern(attributes["url.path"], "^/api/orders/[^/]+", "/api/orders/:id")
          - delete_key(attributes, "user.id")
          - delete_key(attributes, "request.id")

ストレージティアリング

データの経過時間に応じてストレージ層を自動的に移行するHot/Warm/Coldアーキテクチャで、長期保存コストを大幅に削減できる。

ティア保持期間ストレージクエリ性能コスト
Hot0〜7日SSD/NVMe最高速
Warm7〜30日HDD/S3 Standard中速
Cold30日〜1年S3 Glacier/IA低速

コスト最適化チェックリスト

Phase 1:即時適用可能(1〜2週間)

  • 本番環境でDEBUG/TRACEレベルのログをCollectorでドロップしているか?
  • ヘルスチェック・readiness probeのログ/トレースをフィルタリングしているか?
  • メトリクスラベルにユーザーID・リクエストIDなどの高カーディナリティ値が含まれていないか?
  • URLパスラベルが正規化されているか?
  • Collectorにmemory_limiterプロセッサが設定されているか?
  • Collector内部メトリクス(ドロップ率、キューサイズ、メモリ使用量)を監視しているか?

Phase 2:中期最適化(2〜4週間)

  • Tail Samplingがエラー/高レイテンシトレースを100%保持しつつ、正常トラフィックを5〜10%に制限しているか?
  • 2-Tier Collectorアーキテクチャ(Agent + Gateway)が構成されているか?
  • トレースIDベースルーティング(LoadBalancing Exporter)が設定されているか?
  • 不要なログ属性を除去しているか?
  • サービスごとのObservability Budgetが定義されているか?
  • カーディナリティ監視ダッシュボードが構築されているか?

Phase 3:長期インフラ最適化(1〜3ヶ月)

  • Hot/Warm/Coldストレージティアリングが構成されているか?
  • S3 Intelligent-Tieringまたは同等の自動ティアリングが有効化されているか?
  • メトリクスのダウンサンプリングポリシーが適用されているか?
  • ILM/保持ポリシーが規制要件を満たしているか?
  • CI/CDパイプラインにカーディナリティ検証ゲートが含まれているか?

トラブルシューティング

Collectorのメモリ使用量が増加し続ける場合

# 1. Collectorのメモリ使用量を確認
kubectl top pods -n observability -l app=otel-gateway

# 2. pprofでメモリプロファイリング
curl -s http://localhost:1777/debug/pprof/heap > heap.prof
go tool pprof -top heap.prof

# 3. Tail Samplingキューの状態を確認
curl -s http://localhost:8888/metrics | grep tail_sampling

カーディナリティ爆発の原因サービスを特定する方法

# Prometheusで上位メトリクスを確認
curl -s http://prometheus:9090/api/v1/status/tsdb | \
  jq '.data.seriesCountByMetricName | sort_by(-.value) | .[0:10]'

# 特定メトリクスのラベルカーディナリティを分析
curl -s 'http://prometheus:9090/api/v1/query?query=count(http_server_request_duration_seconds_bucket) by (service_name)' | \
  jq '.data.result | sort_by(-.value[1] | tonumber) | .[0:10]'

まとめ

Observabilityコスト最適化は、単にデータを減らすのではなく、シグナルとノイズを精密に分離してObservabilityの品質を維持しながらコスト効率を最大化するエンジニアリング活動だ。

本記事で取り上げた戦略の要約:

  1. サンプリング:Head Samplingでネットワークコストまで削減し、コアサービスにはTail Samplingでエラー/高レイテンシトレースを100%保持する。
  2. フィルタリング:DEBUG/ヘルスチェックログをCollectorでドロップし、属性整理でペイロードサイズを縮小する。
  3. カーディナリティ管理:高カーディナリティラベルを除去し、URLパスを正規化し、Observability Budgetでサービスごとの使用量を制御する。
  4. ストレージティアリング:Hot/Warm/Coldアーキテクチャでデータの経過時間に応じて低コストストレージに自動移行する。

これらの戦略を体系的に適用すれば、全体のObservabilityコストを60〜80%削減しつつ、障害対応に必要なデータを完全に保持できる。

参考資料