運用
分散システムにおけるモニタリングとオブザーバビリティの違い
モニタリングは、壊れると想定していたものが壊れたことを報告します。オブザーバビリティは、想定外の事態がなぜ起きているかを突き止めることを可能にします。システムが複数のサービス、キュー、キャッシュ、リージョンに分散すると、インシデントのほとんどはこの想定外の事態です。
モニタリングは既知の問いに答える
従来のモニタリングは、あらかじめわかっている問いを中心に構築されています。サーバーは稼働しているか、CPU は80パーセントを超えていないか、ディスクの空きは足りているか、夜間ジョブは完了したか。運用担当者は指標を選び、しきい値を設定し、それを超えたらアラートを出します。モノリスを動かす少数のサーバーであれば、これで十分に機能します。起こりうる問題の一覧が短く、オンコール担当者がそれを熟知しているからです。
限界は、すべてのチェックが予測に基づいていることです。下流の依存先の遅延、リトライの嵐、稼働はしているが古いデータを返すキャッシュなど、誰も予測しなかった障害が起きると、顧客が不満を訴えている間もダッシュボードは緑のままです。モニタリングは引き続き必要ですが、システムが一人の頭の中に収まる規模を超えると、それだけでは不十分になります。
分散によって何が変わるか
同じ業務機能を、間にメッセージキューを挟んだ十数個のサービスに分けると、3つのことが変わります。第一に、1件のユーザーリクエストが多くのホスト上の多くのプロセスに関わるため、ひとつのログファイルだけでは全体像がわかりません。第二に、障害が部分的になります。全体としては正常に見えても、特定のリージョン、テナント、コードパスだけが遅くなります。第三に、システムが1日に何度も変更されるため、昨日の基準値はもう当てはまりません。
オブザーバビリティとは、新しい問いを立てるたびに新しいコードをデプロイしなくても、システムが出力するデータからその内部状態を理解できる性質のことです。実際には、どの顧客、どのエンドポイント、どのバージョン、どのリージョンかといった、詳細でカーディナリティの高いテレメトリを収集し、必要に応じて切り分けられることを意味します。問いは、システムが稼働しているかどうかから、どのユーザーが遅さを感じているか、いつからか、何が変わったかへと移ります。
3つのシグナルとその役割
メトリクス、ログ、トレースは、3種類の異なるデータです。それぞれが異なる問いに答え、その間を行き来できることに価値があります。
メトリクス
時間とともに集計される数値です。リクエスト数、エラー率、レイテンシのパーセンタイル、キューの深さなどがあります。保存コストが低く、クエリが速く、アラートや変化の検知に適しています。何がいつ起きたかは示しますが、なぜ起きたかを示すことはまれです。
ログ
文脈を伴う個々のイベントです。構造化ログ(一貫したフィールドを持つ JSON)は検索でき、相互に関連付けられます。自由形式のログは、人が1件ずつ読むことになります。ログは詳細を伝えますが、バイト単位のコストはトラフィックに比例して増えます。
トレース
1件のリクエストがサービスをまたいでたどる経路で、各ホップの所要時間を含みます。トレースは、どこで時間がかかり、どの依存先が失敗したかを示します。すべてのログ行に共通のトレース ID があれば、エンジニアは遅いトレースからその原因となった特定のログエントリへ移動できます。
アラートの基準としてのサービスレベル目標
サービスレベル目標(SLO)とは、ユーザーが体感する指標に対する目標値です。たとえば、30日間の計測で、決済リクエストの99.9パーセントが500ミリ秒以内に正常に完了する、といったものです。割合と期間は組織が設定します。重要なのは、SLO がホストの報告内容ではなく、ユーザーが体験する内容を表すことです。
SLO は、期間内に許容できる失敗の量であるエラーバジェットを定め、それに伴って異なるアラートモデルをもたらします。CPU が一定の線を超えたときに呼び出すのではなく、バジェットの消費が速すぎて期間の終わりまでもたない場合に呼び出します(バーンレートアラート)。緩やかな消費は翌営業日のチケットとなり、急速な消費はオンコールのエンジニアを呼び出します。この変更ひとつで、誰も対応する必要のないアラートのほとんどがなくなります。
SLO は、エンジニアリングとビジネスに共通の言葉も与えます。バジェットに余裕があればチームはより速くリリースでき、消費が進んでいれば信頼性に投資します。CPU のグラフでは、このような議論はできません。
アラート疲れとオンコールのローテーション
監視の取り組みで最もよくある失敗は、アラートの不足ではなく過剰です。ローテーションに週に何十件もの呼び出しが届き、その大半が対応不要であれば、担当者は読まなくなり、本当に重要なアラートがノイズに埋もれます。すべてのアラートは、人がすぐに何らかの対応を取れるか、という単純な基準を満たすべきです。満たさないものは、呼び出しではなく、ダッシュボードのパネルや日次レポートに載せるべきです。
アラートの一式は、レビュー対象のコードとして扱ってください。各アラートには担当者、ランブックへのリンク、存在する理由があり、1か月間対応なしで発報され続けたアラートは削除するか、重要度を下げます。週あたりの呼び出し件数、業務時間外の呼び出し件数、確認までの時間など、ローテーション自体も計測します。健全なオンコールのローテーションは健全なシステムの証であり、不健全なローテーションは投資すべき場所を明確に示すシグナルです。
分散システムでは、もうひとつ要件が加わります。アラートには文脈が必要です。「payments-api のエラー率が高い」とだけ書かれた呼び出しは調査の始まりにすぎませんが、影響を受けた SLO、直近のデプロイ、最も失敗の多いエンドポイントへのリンクを含む呼び出しであれば、すぐに判断を下せます。
テレメトリのコスト
オブザーバビリティのデータにはコストがかかり、その請求は習慣が定着した後に届きがちです。コストを左右するのは、量(リクエストあたりのログとスパンのバイト数にトラフィックを掛けたもの)とカーディナリティ(メトリクスのラベルの組み合わせの数)の2つです。ユーザー ID やリクエスト ID をラベルに付けたメトリクスは、値ごとに新しい時系列を生み出し、どのようなメトリクスストアも圧迫します。
妥当な初期設定だけでも大きな効果があります。カーディナリティの高い識別子はメトリクスのラベルではなく、トレースと構造化ログに持たせます。トレースはサンプリングし、エラーと遅いリクエストはすべて、通常のリクエストは一部だけを残します。保持期間はシグナルごとに設定します。メトリクスは解像度を下げて1年、ログは数週間、トレースは数日とし、コンプライアンス上必要なものにはアーカイブ層を用意します。ログ量の多い発生源は毎月見直してください。ホットパスにある冗長なデバッグ出力ひとつが、請求額の大きな割合を占めることもあります。
目指すべきは、すべてを収集することではありません。次に生じる未知の問いに、組織が払い続けられるコストで素早く答えられる状態をつくることです。
どこから始めるか
サーバー監視からオブザーバビリティへ移行するチームにとって、最も早く効果が出るのは次の順序です。
- 最も重要なユーザーフローについて2~3個のSLOを定義し、単純なしきい値ではなくバーンレートでアラートを出します。
- トレースIDを含む一貫したフィールドセットで、すべてのサービスに構造化ログを導入します。
- リクエスト経路を分散トレーシングで計装します。オープン標準とSDKを使えば、書き直しではなくライブラリの変更で済みます。
- ユーザーが体感する4つのシグナル(トラフィック、エラー、レイテンシ、飽和度)を軸に、サービスごとにダッシュボードを1つ作成します。
- アラートとテレメトリー量を毎月見直し、誰も対応していないものは削除します。
ツールを増やさずに次の問いに答える
次の問いに、チームが1か所で答えられるようになります。SnowTrackは、すでに稼働しているシステムのインフラ、アプリケーション、サービスのテレメトリー、SLO、アラートを1つにまとめます。