はじめに:障害がむしろ監視を止めてしまうなら?
運用中のシステムで障害が発生したとき、エンジニアが最初に行うのはダッシュボードを開き、アラームを確認することです。しかし、そのダッシュボードとアラームシステムが、まさに今ダウンしているインフラに依存していたらどうでしょうか?監視がブラインドになる瞬間、原因分析はおろか、現在の状況すら把握できなくなります。
AirbnbのObservabilityチームはまさにこの問題に直面しました。数千のサービスが共有KubernetesとIstioサービスメッシュ上で動作する環境で、メトリクスパイプラインがまさにその共有インフラに依存していたのです。
この記事では、Airbnbがどのようにこの「循環依存(circular dependency)」を特定し、コンピューティング/ネットワーキング/メタモニタリングの3つのレイヤーで段階的に解決したかを詳しく紹介します。単なるアーキテクチャ改善ではなく、「監視は監視対象よりも高い可用性を持つべきである」 という原則を実践した事例です。
![]()
循環依存:オブザーバビリティの隠れたリスク
Airbnbのプラットフォームチームは、開発者が最小の摩擦でサービスをデプロイ/運用できるよう、共有インフラ(Kubernetes、サービスメッシュなど)を提供しています。問題は、Observabilityスタック自体がその共有インフラ上に構築されていた点です。
graph TD
A[サービスA] -->|メトリクス送信| B[共有Kubernetes]
C[サービスB] -->|メトリクス送信| B
D[監視システム] -->|メトリクス収集| B
B -->|障害発生| D
D -->|アラーム停止| E[エンジニア]
E -->|障害原因特定不可| F[ブラインド]
この構造の問題は明白です:監視システムがダウンしたインフラの助けを借りなければ動作できないなら、障害時に最も必要な瞬間に視界を失います。
解決原則:シンプルだが強力
Airbnbチームのアプローチは原則的にシンプルでした。
すべての内部顧客(internal customer)に、冗長で高可用性なメトリクス収集パスを提供せよ。
ただし、ここで「内部顧客」の範囲を明確にしました。自分たちが保証すべきシステム(Observabilityチームが直接管理するサービス)に対してのみ冗長性を設計し、外部障害ドメイン(fault domain)まで責任を持とうとはしませんでした。
1. コンピューティングレイヤーの分離:専用クラスターの妥協点
Airbnb Cloudチームは全体のKubernetesクラスターを管理しています。Observabilityチームは自分のワークロードをどこで実行するか、2つの極端な選択肢の間で悩みました。
| 選択肢 | メリット | デメリット |
|---|---|---|
| 共用プロダクションクラスターで実行 | 運用負担最小化 | 監視対象と強結合 → 循環依存 |
| 自前Kubernetesクラスター運用 | 完全な分離 | 深い運用専門知識が必要、メンテナンス負担 |
Airbnbが選んだ「ほどよい」解決策は専用Kubernetesクラスターでした。
- このクラスターはプロダクトや他のインフラアプリケーションと共有されません。
- しかし、Cloudチームが管理します。つまり、運用負担はCloudチームが負う一方、障害ドメインは分離されたのです。
変更管理も徹底しました。一度に1つの主要変更のみ適用し、低優先度クラスターで先に検証した後、運用クラスターに反映しました。国内のクラウド環境でも「専用クラスター」を設けることは追加コストになり得ますが、障害時の可視性(visibility)をコスト換算すれば、十分に投資する価値がある領域です。

2. ネットワーキングレイヤーの分離:サービスメッシュからの脱却
Observabilityトラフィックは一般のビジネストラフィックと性質がまったく異なります。
- ボリューム: Observabilityデータの方がビジネストラフィックよりはるかに多い。
- 優先度: 障害時、メトリクスは最も重要なデータの一つ。
AirbnbはIstioをサービスメッシュとして使用していましたが、2つの問題がありました。
- 循環依存: サービスメッシュのメトリクスを収集するために、同じサービスメッシュに依存しなければならない。
- トラフィック混雑: テレメトリーのスパイクが共有帯域を占有し、ビジネストラフィックにまで影響。
解決策:カスタムEnvoyプロキシレイヤー
Airbnbはサービスメッシュから独立したカスタムLayer7ネットワークイングレスレイヤーを構築しました。Envoyベースで動作し、ロードバランシングとルーティングを専任します。
# 擬似コード:ヘッダーベースルーティングの例
# 実際のEnvoy設定の概念的表现
def route_request(request):
# すべてのリクエストはtenantヘッダーを含む必要がある
tenant = request.headers.get("X-Tenant-Id")
if not tenant:
return reject_request("Missing tenant header")
# サービス名を基にバックエンドクラスターをマッピング
backend_cluster = service_to_cluster_map.get(request.service_name)
if not backend_cluster:
return reject_request("Unknown service")
# 読み取り/書き込みリクエストを分岐
if request.method == "WRITE":
return route_to_primary(backend_cluster, request)
else:
return route_to_replica(backend_cluster, request)
このカスタムレイヤーによって得られた利点:
- 分離: サービスメッシュの障害がメトリクス収集に影響しない。
- 優先度制御: テレメトリートラフィックとビジネストラフィックを明確に分離。
- 柔軟な機能: メトリクスミラーリング、細粒度アクセス制御などのカスタム機能を実装可能。
国内クラウド環境のヒント: すでにIstioやLinkerdなどのサービスメッシュを使用しているなら、Observabilityトラフィックだけでも別のネットワークパス(例:dedicated Envoy proxy)に分離することを検討してください。特に大規模KafkaクラスターやPrometheusを運用している場合はなおさらです。
3. メタモニタリング:監視を監視する方法
コンピューティングとネットワーキングレイヤーを安定化した後、自然な疑問が生まれました。「では、この監視システム自体が正常に動作していることはどうやって知るのか?」
Airbnbはメタモニタリング(meta-monitoring) レイヤーを追加しました。
- 別のPrometheusインスタンスがObservabilityスタック専用で実行されます。
- このPrometheusはObservabilityスタックと異なるアベイラビリティゾーン(AZ)、異なるKubernetesノードに配置され、相関障害(correlated failure)を防ぎます。
- AlertmanagerとPrometheusのペアが同じ共有インフラに配置されないようにします。
Dead Man's Switch(デッドマンスイッチ)
メタモニタリングがダウンしたら?無限後退(infinite regress)を避けるためにDead Man's Switchを使用します。
# Prometheus alerting ruleの例 (Dead Man's Switch)
groups:
- name: meta-monitoring
rules:
- alert: DeadMansSwitch
expr: vector(1)
labels:
severity: none
annotations:
summary: "Dead Man's Switch - Prometheusが正常なら常に発報"
動作方式:
- Prometheusが正常にスクレイピング中なら、
DeadMansSwitchアラートが常に発報(firing) します。 - Alertmanagerはこのアラートを継続的にAWS SNSトピックに送信します。
- CloudWatchアラームがSNSメッセージ受信率を監視します。
- メッセージが停止した場合(Prometheusダウン、スクレイピング停止、Alertmanager障害など)、オンコールエンジニアにページが送信されます。
この構造はシンプルですが、「監視の監視」がサイレント障害(silent failure)に陥るのを防ぎます。

まとめ:監視をプロダクションシステムとして扱う
Airbnbの事例は単なる技術的改善を超え、Observabilityを一つのプロダクションシステムとして捉える視点の転換を示しています。
核心原則:監視システムの可用性は監視対象の可用性を必ず上回らなければならない。
実務に適用できるチェックリスト
- 依存関係マップを作成する: 自分の監視システムがどのインフラに依存しているかを明示的にドキュメント化しましょう。
- 循環依存を見つける: 監視対象となるシステムが監視パイプラインの必須構成要素になっていないか確認しましょう。
- 障害ドメインを分離する: 最低でも監視専用のクラスターやネットワークパスを一つは確保しましょう。
- メタモニタリングを構築する: 「監視が生きているか」を確認する別のパスを作り、Dead Man's Switchで最終安全装置を用意しましょう。
合わせて読みたい記事
- React動的フォーム、コンポーネント vs スキーマ 実務で悩む選択肢 — インフラではなくフロントエンド領域での依存関係管理のインサイト
- Spotifyが1800パイプラインを6ヶ月で移行した秘訣 HonkエージェントとFleet Management実戦事例 — 大規模マイグレーションにおける運用信頼性確保戦略
次のステップとしての学習方向
- Prometheus OperatorとVictoriaMetricsを活用したメトリクスパイプラインの二重化
- Grafana Mimir または Thanosを用いた長期メトリクスストレージの高可用性設計
- OpenTelemetryでトレース/メトリクス/ログを統合収集する際の依存関係管理パターン
この記事が役に立ったなら、ぜひあなたのプロジェクトでも「監視の監視」を一度考えてみてください。障害はいつも予期せぬ瞬間に訪れるものですから。