天天看點

非容器應用與K8s工作負載的服務網格化實踐-7 基于ASM的POD和VM可觀測性實踐

服務網格的可觀測性能力是通過Sidecar實作的,對于業務服務源代碼來說是近零侵入的。可觀測性包括資料采集、資料存儲、資料展示和聚合分析。主要有三個次元:Metrics、Logging、Tracing,分别用于可聚合資料、離散事件、請求鍊路的可觀測性。相應地,阿裡雲生态下,ASM打通了ARMS( https://www.aliyun.com/product/arms) 、Log Service( https://www.aliyun.com/product/sls) 、TracingAnalysis( https://www.aliyun.com/product/xtrace)

,供使用者使用服務網格的可觀測性能力。

本篇隻涉及請求鍊路,這個次元最容易展示VM中非容器應用網格化帶來的增益,以抛磚引玉。

1 近零侵入

本篇示例容器中的微服務源代碼依然使用

http_springboot_demo

。抛開雲原生,單看這個springboot開發的微服務,如果要實作全鍊路請求的采集,需要有一行主動打點的日志,維護并記錄

requestId

作為全鍊路唯一鍵的請求和響應資訊。這個資訊由日志采集agent上報,然後由日志系統根據

requestid

提供查詢和聚合。代碼示意如下:

@GetMapping(path = "/hello/{msg}")
public String sayHello(@PathVariable String msg) {
    String url = "http://" + HTTP_HELLO_BACKEND + ":8001/hello/" + msg;
    String backServiceResult = helloService.sayHello(url);
    String result = HELLO + " " + msg;
    log.info("打點日志...")
    return result + backServiceResult;
}           
public String sayHello(String url) {
    Request request = new Request.Builder()
            .url(url)
            .build();
    try (Response response = client.newCall(request).execute()) {
      ...           

這個微服務網格化後,微服務源代碼不再需要主動打點,相應地也無需維護全鍊路唯一鍵。這些工作Sidecar都已經實作了,而且是基于CNCF雲原生生态下的

OpenTracing

(/

OpenTelemetry

)标準實作的,無論從專業性還是标準上,都優于業務代碼自己打點。而這個『近零侵入』的地方就是“propagate tracing headers”——需要業務代碼傳遞如下header到下遊。僅此而已。代碼示意如下:

@GetMapping(path = "/hello/{msg}")
public String sayHello(@PathVariable String msg, @RequestHeader Map<String, String> headers) {
    String url = "http://" + HTTP_HELLO_BACKEND + ":8001/hello/" + msg;
    String backServiceResult = helloService.sayHello(url, headers);
    String result = HELLO + " " + msg;
    return result + backServiceResult;
}           

上面這段代碼,較之前述一段,少了第6行主動打點,多了

RequestHeader

參數。傳遞給下遊的代碼示意如下:

public String sayHello(String url, Map<String, String> headers) {
    Map<String, String> tracingHeaders = buildTracingHeaders(headers,
            "x-request-id",
            "x-b3-traceid",
            "x-b3-spanid",
            "x-b3-parentspanid",
            "x-b3-sampled",
            "x-b3-flags",
            "x-ot-span-context");
    Request request = new Request.Builder()
            //propagate tracing headers
            .headers(Headers.of(tracingHeaders))
            .url(url)
            .build();
    try (Response response = client.newCall(request).execute()) {           

之是以說是『近零侵入』是因為

RequestHeader

參數在多數業務代碼中本身就存在,就算不存在也可以直接從spring容器context中直接拿到,是以侵入的代價就是構造并傳遞上面代碼段中的header map。而這帶來的好處是省去了主動打點代碼及其維護成本。

2 搭建實驗環境

本篇實驗繼續使用第2篇的元件拓撲,如下圖所示。本篇的重點是确認完整的端到端鍊路的可追蹤性。

由于Sidecar負責上報鍊路追蹤的資料,業務代碼無需感覺具體的鍊路追蹤系統。ASM支援阿裡雲鍊路追蹤産品TracingAnalysis,也支援使用者自建Zipkin。對于虛拟機的網格化鍊路追蹤而言,隻需在啟動參數中提供鍊路追蹤系統即可。餘文詳述。

TracingAnalysis

由于ASM已經在資料平面建立了TracingAnalysis相關的POD,我們隻需為虛拟機提供一個鍊路追蹤服務即可。示意如下:

apiVersion: v1
kind: Service
metadata:
  labels:
    app: tracing
    component: zipkin
  name: zipkin-slb
  namespace: istio-system
spec:
  ports:
    - name: zipkin
      port: 9411
      protocol: TCP
      targetPort: 9411
  selector:
    app: tracing
    component: zipkin
  type: LoadBalancer           
k get svc zipkin-slb -n istio-system
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)          AGE
zipkin-slb   LoadBalancer   172.19.10.62   39.107.229.139   9411:31170/TCP   178m           

通過如下指令模拟dns将鍊路追蹤服務提供給虛拟機:

zipkin_clusterIp=$(k get svc zipkin-slb -n istio-system | grep zipkin | awk -F ' ' '{print $4}')
echo "$zipkin_clusterIp zipkin.istio-system" >dns_record

VMS=("$VM_PUB_1" "$VM_PUB_2" "$VM_PUB_3")
for vm in "${VMS[@]}"; do
  ssh root@"$vm" "sed -i '/zipkin.istio-system/d' /etc/hosts"
  ssh root@"$vm" "cat >> /etc/hosts" <dns_record
done
rm -rf dns_record           

最後在VM中向

/var/lib/istio/envoy/sidecar.env

追加一行:

ISTIO_AGENT_FLAGS="--zipkinAddress zipkin.istio-system:9411 --serviceCluster vm1-hello2-en"           

Zipkin

自建zipkin的方式參見文檔:

向自建系統導出ASM鍊路追蹤資料

,其他步驟與TracingAnalysis一緻。

實驗環境

與第2篇類似,通過如下腳本啟動

本篇實驗執行個體

的相關各元件:

sh asm/ack.deploy.sh
sh asm/asm.deploy.sh
sh asm/asm_traffic_shift.sh
sh asm/dns.fake.sh           

3 鍊路追蹤驗證

使用如下

腳本

發起端到端調用:

IP=$(k -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
for i in {1..1000}; do
  resp=$(curl -s "$IP":8008/hello/eric)
  echo "$resp" >>test_traffic_shift_result
done           

全局拓撲

TracingAnalysis提供了全局拓撲,通過這個拓撲圖,我們可以一目了然地看到VM中的應用和ack容器中的POD一樣,作為端到端鍊路上的一個endpoint存在。示意如下。

非容器應用與K8s工作負載的服務網格化實踐-7 基于ASM的POD和VM可觀測性實踐

Tracing

登入TracingAnalysis或者自建zipkin系統檢視tracing。如下圖所示,VM中的Sidecar上報了hello2應用鍊路的

inbound

outbound

資料,與hello1/hello3 POD形成完整的調用鍊路。

非容器應用與K8s工作負載的服務網格化實踐-7 基于ASM的POD和VM可觀測性實踐

全鍊路聚合

通過TracingAnalysis的全鍊路聚合,可以完整地看到hello2的三個版本

vm1-hello2-en

/

vm2-hello2-fr

vm3-hello2-es

鍊路追蹤資料的聚合資訊。

非容器應用與K8s工作負載的服務網格化實踐-7 基于ASM的POD和VM可觀測性實踐

到此,基于ASM的POD和VM可觀測性實踐驗證完畢。通過本篇實驗,我們可以看到,非容器應用網格化後直接具備了強大的服務可觀測性能力。

由于時間和精力關系,本系列到此結束。希望在雲原生之下,服務網格能為我們的産品帶來一些不同和驚喜。