Istio Trace鏈路追蹤方案

吳德寶AllenWu發表於2018-10-19

[TOC]

Istio Trace鏈路追蹤方案

Istio Trace支援

envoy支援trace

envoy原生就支援分散式追蹤系統的接入,如支援jaeger和zipkin,如envoy的Tracing官方文件中表明envoy支援如下trace特性:

  • 生成Request Id,填充HTTP的header欄位x-request-id
  • 外部跟蹤服務整合,如支援LightStep, Zipkin或任何Zipkin相容後端(如Jaeger)
  • 新增Client trace ID

相關資訊可以參考這裡 或者 envoy官方文件Jaeger Tracing,另外,在原始碼中有對應的trace相關的原始碼

Istio支援trace

Istio的分散式追蹤相關介紹裡面相關說明可以知道,Istio的envoy代理攔截流量後會主動上報trace系統,通過proxy的引數zipkinAddress指定了trace系統的地址,這樣就不會再經過mixer了,直接envoy和trace系統互動,大體流程:

  • 如果incoming的請求沒有trace相關的headers,則會再流量進入pods之前建立一個root span

  • 如果incoming的請求包含有trace相關的headers,Sidecar的proxy將會extract這些span的上下文資訊,然後再在流量進入pods之前建立一個繼承上一個span的新的span

由於Istio的proxy代理是envoy,而envoy又原生支援jaeger,那因此Istio自然而然就支援jaeger了,在官方文件Distributed Tracing中有相關較為詳細的說明

當然,預設是通過envoy這個proxy直接上報的,如果要經過mixer上報,也是可行的,可以進行相關配置,額外處理一下,具體可以參考idou老師教你學Istio 08: 呼叫鏈埋點是否真的“零修改”?

不過目前envoy支援的trace方案相對比較簡單,採用策略無法應用於Jaeger的所有策略,然後也不支援不同業務有不同的取樣策略,因此Istio進行配置,也是全域性的。

~/goDev/Applications/src/Istio.io/Istio/pilot/pkg/networking/core/v1alpha3/listener.go中的原始碼如下:

	if env.Mesh.EnableTracing {
		tc := model.GetTraceConfig()
		connectionManager.Tracing = &http_conn.HttpConnectionManager_Tracing{
			OperationName: httpOpts.direction,
			ClientSampling: &envoy_type.Percent{
				Value: tc.ClientSampling,
			},
			RandomSampling: &envoy_type.Percent{
				Value: tc.RandomSampling,
			},
			OverallSampling: &envoy_type.Percent{
				Value: tc.OverallSampling,
			},
		}
		connectionManager.GenerateRequestId = &google_protobuf.BoolValue{Value: true}
	}
複製程式碼

Trace(jaeger)的持久化儲存

jaeger在Istio中的現狀

更多jaegertracing資訊檢視官網架構介紹

jaeger的簡單部署

目前官方自帶的jaeger採用的是jaegertracing/all-in-one這個映象,這個會包含三個元件 jaeger-agent、jaeger-collector、jaeger-query,其中jaeger-collector會將資料儲存,而all-in-one這映象目前僅僅是儲存在記憶體裡面的,也就是臨時儲存,如果刪掉pod重啟,jaeger的資料是沒有了的。 jaegertracing/all-in-one映象記憶體儲存相關

為此,我們要考慮,如何將jaeger-collector的資料儲存指定為自己的儲存服務如ES叢集,採用官方自帶的肯定不行了,只能是自己部署一套jaeger服務,或者讓jaeger服務的agent的收集地址指向我們自己的服務

doc.Istio.cn/en/help/faq… Istio.io/docs/refere…

這兩篇文章有說設定trace_zipkin_url, trace_jaeger_url,可以達到目的,檢視yaml配置發現mixer只有設定trace_zipkin_url:

      containers:
      - name: mixer
        image: "docker.io/Istio/mixer:1.0.0"
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9093
        - containerPort: 42422
        args:
          - --address
          - unix:///sock/mixer.socket
          - --configStoreURL=k8s://
          - --configDefaultNamespace=Istio-system
          - --trace_zipkin_url=http://zipkin:9411/api/v1/spans
複製程式碼

這個只是針對Mixer元件而言的trace,如果是envoy本身的tarce,需要修改proxyv2的引數

jaeger持久化儲存的方案

Istio開源版本中,呼叫鏈對接jaeger是從envoy直接報上去的,沒有通過mixer來做。

因為呼叫鏈的資料量會很大,可靠性以及規模確是需要重點考慮的,因此必須要使用自己的服務 ,如果要配置為自己的jaeger服務,需要用kubectl修改Istio這個configmap中的zipkinAddress,配置為自己的服務地址,另外就是jaeger收資料是相容zipkin的。

kubectl get configmap Istio -n Istio-system  -o yaml |grep zipkinAddress

有兩處zipkinAddress地址,如下:
zipkin.Istio-system:9411

複製程式碼

對於華為雲而言,呼叫鏈這裡他們會對接到華為雲的apm服務,在可靠性和效能上都會有保證。

對接外部的trace系統[Jaeger]

K8S獨立部署Jaeger元件

根據K8S安裝部署Jaeger官方文件部署基於k8s的Jaeger的生產環境下的容器,注意一定要採用文件中Production這個生成的部署方式。

注意建立Elasticserach的時候,需要等待特別久,而且一定要等到Elasticserach這個pod的狀態為Running的時候才能建立Jaeger的其他元件,因為其他元件要依賴Elasticserach

然後修改jaeger-query這個Service的type為NodePort,然後通過 kubectl get service jaeger-query ,可以看到Port,然後利用host ip可以訪問,如2.2叢集獨立部署的Jaeger Query UI

需要部署jaeger相對比較麻煩,有一些引數需要設定,這個需要一定的學習能力,需要對jaeger對外暴露的埠、協議有一定的理解;然後還需要對儲存引擎如ES有一定的瞭解

另外,如果是通過二進位制安裝部署的話,相對較為簡單,只需要注意啟動引數即可

修改Istio到已有Jaeger服務

通過kubectl get configmap istio -n istio-system -o yaml |grep zipkinAddress先直接修改zipkinAddress的地址,指定為jaeger-collector這個Service的地址,埠是9411,只有這個9411地址才相容zipkin協議。因為envoy這個proxy會預設使用環境變數來設定zipkinAddress地址,預設地址是zipkin.istio-system:9411。修改過configmap之後,如果後面通過helm upgrade更新,則現在通過這個方式來修改的資料會失效,因此要完全修改,則必須通過修改過install/kubernetes/helm/istio//templates/configmap.yaml,同時還要修改install/kubernetes/helm/istio//charts/mixer/templates下面的zipkin相關的地址。

如果是istio.yaml這個模板檔案部署,則還需:

  • 修改istio.yaml檔案中的 zipkinAddress: zipkin.Istio-system:9411

    • 修改為:zipkinAddress: 10.233.61.200:9411【ClusterIP只針對K8S叢集內】
  • 修改istio.yaml檔案中的mixer相關的trace_zipkin_url地址

    • 修改為:--trace_zipkin_url=http://10.233.61.200:9411/api/v1/spans【ClusterIP只針對K8S叢集內】
  • 修改istio.yaml檔案中的proxyv2相關的zipkinAddress這個args

    • 修改為:10.233.61.200:9411【ClusterIP只針對K8S叢集內】

其他說明:

  • 修改所有zipkinAddress相關的地址為jaeger-collector這個Service的地址,這個如果都是K8S叢集,可以直接配置為ClusterIP,但是實際中需要配置一個全域性域名

    • istio這個configmap中的zipkinAddress地址,proxy會採用這個環境變數,但是已經部署的pod不會生效了,因為是手動注入的,istioctl kube-inject的時候才會用到proxy的環境變數,因此需要刪除Deployment然後重新部署生效。如果是自動注入的應該就只需要重啟pod。
  • jaeger-agent這個服務,如果Istio直接配置為外部jaeger地址的話,是不會經過jaeger-agent的,因此可以關閉

  • 由於通過ES進行資料儲存,因此現在殺掉jaeger相關的Pod,重啟後資料依然存在

  • 對接到外部jaeger服務的話,Istio自帶的jaeger相關的就可以直接關閉了

取樣策略修改和配置

Jaeger本身支援在client端調整和通過collector調整取樣策略,但是在Istio中並沒有Jaeger的client,只是envoy裡面支援了trace,直接修改envoy的trace相關原始碼不太友好。不過Istio中提供了一個全域性的設定,通過設定pilot的引數可以用來控制採用策略。

Istio的取樣流程大致是:在pilot的v1alpha3的流量管理介面中,在提供Listener的Http filters的時候會判斷:是否使能了mesh的trace,如果使能,則建立trace並讀取 採用配置,取樣通過環境變數PILOT_TRACE_SAMPLING來配置,其範圍是0.0 - 100.0,預設為100,全取樣。

修改的方式有兩種:

  • helm安裝時候的選項引數:pilot.traceSampling

  • 通過kubectl -n Istio-system edit deploy Istio-pilot修改PILOT_TRACE_SAMPLING變數

具體詳見

PILOT_TRACE_SAMPLING的值是100的時候,表示全取樣,每一次請求都會取樣,可以驗證得到,通過訪問測試頁面,記錄發起的請求次數,然後檢視Jaeger Trace UI,檢視Services為productpage的Trace,發現發起請求的次數和Trace的次數保持一致。

PILOT_TRACE_SAMPLING的值是50的時候,表示取樣1/2,每兩次請求都會取樣一次,修改完後,等待一小會兒,然後驗證。驗證結果表示現在並非1:2,但是也不完全是1/2的概率,具體還有待分析Jaeger的原理,但是至少證明了策略的修改是有效的

對接Mtrace系統

現有Mtrace系統,在原有Jaeger基礎上做了一些調整,使用了protobuf協議,同時增加了kafka。因此要想對接MTrace系統,還需要對proxy(envoy)做一些調整,並不是僅僅修改一些配置引數和地址等就可以解決的

業務接入Trace鏈路注意點

a,業務處理HTTP Header

雖然Istio能夠攔截流量並自動傳送Span資訊,但是要把整個過程統一追蹤並連結起來,還需要業務在程式碼中處理和追蹤相關的HTTP Header,這樣代理在傳送 Span 資訊的時候,才能正確的把同一個跟蹤過程統一起來。具體詳見

在Mtrace等系統或者原生的jaeger中,會有有個client的角色存在,這個client會建立並初始化一個trace,並處理好TraceID的事情,但是Istio後,服務中沒有Mtrace 發client端的 SDK,因此才需要再業務程式碼中處理好http header,但是對於非HTTP如TCP需要自行擴充套件支援,這個暫時不考慮;對應gRPC的話,因為也是基於http,因此可以通過一些方式新增。

所以,對於trace這塊,並非完全沒有任何侵入,業務程式碼有一點點小的改動,就是需要額外處理下http 的指定的header並依次傳遞

b,Istio設定取樣百分比

百分比預設值為100,全部取樣,可以修改為0-100;修改的方式有兩種:

  • helm安裝時候的選項引數:pilot.traceSampling

  • 通過kubectl -n Istio-system edit deploy Istio-pilot修改PILOT_TRACE_SAMPLING變數

具體詳見

這個設定是全域性的,沒有辦法針對特定業務有特定的取樣策略。如果需要對特定業務取樣,就需要給collector配置靜態的json策略檔案,然後也需要client支援,具體可以參考Jaeger官方文件。

問題 & TODO

  1. 需要業務程式碼中處理好http header,但是對於非HTTP而言,怎麼弄 ?

    • http 和 gRPC都需要業務自己處理好header
    • TCP需要自定義擴充套件欄位
  2. 不通過envoy上報,通過mixer上報

  3. 支援不同業務不同的採用策略

參考

Istio 分散式追蹤文件

jaeger-kubernetes生產部署

idou老師教你學Istio 08: 呼叫鏈埋點是否真的“零修改”?

相關文章