istio-opentracing鏈路追蹤方案
istio-opentracing鏈路追蹤主要是由sidecar(envoy)支持的,istio只是在上層進行配置的修改。
envoy鏈路追蹤
envoy主要用三個功能來支撐系統范圍內的跟蹤
- 生成Request ID: envoy會在需要的時候生成UUID,並操作名為[x-request-id]的HTTP Header。應用可以轉發這個Header用於統一的記錄和追蹤。
- 集成外部追蹤服務: envoy支持可插件的外部跟蹤可視化服務。目前支持LightStep、zipkin或者Zipkin兼容的后端(例如:jaeger).另外可自己添加其它的追蹤服務。
- 客戶端跟蹤ID連接: x-client-trace-id Header 可以用來把不信任的請求 ID 連接到受信的 x-request-id Header 上。
初始化追蹤
有多種途勁初始化追蹤
- 外部客戶端,使用x-client-trace-id Header。
- 內部服務,使用x-envoy-force-trace Header。
- 隨機采用使用運行時設置: random_sampling。
跟蹤上下文信息
不管使用的是哪個跟蹤服務,都應該傳播x-request-id,這樣在被調用服務中啟動相關性的記錄。
- 如果使用了 LightStep 跟蹤器,在發送 HTTP 請求到其他服務,Envoy 依賴這個服務來傳播 x-ot-span-context Header。
- 如果使用的是 Zipkin,Envoy 要傳播的是 B3 Header.(x-b3-traceid, x-b3-spanid, x-b3-parentspanid, x-b3-sampled,以及 x-b3-flags)也可以由外部客戶端提出,用來啟用或者禁用某個服務的跟蹤請求。
istio鏈路追蹤
鏈路追蹤參數
istio鏈路追蹤提供了全局配置zipkinAddress。istio的sidecar流量攔截后上報到鏈路系統,envoy的上報地址通過proxy_init的--zipkinAddress參數傳入。由上面可知envoy的鏈路追蹤主要的原生支持是jaeger。
istio的鏈路追蹤並不能在sidecar中全部處理,是有侵入性的。業務需要存儲幾個特殊字段,在要調用下個服務時,把這幾個字段帶上。這樣才能把整條鏈路串起來。具體可看上面的跟蹤上下文信息,istio鏈路追蹤例子。
mix模塊中的telemetry和policy這兩個的鏈路追蹤是通過參數--trace_zipkin_url=http://zipkin:9411/api/v1/spans 來配置的。
采樣率
鏈路的采樣率istio中只提供了一個全局的配置,通過配置pilot的參數PILOT_TRACE_SAMPLING來控制,其范圍是0.0-100.0,最小可配參數0.01,默認100。
修改方式:
- helm安裝時參數選項:[pilot.traceSampling](https://istio.io/docs通過kubectl -n Istio-system edit deploy Istio-pilot修改PILOT_TRACE_SAMPLING變量。/reference/config/installation-options/)。
- 生成的yaml文件中修改PILOT_TRACE_SAMPLING變量,重新apply。
- 通過kubectl -n Istio-system edit deploy Istio-pilot修改PILOT_TRACE_SAMPLING變量。
jaeger
istio的tracing默認使用jaeger來實現日志追蹤的發送,存儲,查詢。
先來看jaeger的架構圖:
jaeger主要由以下幾部分組成
- jaeger-client為不同語言實現的OpenTracing標准的SDK.應用程序通過API寫入數據,然后按照指定策略把trace傳遞給jaeger-agent.
- agent是一個UDP中轉服務,它將數據批量發送給collector.它是一個基礎組件,布在所有機器上.
- collector接收agent發送來的數據,然后將數據寫入后端.collector是一個無狀態組件,可以建任意數量.
- data-store后端存儲被設計成一個可插拔的組件.支持Cassandra和ElasticSearch.
- query從存儲中提取數據並通過UI展示.
istio中jaeger現狀
istio目前官方自帶的是all-in-one的鏡像,所有的組件都包含在一個鏡像中.數據的存儲是存在內存中,pod刪除或重啟,所有的數據就全沒有了.這沒法線上使用.
為此,我們需要考慮將數據存儲為指定的存儲服務,采用官方自帶的肯定不行,需要自己重新部署一套jaeger。
jaeger持久化存儲
k8s部署jaeger
根據官方文檔部署基於k8s的Jaeger的生產環境下的容器,這個要采用Production這個生成的部署方式。
這種方式的部署比較麻煩,需要對jaeger有一定的理解,對存儲服務如ES都需要有一定的研究。因此這種試不推薦。
接入自己的ES服務
istio的鏈路追蹤通過zipkin直接傳輸到jaeger-collector,jaeger-collector將數據發送到自己現有的ES集群進行存儲,jaeger-query直接去現有ES集群查詢。
鏈路追蹤發送到jaeger-collector
如果不在同個namespace下,需要修改zipkin地址為jaeger的zipkin收集地址。envoy這個proxy會默認使用環境變量來設置zipkinAddress地址,默認地址是zipkin.istio-system:9411。可在yaml下查找zipkinAddress來修改,然后更新就可以。如果后繼有helm update更新,需要去修改charts,在install/kubernetes/helm/istio//templates/configmap.yaml
和 install/kubernetes/helm/istio//charts/mixer/templates
這兩個下面的zipkin地址。 mix相關的trace_zipkin_url的zipkin也要改成對應的地址。
- 修改istio的zipkin地址需要重新啟動pod。
- jaeger-agent這個服務,因為我們是直接配置到jaeger-collector因些不需要。
jaeger-collector到ES集群
這個官方的jaeger是支持發送到kafka,但由於jaeger會生成3個index(jaeger-span,jaeger-service,jager-dependencies),而kafka發送到ES時,要區分有點麻煩。暫時先直接發送到ES。
jaeger-query
這個配置只需將查詢地址改為ES的地址。
jaeger-query的dependencies服務生成圖需要自己配置spark-dependencies
線上例子
jaeger-collector的ES配置參數可通過下面來查看,jaeger-query的參數也是一樣的
docker run \
-e SPAN_STORAGE_TYPE=elasticsearch \
jaegertracing/jaeger-collector:1.8 \
--help
k8s jaeger的configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: jaeger-configuration
namespace: istio-system
labels:
app: jaeger
jaeger-infra: configuration
data:
span-storage-type: elasticsearch
collector: |
es:
server-urls: http://example1.com:9200,http://example2.com:9200
index-prefix: online-opentracing
collector:
zipkin:
http-port: 9411
query: |
es:
server-urls: http://example1.com:9200,http://example2.com:9200
index-prefix: online-opentracing
k8s jaeger-collector和jaeger-query
apiVersion: v1
kind: List
items:
- apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: jaeger-collector
namespace: istio-system
labels:
app: jaeger
jaeger-infra: collector-deployment
spec:
replicas: 3
strategy:
type: Recreate
template:
metadata:
labels:
app: jaeger
jaeger-infra: collector-pod
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "14268"
spec:
containers:
- image: jaegertracing/jaeger-collector:1.8.2
name: jaeger-collector
args: ["--config-file=/conf/collector.yaml"]
ports:
- containerPort: 14267
protocol: TCP
- containerPort: 14268
protocol: TCP
- containerPort: 9411
protocol: TCP
readinessProbe:
httpGet:
path: "/"
port: 14269
volumeMounts:
- name: jaeger-configuration-volume
mountPath: /conf
env:
- name: SPAN_STORAGE_TYPE
valueFrom:
configMapKeyRef:
name: jaeger-configuration
key: span-storage-type
volumes:
- configMap:
name: jaeger-configuration
items:
- key: collector
path: collector.yaml
name: jaeger-configuration-volume
- apiVersion: v1
kind: Service
metadata:
name: jaeger-collector
namespace: istio-system
labels:
app: jaeger
jaeger-infra: collector-service
spec:
ports:
- name: jaeger-collector-tchannel
port: 14267
protocol: TCP
targetPort: 14267
- name: jaeger-collector-http
port: 14268
protocol: TCP
targetPort: 14268
- name: jaeger-collector-zipkin
port: 9411
protocol: TCP
targetPort: 9411
selector:
jaeger-infra: collector-pod
type: ClusterIP
- apiVersion: v1
kind: Service
metadata:
name: zipkin
namespace: istio-system
labels:
app: jaeger
jaeger-infra: zipkin-service
spec:
ports:
- name: jaeger-collector-zipkin
port: 9411
protocol: TCP
targetPort: 9411
selector:
jaeger-infra: collector-pod
type: ClusterIP
- apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: jaeger-query
namespace: istio-system
labels:
app: jaeger
jaeger-infra: query-deployment
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: jaeger
jaeger-infra: query-pod
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "16686"
spec:
containers:
- image: jaegertracing/jaeger-query:1.8.2
name: jaeger-query
args: ["--config-file=/conf/query.yaml"]
ports:
- containerPort: 16686
protocol: TCP
readinessProbe:
httpGet:
path: "/"
port: 16687
volumeMounts:
- name: jaeger-configuration-volume
mountPath: /conf
env:
- name: SPAN_STORAGE_TYPE
valueFrom:
configMapKeyRef:
name: jaeger-configuration
key: span-storage-type
volumes:
- configMap:
name: jaeger-configuration
items:
- key: query
path: query.yaml
name: jaeger-configuration-volume
- apiVersion: v1
kind: Service
metadata:
name: jaeger-query
namespace: istio-system
labels:
app: jaeger
jaeger-infra: query-service
spec:
type: NodePort
ports:
- name: jaeger-query
port: 80
protocol: TCP
targetPort: 16686
nodePort: 32686
selector:
jaeger-infra: query-pod
參考文檔: