Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Distributed Tracing@OpenShift Meetup Tokyo20191018
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
16yuki0702
October 18, 2019
Programming
910
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Distributed Tracing@OpenShift Meetup Tokyo20191018
16yuki0702
October 18, 2019
More Decks by 16yuki0702
See All by 16yuki0702
mwnewsletter202007-serverless.pdf
16yuki0702
1
780
Distributed Tracing@JJUG CCC 2019 Fall
16yuki0702
3
1.1k
Other Decks in Programming
See All in Programming
Performance Engineering for Everyone
elenatanasoiu
0
200
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
170
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
contour_gara
0
550
ふつうのFeature Flag実践入門
irof
8
4.1k
1B+ /day規模のログを管理する技術
broadleaf
0
100
Signal Forms: Details & Live Coding @enterJS 2026 in Mannheim
manfredsteyer
PRO
0
170
Agentic UI
manfredsteyer
PRO
0
180
Make SRE Operations Easier with Azure SRE Agent
kkamegawa
0
7.3k
決定論的オーケストレーションの設計と実装 / Design and Implementation of Deterministic Orchestration
nrslib
4
1.5k
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
4.4k
OSもどきOS
arkw
0
580
Inside Stream API
skrb
1
750
Featured
See All Featured
Test your architecture with Archunit
thirion
1
2.3k
How to build a perfect <img>
jonoalderson
1
5.7k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
66
55k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
How GitHub (no longer) Works
holman
316
150k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.5k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
780
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
750
Code Reviewing Like a Champion
maltzj
528
40k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
62
44k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Transcript
1 分散トレーシング Hiroyuki Sasagawa (
[email protected]
) Middleware Specialist SA 2019/10/18 OPTIONAL
SECTION MARKER OR TITLE
• 分散トレーシングの歴史 ◦ OpenTracing, OpenCensus, OpenTelemetry • 分散トレーシングの概念 ◦ なぜ必要か
◦ Trace, Span等々の仕様の話 • 実際にサンプルを作って動かす • まとめ 今日話すこと 2
• CNCF傘下のプロジェクト(incubating) • 分散トレーシングの標準化を進める • Tracing APIの仕様を定める ◦ 実装が乱立してきたので仕様としてまと めようぜ!ってなった
• 各トレーサがTracingi APIを実装する (Zipkin, Jeager, etc...) • Tracingのみ提供 OpenTracing 3
• Googleが社内で利用しているメトリック収 集、分散トレーシングライブラリのOSS実 装 ◦ TracingだけではなくMetricも含む • 仕様とライブラリのセット • グラフ化したい場合は別途Datadog,
Prometheus, Zipkin, Jaeger等の別サー ビスが必要 • Java, Go, C++, Erlang… 等様々な言語で 使用可能 OpenCensus 4
• CNCF傘下のプロジェクトとしてOpenCensusと OpenTracingが合体 • 標準化を進める為のシステムコンポーネント、言 語毎のライブラリを提供 • OpenTelemetry仕様の大部分は分散トレーシン グに関する物 •
Tracing、Metric、最終的にはLogも含む • agent/collectorモデル(OpenCensusと同様) • 11/6 OpenTracing,OpenCensusは正式に終了 OpenTelemetry 5
• マイクロサービスは小さなサービスの集まり • サービスがスケールすればするほどサービス間の関係は複雑さを増す • サービス間のリクエストで問題が発生した場合どうする?? ◦ 特定の条件でサービスが極端に遅くなる ◦ サービス単体では問題なさそう
◦ どこかのサービス間、かつ特定のタイミングのみ遅くなる ▪ ログとメトリック収集だけではこの事象を素早く特定するのは非常に困難 なぜ分散トレーシングが重要なのか?? 6
• 分散トレーシングではサービス間の リクエストの詳細な状態を記録する ◦ リクエストパスの追跡 ◦ サービス間(ホップ)のレイテンシ ◦ サービス間のエラー状況 •
複雑なマイクロサービス間の関係をビュー として確認することができる ◦ トラブルシューティングが容易 ▪ どこのサービス間でエラーが起きて いるか、遅延が起きているか なぜ分散トレーシングが重要なのか?? 7
• Trace ◦ 分散システム間のリクエストの記録 ◦ Spanのツリー、またはDAG(有効非巡回グラフ - git commit treeと一緒)
で表 現される • Span ◦ Trace内の連続した作業セグメント ◦ 名前と時間を持つ ◦ 他のSpanと親子関係等を持ち関連しあう ◦ フォーマットはOpenTracingとOpenCensusで異なる ▪ OpenTelemetryは両方と互換性がある 分散トレーシングの概念 8
• Root Span ◦ Traceの最初のSpan ◦ Root Spanの時間はTrace全体の時間を表すか、非常に近くなる • Context
Propagation ◦ Tracingはコンテキストの伝搬で成り立つ ▪ GolangのContextパッケージを考えると想像しやすそう ◦ 複数サービスを横断するリクエストが辿るパス内で、一意にどのリクエストか識 別可能な情報 分散トレーシングの概念 9
• Tracer Interface ◦ Spanの作成とSpan間でやりとりするInterfaceを定義 ◦ OpenTracingではマイクロサービス間でSpanを送信するのに必要なメタデータ のinject, extractを行うTracerをベンダーが実装する ◦
OpenTelemetryの実装ライブラリは OpenCensusが採用していた agent/collectorと同様のモデルを使用する 分散トレーシングの概念 10
• SpanAはRoot Span • SpanBとCはSpanAの子 • SpanGはSpanAの後に開始 分散トレーシングの概念 11
• Operation name ◦ 大抵はspanを開始したAPIの参照 • Start/finish timestamp ◦ spanがいつ開始/終了したか
• Tags ◦ クエリ/フィルタ用にユーザで定義するannotation • Logs ◦ span追跡用のkey/valueペア • SpanContext ◦ Span境界を超えて伝搬されるメタデータ Spanのフォーマット (OpenTracing) 12
• Name ◦ Spanが何かを定義する文字列 • SpanID ◦ SpanのID • TraceID
◦ Spanが所属するTraceのID • ParantSpanID ◦ Spanの親ID • StartTime/EndTime ◦ Spanがいつ開始/終了したか Spanのフォーマット (OpenCensus) 13
• Status ◦ ある時点のスパンの状態を表現 • Time event ◦ ある時点で発生したイベントを定義 •
Link ◦ Trace内のspan間の関係を定義 • SpanKind ◦ Span間の関係の定義 • TraceOptions ◦ Spanがサンプリングされるかどうか。バイトで定義 • TraceState ◦ Spanの位置/順序に関する詳細 Spanのフォーマット 2 (OpenCensus) 14
• OpenTracing, OpenCensus両方に互換性を持つ Spanのフォーマット (OpenTelemetry) 15
• OpenTracing実装の一つ • Twitterが開発 • Envoyで使われている (対応している) • 2012年くらいから存在し結構歴史は古い •
バックエンドはJavaで実装され、UIも提供 • C#, Go, Java, JavaScript, Ruby, Scala, PHP等色々な言語でクライアント提供 Tracing実装 - Zipkin 16
Zipkin 17
• OpenTracing実装の一つ • Uberが開発 (2017) • OpenTelemetryのバックエンドとして機能できる • Client LibraryはOpenTelemetry
APIを当面実装して対応 ◦ 将来的には凍結し、独自機能はOpenTelemetryに組み込む予定 • agent/collector のモデルで動作する (OpenCensusと非常に似ている) ◦ OpenTracing実装でありつつ、OpenCensusと同じようなアーキテクチャ • OpenShift Service Mesh (Istio) 内でバックエンドコンポーネントとして使用される • OpenTelemetryと少しずつ統合していくと思われる Tracing実装 - Jaeger 18
Jaeger 19
• OpenTelemetry ◦ 複数言語にAPI, SDKを提供し、テレメトリデータをバックエンドにエクスポートで きる機構を提供 • Jaeger ◦ agent/collectorで動作するが、主な目的はテレメトリデータを受信し、データの
処理、集約、マイニング、可視化することが目的 ▪ 主にトレースバックエンドとして動作する ◦ クライアントライブラリを持つが、大部分がOpenTelemetryと重複する為将来的 に独自機能をOpenTelemetryに組み込み凍結予定 • OpenTelemetryはJaegerをバックエンドとしてネイティブにサポート • 主とする領域がそれぞれある JaegerとOpenTelemetryを整理 20
• OpenShift Service Meshを使う ◦ https://docs.openshift.com/container-platform/4.1/service_mesh/service _mesh_day_two/ossm-example-bookinfo.html ◦ Operatorで簡単にインストール可能 •
annotations: sidecar.istio.io/inject: "true" をDeployment Configに設定すると sidecarが立ち上がる • クライアントライブラリはOpenTracingを使用 • バックエンドはJaegerを使用 分散トレーシングを試してみる 21
• gateway appを通して後ろのdest1, dest2, dest3へリクエストを転送 ◦ 単純にリクエストを転送するだけし か行わない • そのアプリケーションが目的地だった場
合 Hello from dest1 みたいなレスポン スを返す • Goで実装してみた サンプルアプリケーションの構成 22
• Envoy(Sidecar Proxy)がトレーシング情報を直接Tracing Backend(Jaeger)に送信 • Envoyが以下行う ◦ リクエスト通過時にRequestID, トレースヘッダー(X-B3-TraceID)を生成 ◦
リクエスト、レスポンスのメタデータ(レスポンスタイム等)に基づき各リクエストの Trace Spanを生成 ◦ 生成されたTrace Spanをトレースバックエンド(Jaeger)に送信 ◦ Traceヘッダーをproxyされるアプリケーションに送信 • Istio/EnvoyではLightStep, Zipkinをサポート。Zipkin API互換バックエンド(Jaeger)を サポート Envoy-Based Tracing 23
Key : uber-trace-id Value : {trace-id}:{span-id}:{parent-span-id}:{flags} Propagation Format - Jaeger
24 • Jaegerはデフォルトだと上記フォーマットでHttp headerにPropagation情報を転送し てくる • Istio/Envoyはこのフォーマットは対応していない • Zipkinのヘッダーフォーマットであるb3-propagationを使う必要がある ◦ もしくはLightStep
x-b3-traceid x-b3-parentspanid x-b3-spanid x-b3-sampled Propagation Format - b3(Zipkin) 25 •
リクエストを中継するサービスは上記ヘッダーをExtractし て次のサービスにPropagationさせる • Twitterではシステム名を鳥にちなんで名付けることが多 く、Zipkinは元々Big Brother Bird 略してB3と呼ばれてい たらしい。 ◦ なのでheaderのprefixにもb3
x-ot-span-context Propagation Format - 余談 26 • LightStep形式の場合は上記ヘッダーが必要
• アプリケーションはproxyからリクエストを受け取ったらcontextをextractし次のリクエ ストに必要なheader(x-b3-*)をinjectする ◦ Request-Idだけライブラリでinjectされないので自前で設定する ◦ outgoingもIstioが拾ってspanを生成してくれる • 末端(リクエストを中継しない)アプリケーションは特別な実装は不要 •
基本OpenTracing実装のライブラリ使えば大丈夫 Envoy-Based Tracing - Application側で必要な実装まとめ 27
実装 (クライアント初期化処理) 28 Import ( ... opentracing "github.com/opentracing/opentracing-go" jaeger "github.com/uber/jaeger-client-go"
"github.com/uber/jaeger-client-go/zipkin" ) func InitTracing(serviceName string) (opentracing.Tracer, io.Closer) { zipkinPropagator := zipkin.NewZipkinB3HTTPHeaderPropagator() injector := jaeger.TracerOptions.Injector(opentracing.HTTPHeaders, zipkinPropagator) extractor := jaeger.TracerOptions.Extractor(opentracing.HTTPHeaders, zipkinPropagator) tracer, closer := jaeger.NewTracer( serviceName, jaeger.NewConstSampler(true), jaeger.NewNullReporter(), injector, extractor, ) opentracing.SetGlobalTracer(tracer) ... • 必要なヘッダー(x-b3-*)をextract, injectする為にzipkinPropagatrorを 使用 • JaegerはOpenTracingの実装なの でOpenTracing.Tracer Interfaceを 満たす • Tracerをアプリ内でシングルトンにす る為SetGlobalTracerする • Sampling Rateは固定 • Reporterもテスト用にNullReporter ◦ 詳しい説明はこちら
実装 (Propagation) 29 func Propagate(w http.ResponseWriter, r *http.Request, url string)
{ tracer := opentracing.GlobalTracer() spanCtx, err := tracer.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(r.Header)) if err != nil { panic(err) } req, err := http.NewRequest("GET", url, nil) if err != nil { panic(err.Error()) } tracer.Inject( spanCtx, opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header), ) ... • opentracing.GlobalTracer()でtracer取得 (シングルトン) • Propagateするアプリケーションはistio proxyが生成したTrace, Spanを取得する為 にリクエストからSpanCtxをextract • リクエストを作成してSpanCtxから必要な ヘッダーをinject
実装2 (Propagation) 30 func Trace(w http.ResponseWriter, r *http.Request, traceName, url
string) { ... incomingHeaders := []string{ "x-request-id", "user-agent", } for _, header := range incomingHeaders { req.Header.Set(header, r.Header.Get(header)) } resp, err := do(req) if err != nil { panic(err.Error()) } w.Write([]byte(string(resp))) } • X-request-id等、自分で抽出し ないといけないheaderだけ抽出 して設定 • 伝搬先にリクエストを送信して、 リクエスト元にレスポンスを返却
実装 (Destination) 31 func handler(w http.ResponseWriter, r *http.Request) { serviceName
:= os.Getenv("SERVICE_NAME") resptStr := fmt.Sprintf("Hello from %s!!", serviceName) w.Write([]byte(resptStr)) } • リクエストを伝搬しないアプリケーショ ンはサービス名だけレスポンスに設 定して返却
図を交えてもう一度整理 32 Pilot-agent (Envoy) dest3 app Pilot-agent (Envoy) istio-ingressgateway Pilot-agent
(Envoy) gateway app Pilot-agent (Envoy) dest1 app Pilot-agent (Envoy) dest2 app Request Zipkin (k8s Service) Jaeger (Collector) Jaeger UI
図を交えてもう一度整理 33 Pilot-agent (Envoy) dest3 app Pilot-agent (Envoy) istio-ingressgateway Pilot-agent
(Envoy) gateway app Pilot-agent (Envoy) dest1 app Pilot-agent (Envoy) dest2 app Request Zipkin (k8s Service) Jaeger (Collector) Jaeger UI • EnvoyがInbound, Outbound時にSpan生成、proxyされたアプリケーションに渡す。 TracerにはOpenTracing(Zipkin)を使用 • Envoyが直接istio-system内のZipkin Serviceにテレメトリ送信 ◦ Zipkinの後ろに控えているのはJaeger Collector (ややこしい!)
図を交えてもう一度整理 34 Pilot-agent (Envoy) dest3 app Pilot-agent (Envoy) istio-ingressgateway Pilot-agent
(Envoy) gateway app Pilot-agent (Envoy) dest1 app Pilot-agent (Envoy) dest2 app Request Zipkin (k8s Service) Jaeger (Collector) Jaeger UI • ProxyされたアプリケーションはOpenTracing(Jaeger)を使用して、Proxyから渡って きたContextをProgateする ◦ ただしヘッダーの形式はIstio/Envoyと合わせてZipkin(B3)(ややこしい!!)
図を交えてもう一度整理 35 Pilot-agent (Envoy) dest3 app Pilot-agent (Envoy) istio-ingressgateway Pilot-agent
(Envoy) gateway app Pilot-agent (Envoy) dest1 app Pilot-agent (Envoy) dest2 app Request Zipkin (k8s Service) Jaeger (Collector) Jaeger UI • Envoy(Zipkin)とアプリケーション(Jaeger)で異なるライブラリを使用していても、 OpenTracing実装なので正しくContextをPropagateできる ◦ OpenTracingの恩恵 ◦ OpenTelemetryが成熟すればもっとわかりやすくなるはず!
kialiで確認 36
Jaegerでも確認 37 Outbound Inbound
Headerを見てみる (gateway) 38 X-Request-Id, [5465a62d-e194-99a0-9230-d44a52231e60] X-B3-Traceid, [a8cfcf72af6f01b2548c9f9605ac2b1f] X-B3-Spanid, [845a979942ca2aa4] X-B3-Parentspanid,
[548c9f9605ac2b1f] X-B3-Sampled, [1] X-Forwarded-Host: [istio-ingressgateway-istio-system.apps.opensh...] • X-Forwarded-Hostをみるとistio-ingressgatewayからリクエストからきていること がわかる • isito-ingressgatewayがX-Request-ID, X-B3-Traceidを生成 • X-B3-Parentspanidはisito-ingressgatewayが生成したSpanを指す • X-B3-Spanidはistio-sidecarがリクエストを受け取った時に生成(inbound)
Headerを見てみる (dest1) 39 X-Request-Id, [5465a62d-e194-99a0-9230-d44a52231e60] X-B3-Traceid, [a8cfcf72af6f01b2548c9f9605ac2b1f] X-B3-Spanid, [02b0374724e15993] X-B3-Parentspanid,
[60a1097e8035b5e2] X-B3-Sampled, [1] • X-B3-Parentspanidはgateway のOutbound Spanを指す • X-B3-Spanidはistio-sidecarがリクエストを受け取った時に生成(inbound)
Headerを見てみる (dest2) 40 X-Request-Id, [5465a62d-e194-99a0-9230-d44a52231e60] X-B3-Traceid, [a8cfcf72af6f01b2548c9f9605ac2b1f] X-B3-Spanid, [8959f06229087845] X-B3-Parentspanid,
[f96978dbdc3effb1] X-B3-Sampled, [1] • X-B3-Parentspanidはdest1 のOutbound Spanを指す • X-B3-Spanidはistio-sidecarがリクエストを受け取った時に生成(inbound)
Spanの関係 41 548c9f9605ac2b1f 845a979942ca2aa4 60a1097e8035b5e2 02b0374724e15993 f96978dbdc3effb1 8959f06229087845
Sample置き場 42 • • 試したいだけなら アプリより軽量かつシンプル ◦ なぜならリクエストの転送しかしていないから • Bookinfoはpython(productpage),
java(reviews), node.js(ratings), ruby(details) でそれぞれ実装 ◦ Goのサンプルがないのでよろしければどうぞ ▪ ほぼRequestへのextract, injectしかしてないけど。。。
まとめ 43 • 分散トレーシングに関しては今後OpenTelemetryに要注目 • バックエンド(Collector)に関してはJeagerが有力? ◦ Clientライブラリ, agent/collector全てOpenTelemetryと密に関わっているし ▪
作者も一緒だし • OpenShift Service Meshで分散トレーシングするなら、アプリ側でちょっと実装入れ るだけで割と簡単に試せるはず ◦ ただしSideCarに対するInbound/Outboundだけでなく、もっと細かくSpan取りた いなら自分でStartSpanとかする必要あり ▪ 例えば特定の関数だけ細かく取りたいとか
linkedin.com/company/red-hat youtube.com/user/RedHatVideos facebook.com/redhatinc twitter.com/RedHat 44 Red Hat is the world’s
leading provider of enterprise open source software solutions. Award-winning support, training, and consulting services make Red Hat a trusted adviser to the Fortune 500. Thank you OPTIONAL SECTION MARKER OR TITLE