2.7K Views
March 10, 22
スライド概要
2022年3月開催のObservability Conference 2022での発表資料です。
https://event.cloudnativedays.jp/o11y2022/talks/1373
New Relic株式会社、Technical Support Manager.
Deep Dive Distributed Tracing Observability Conference 田中 孝佳 @tanaka̲733 資料は公開済です(セッション概要にリンクあります) 質問はカンファレンスのQ&AあるいはTwitterまで
登壇者紹介 田中 孝佳 (@tanaka̲733) New Relic K.K. Lead Technical Support Engineer 好きな言語はC#。C# Tokyoコミュニティの運営メンバー OpenTelemetry .NETハンズオンなどを開催 Microsoft MVP for Azure, Development Technologies Microsoft Certified Cloud Solution Architect Expert Certified Kubernetes Administrator/Application Developer(CKA/CKAD)
本日のゴール • オブザーバビリティにおけるトレースの重要性 • 分散トレースでなければわからないことを知る • 分散トレースの構造の把握 • なぜつながるかを理解し、つながらない問題に対応できる • 多数のトレースから注目すべきトレースを選ぶことの重要性 • 分散トレースのオーバーヘッドを理解し、 適切なサンプリング方法を設計できる
今日話さないこと • メトリクス、ログとの連携 • 分散ツールの各計装ツールの固有の機能 • 個別のツールや言語における分散トレースの詳細 OpenTelemetryやW3C Trace Contextといった オープンなプロジェクトを中心に 多くのツールで共通している概念をお話します
目次 • オブザーバビリティと分散トレース • 分散トレースの概念と整理 • (分散)トレースとはなにか • トレースの概念と用語を整理する • 分散トレースをつなげる仕組み=伝搬 • 分散トレースをつなげる課題 • W3C Trace Context • 多数のトレースから注目すべきものを見つける =サンプリング • グルーピングとサンプリング • ヘッドベースサンプリングとテールベースサンプリング
オブザーバビリティと 分散トレース
なぜ監視するのか HWの迅速な プロビジョニング SWの迅速な デプロイ 重大な問題を迅速に 検出する監視 マイクローサビスを採用ときに考慮すべき3つの能力 Fowler, Martin. 2014. “Microservice Prerequisites.” MartinFowler.com. August 28, 2014. https://martinfowler.com/bliki/MicroservicePrerequisites.html
オブザーバビリティとは 問題 問題 問題 根本原因
オブザーバビリティーの3本柱 トレース (特に分散トレース) • • サービスのボトルネック を分析する リクエストの通過した パスと構造を把握 メトリクス • • サービス全体の傾向を 分析 数値化したテレメトリー データを集約する ログ • • 詳細なデバッグ情報を分 析 プロセスから出力した テキスト情報
分散トレースが生まれた背景 原因と結果が離れる ひとつひとつの要素は 壊れやすい (単体のSLAは低い) 何百、何千の ホスト(コンテナ)
分散トレースが必要な理由 「インシデントが発生している最中(一刻を争う時)に 根本原因を発見するために必要です。」 メトリクスでは 全体の傾向がわかっても 少数の異常な振る舞いが 埋もれがち ログで詳細はわかるものの、 多数の要素のどのログを 見ればいいのかわからない
分散トレースが目指すもの • システム内を流れるリクエストをテレメトリーデータで取得し、 分散システムのプロファイリングとモニタリングを可能に • 少数の異常な振る舞いを検知可能に • アプリケーションのパフォーマンス問題の 検出と解決にかかる時間を短縮可能に • 多くの言語/フレームワーク/ランタイムで適用可能に (今日はふれない内容)
分散トレース の概念と構造
トレースの構造 トレース内の作業の単位をスパンとし、 スパンのDAG(有向非巡回グラフ)として表現 Span A root Span (必ず1つだけ存在) AのChild Span Caller Span (呼び出しスパン) Span B Span C Span E Span D サービスA Callee Span (呼び出されたス パン) Span P サービスB
スパンの属性 スパンに必要なデータは属性としてもたせる • • • • • TraceID: 所属するトレースを一意に識別 SpanID: 自身のスパンをトレース内で一意に識別 ParentID: 自分の親スパンへの参照 Name: スパンを表現する名前 Start/End Time: 作業の開始・終了時刻から経過時間を算出 • Tags: キー値のペアで表現される追加の情報 • Events: トランザクション内での出来事を表現
トレースの表現方法 • スパンの親子関係に着目 • ボトルネック(経過時間)に着目 • サービスの依存関係に着目
スパンの親子関係に着目した表現方法 DAG Span A Span B Span C Span E Span D サービスA Span P サービスB
ボトルネックに着目した表現方法 time Span A Span B C Span D Span E Span P ボトルネック(どこで経過時間がかかっているか)を見つけるためには、 横軸を実時間にしたこのような表現が使われることが多い。 上の図では、SpanP、つぎにSpanDがボトルネックだとわかる
Notifi cation サービスの依存関係に着目した表現方法 Ext Client Purchase API Client API Purchase DB DB Notification User DB User 分散システムにおいては、トレースからどのように呼び出されたか (システムの依存関係)を見つけることもできる。 Ext
トレースの活用 • 有用なトレースを見つける è 最後の章へ • 属性でクエリする • 経過時間や数値型の属性をメトリクス化し、異常値を見つける • ボトルネックを見つける • エラーや例外状態のスパン • 経過時間などの数値が異常値なスパン • 正しく計測できているか確認すべきケース • calleeとcallerの時間がずれているスパン • 断片化されたスパン
エラーや例外状態のスパン • アプリケーション例外がスローされた(予期せぬ例外) • エラー状態とマークされたスパン(予期された例外) • 応答コードがエラーのスパン • HTTP呼び出しで4xxや5xxステータスレスポンスだった • DB呼び出しでエラーが起きた Span A Span B C DB エラー status code=502エラー アプリケーション例外
呼び出し側と呼び出された側の時間ずれ caller span callee span ネットワーク、キュー ロードバランサーなど さまざまな要素での遅延 caller caller callee サーバー時刻のずれ 非同期処理 callee サーバー時刻のずれ
断片化されたスパン 子スパンが見えない (大きな1つのスパン しか見えない) 呼び出されたスパンがない つながっていないスパン (Orphaned Span) がある Span A Span A サービスY呼出 Span サービスYのSpan サービスZのSpan 親スパンが見えない Span
断片化されたスパンへの対処(一例) • みたいトレースがどのトレースでも見えない • 計測コードが正しく実装されているか • 同じトレースでも見えるときと見えないときがある • サンプリングの問題 è 最後の章へ • サービスを超えたトレースがつながらない • 呼び出したトレースが独立している è 次の章へ • 呼び出したトレースがみえない è 計測されている? • その他考慮すべきこと • スパンデータが到着していない • 時刻のずれ • バックエンドツール側の制約(UI上の制約など)
トレース計測のプラクティス「名前」 • 名前は集約可能 • POST /api/v1/users/12345 • ○ POST /api/v1/users/{id} id=12345はタグとして記録 • 名前はリソースではなく、アクションを表すべき リソースの種類はタグとして記録 • ReadBooksFromFile • ○ ReadBooksを名前 storage=Fileをタグとして記録
トレース計測のプラクティス「タグ」 • カーディナリティの高いデータは名前ではなく、 タグとして使用する • List?color=blue • ○ Listが名前、color=blueはタグ • 複数のシステムで共通化する • bookidなのかbookIdなのかbook̲idなのか統一 • わかりやすい名前 • lengthよりもlength̲mm • スパンが生成されたインフラの情報をタグに追加する • サービスの名前、バージョン、 ホスト、コンテナ、ランタイム、地域・リージョンなど
トレース計測のプラクティス「スパン」 • ログよりも子スパンやタグ • スパンでの処理がエラー状態であるならば スパンの状態もエラーとする • 回復不能なエラーであってもできる限りスパンを停止させる • スパンは意味のある作業の単位で作成する 10:00:00 処理X開始 color=blue 10:01:23 処理X完了 スパン Span X (color=blue)
分散トレースをつなげる仕組み =伝搬
サービス境界と分散トレース • 呼び出した側と呼び出された側の対応づけが必要 • HTTP呼び出しのケースが多い • trace idと呼び出した側のspan idの引き渡し Span E trace id:1234 span id: abcd trace id=1234 parent span id=abcd と設定しないといけない Span P
ベンダー固有の実装と課題 • テキスト形式でフォーマットしたデータを HTTPヘッダー経由でやり取り • ヘッダー名やフォーマットが固有 vendoer̲y: {trace̲id:1234, parent̲id:abcd} Span E trace id:1234 span id: abcd Span P
異なるツール間でもトレースをつなげたい Span Span P vendor̲x: xxx̲format Span T vendor̲y: yyy̲format vendor Yの計測ツールは vendor̲xフォーマットを認識できないため Span Pが親となる新規のトレースとして記録される
W3C Trace Context 分散トレースのためのHTTPヘッダーのフォーマットの標準規格 https://www.w3.org/TR/trace-context/ traceparent: トレースIDと呼び出しスパンIDを識別 tracestate: ベンダー固有の情報
W3C Trace Contextの詳細 traceparent: バージョン(2バイト)-トレースID(16バイト)-スパンID(8バイト)-ト レースフラグ(8ビット) 例) 00-07b4bf1339212a6e634ede07e21e8a72ded04c84c8082456-01 tracestate: トレースを記録するベンダーツールごとに利用 例: New Relicの場合 アカウント、親スパンの種類、アプリケーションID、 スパンID、トレースID、 サンプリング有無、優先度など
W3C Trace Contextでの トラブルシューティング • 呼び出し側がtraceparentヘッダーを送出しているか? • 呼び出された側が同じtraceparentを受け取っているか? • プロキシやLBなど中間要素が除去・改変していないか確認 • 両者のスパンが同じTraceIdを持つことを確認 • 異なる場合は呼び出された側のトレースの計装を確認 (traceparentのTraceIdを適用する方法)
W3C Trace Contextの課題 • job queue/pubsubなどHTTP以外での依存関係 • HTTPヘッダーのようなデータをやり取りできる標準機能がない • 技術的にはtraceparentをやり取りできれば繋げられる • 分散トレースの定義上、1つに表現しづらいパターン • 例えばfork-joinパターン • トレースやスパンの属性を使って、 関連する複数のトレースをまとめられるようにする traceid=123, jobid=abc traceid=789, ex̲jobid=abc traceid=456, jobid=abc
多数のトレースから見るべき トレースに注目する方法
藁の山から針を見つけるために • 山の量をへらす è サンプリング • 山を束に分けて見つけやすくする è グルーピング
多数のトレースの表現方法 • 詳細な実装はツール依存ではあるが、その概念は共通になりつ つあるので整理したい • 計測ツールのどこで行うかがポイント アプリ バックエンド (トレースの保管・ 可視化) 計測 ツール アプリ 計測 ツール コレクター
グルーピング • トレースやスパンの属性ごとに分類する • トレースの名前ごと • DBの操作ごと • 分類した中で異常値を見つける • エラー状態のスパンを含むもの • 経過時間が平均から外れたもの 必要な属性を計測ツールやコレクターで付加し バックエンドの可視化機能として提供することが多い
サンプリング • 多数あるものから注目したいものだけを選ぶ • 事前にメトリクスで集約することで全体の傾向はつかめる • 異常な、問題を含んでいるトレースを選択したい エラー 異常値
トレースの収集方法とサンプリング アプリ 計測 ツール サービスごとの サンプリング コレクター サービス全体での サンプリング バックエンド (トレースの保管・ 可視化) 保管時の制約 UI表示上の制約
ヘッドベースサンプリング あるいはアップフロントサンプリング トレースの開始時点でサンプリングするかどうか決める • 親スパンから先のすべてのスパンに サンプリングされたことを伝える必要がある • 事前に決定するため、経過時間が長かったりエラーが起きたりした トレースを見逃す可能性がある
テールベースサンプリング あるはレスポンスベースサンプリング サービスX サービスY サービスZ トレースが完了してから、サンプリングするかどうか決める
テールベースサンプリングが 注目される理由 • トレースの全体像を見て判断できるため、 少数のエラースパンや経過時間の長いスパンを 見逃さず選択できる • エラーのあるスパンは100%、 その他のスパンは10% のような選択ロジックも可能
テールベースサンプリング 実装する仕組みと課題 • 自社サービス全部のトレースを処理する必要性 • 完了していないすべてのスパンをバッファし、 サンプリング判定する必要性 • ネットワーク転送量、コレクターの可用性、 バックエンドツールの保存コストなどの運用が必須 • 最近ではマネージドなコレクターを提供するSaaSも アプリ 計測 ツール コレクター アプリ 計測 ツール
確率的サンプリング 適用型サンプリング(adaptive sampling)など近い概念も 親スパンがサンプルされたかと サンプリングの確率を伝搬させ、 子スパンごとに再度計算した確率で サンプリングを行う サービスX サービスY サービスZ OpenTelemetryではtracestateを使って確率的サンプリングを行う 仕様がExperimentalで検討中 https://opentelemetry.io/docs/reference/specification/ trace/tracestate-probability-sampling/
まとめ
まとめ • 分散トレースによりサービス全体のボトルネックを分析 • 分散トレースは作業の単位であるスパンのDAGで表現 • ボトルネックを見つけやすくするよう スパンの名前やタグづけを考える • W3C Trace Contextにより計測ツールが異なっても 分散トレースがつながるようになった • 少数のエラーや異常なスパンを見つけるには テールベースサンプリングという手法がある