在非istio的環境中,如果我們選擇了zipkin作為鏈路追蹤的解決方案,那么我們需要業務代碼里對每次調用生成span/trace id,雖然大部分流行語言zipkin都提供了對應的sdk幫我們做了這些集成工作,但是我們還是要在發出請求時手動調用sdk提供的方法生成並攜帶相應header到業務下游,相當於要對每一種語言都要去手動做一次 request的封裝,如果公司使用的語言多了那么會是一種很繁瑣的工作。那么有沒有一種工具能幫我們自動生成每次調用所需的信息呢? 答案當然是有的,在istio環境中,這一切都變成了可能、當envoy收到調用請求時,會自動幫我們注入所需的headers,在業務代碼中我們只需做少量改動,只需要調用下游服務時傳遞header 就可以了。參考地址:https://istio.io/latest/zh/docs/tasks/observability/distributed-tracing/overview/
下面是一個python flask 應用在istio中接入zipkin的例子:
1.拓撲:
有三個應用,分別是 zipkin-a , zipkin-b, zipkin-c
調用關系是: zipkin-a -----> zipkin-b ----> zipkin-c
案例代碼:
zipkin-a:
from flask import Flask,request import requests app = Flask(__name__) @app.route('/') def hello_worlda(): tmp_headers = {} b3_headers = ["x-request-id","x-b3-traceid","x-b3-spanid","x-b3-parentspanid","x-b3-sampled","x-b3-flags","x-ot-span-context"] for header in b3_headers: if request.headers.get(header): tmp_headers.update({header:request.headers.get(header)}) requests.get('http://zipkin-b:5001',headers=tmp_headers) return 'zipkin-a!' if __name__ == '__main__': app.run(host="0.0.0.0",port=5000)
zipkin-b:
from flask import Flask,request import requests app = Flask(__name__) @app.route('/') def hello_worlda(): tmp_headers = {} b3_headers = ["x-request-id","x-b3-traceid","x-b3-spanid","x-b3-parentspanid","x-b3-sampled","x-b3-flags","x-ot-span-context"] for header in b3_headers: if request.headers.get(header): tmp_headers.update({header:request.headers.get(header)}) requests.get('http://zipkin-c:5002', headers=tmp_headers) return 'zipkin-b' if __name__ == '__main__': app.run(host="0.0.0.0",port=5001)
zipkin-c:
from flask import Flask,request app = Flask(__name__) @app.route('/') def hello_world(): print(' ------------- ^^^ -----------') print(request.headers) return 'Hello World!' if __name__ == '__main__': app.run(host="0.0.0.0",port=5002)
對應k8s manifest:
zipkin-a:
kind: Deployment metadata: name: zipkin-a spec: selector: matchLabels: app: zipkin-a version: "v1" replicas: 1 template: metadata: labels: app: zipkin-a version: "v1" spec: containers: - name: zipkin-a image: reg.xthklocal.cn/xthk-library/zipkin_a command: ["python","/tmp/a.py"] ports: - containerPort: 5000 name: http protocol: TCP --- apiVersion: v1 kind: Service metadata: name: zipkin-a spec: ports: - name: http-5000 port: 5000 protocol: TCP targetPort: 5000 selector: app: zipkin-a type: ClusterIP
zipkin-b:
apiVersion: apps/v1 kind: Deployment metadata: name: zipkin-b spec: selector: matchLabels: app: zipkin-b version: "v1" replicas: 1 template: metadata: labels: app: zipkin-b version: "v1" spec: containers: - name: zipkin-b image: reg.xthklocal.cn/xthk-library/zipkin_b command: ["python","/tmp/b.py"] ports: - containerPort: 5001 name: http protocol: TCP --- apiVersion: v1 kind: Service metadata: name: zipkin-b spec: ports: - name: http-5000 port: 5001 protocol: TCP targetPort: 5001 selector: app: zipkin-b type: ClusterIP
zipkin-c:
apiVersion: apps/v1 kind: Deployment metadata: name: zipkin-c spec: selector: matchLabels: app: zipkin-c version: "v1" replicas: 1 template: metadata: labels: app: zipkin-c version: "v1" spec: containers: - name: zipkin-c image: reg.xthklocal.cn/xthk-library/zipkin_c command: ["python","/tmp/c.py"] ports: - containerPort: 5002 name: http protocol: TCP --- apiVersion: v1 kind: Service metadata: name: zipkin-c spec: ports: - name: http-5000 port: 5002 protocol: TCP targetPort: 5002 selector: app: zipkin-c type: ClusterIP
istio 增加以下zipkin 配置:
data: mesh: |- defaultConfig: tracing: zipkin: address: 192.168.3.100:31377 #改成zipkin server的實際地址
進入任意能與zipkin-a 容器通信的容器調用zipkin-a 服務觸發鏈路上報 (如果采樣率未設置未全部采樣,需要多次調用才能看到效果)
登錄zipkin查看效果