Istio Trace鏈路追蹤方案

[TOC]html

Istio Trace鏈路追蹤方案

Istio Trace支持

envoy支持trace

envoy原生就支持分佈式追蹤系統的接入,如支持jaeger和zipkin,如envoy的Tracing官方文檔中代表envoy支持以下trace特性:git

  • 生成Request Id,填充HTTP的header字段x-request-id
  • 外部跟蹤服務集成,如支持LightStep, Zipkin或任何Zipkin兼容後端(如Jaeger)
  • 添加Client trace ID

相關信息能夠參考這裏 或者 envoy官方文檔Jaeger Tracing,另外,在源碼中有對應的trace相關的源碼github

Istio支持trace

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

  • 若是incoming的請求沒有trace相關的headers,則會再流量進入pods以前建立一個root spanjson

  • 若是incoming的請求包含有trace相關的headers,Sidecar的proxy將會extract這些span的上下文信息,而後再在流量進入pods以前建立一個繼承上一個span的新的span後端

因爲Istio的proxy代理是envoy,而envoy又原生支持jaeger,那所以Istio天然而然就支持jaeger了,在官方文檔Distributed Tracing中有相關較爲詳細的說明api

固然,默認是經過envoy這個proxy直接上報的,若是要通過mixer上報,也是可行的,能夠進行相關配置,額外處理一下,具體能夠參考idou老師教你學Istio 08: 調用鏈埋點是否真的「零修改」?bash

不過目前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: 調用鏈埋點是否真的「零修改」?

【"歡迎關注個人微信公衆號:Linux 服務端系統研發,後面會大力經過微信公衆號發送優質文章"】

個人微信公衆號
相關文章
相關標籤/搜索