【譯文連載】 理解Istio服務網格(第六章 可觀測性)

全書目錄

​本文目錄

第6章 可觀測性

6.1 分佈式調用鏈跟蹤(tracing)

6.1.1 基本概念

6.1.2 Jaeger

6.1.3 Istio對分佈式調用跟蹤的支持

6.2 遙測(Metric)

6.3 服務圖(Service graph)

 

第6章 可觀測性

微服務架構管理中最大的挑戰之一是如何通過簡單方法就能了解系統各個組件之間的關係。終端用戶的一次會話可能會流經多個甚至幾十個獨立部署的微服務,因此,發現哪裡有性能瓶頸或錯誤變得尤為重要。 

本章中,我們會通過Jaeger實現調用鏈跟蹤、通過Grafana和Prometheus實現遙測數據收集和展示,通過Kiali生成服務可視化圖。 

Istio的Mixer模塊由istio-policy和istio-telemetry服務組成,運行在istio-system命名空間的兩個獨立的pod中。下面的命令能很容易地將它們找出來,因為它們都帶有同樣的標籤:

    oc get pods -l istio=mixer -n istio-system

    oc get services -l istio=mixer -n istio-system

6.1 分佈式調用鏈跟蹤(tracing)

通常,了解微服務系統架構所做的第一件事情就是看那些服務參與了終端用戶會話。當多個團隊部署了大量互相獨立的微服務時,要理解它們之間的依賴會非常困難。Istio的Mixer模塊帶有開箱即用的能力,從分佈式服務中獲取跟蹤跨度(tracing span)。這意味着跟蹤功能是與編程語言無關的,因此使用不同語言進行編程的團隊都可以使用它。

6.1.1 基本概念

分佈式調用鏈跟蹤這概念起源於Google發表的論文《Dapper,大規模分佈式系統的跟蹤系統》。它具有以下幾個核心概念。 

OpenTracing:是CNCF(雲原生計算基金會)下的一個項目,其中包含了一套分佈式調用跟蹤的標準規範、各種語言的API、編程框架和函數庫。其目的是定義一套分佈式調用跟蹤的標準,以統一各種分佈式調用跟蹤的實現。目前已有大量支持OpenTracing規範的跟蹤程序(Tracer),包括Jaeger和Zipkin等。在微服務應用中採用OpenTracing API實現分佈式調用各種,可以避免供應商鎖定,從而以最小的代價和任何兼容OpenTracing的基礎設施對接。 

跨度(span:是兩個服務之間的一次請求與響應過程,比如一次REST調用或者數據庫操作。Jaeger將其定義為“系統中的一個邏輯的交互單元,具有操作名稱(operation time)、操作開始時間(start timestamp)和結束時間(finish timestamp)”。跨度是分佈式調用跟蹤的最小跟蹤單位。 

調用鏈(trace:是分佈式系統中的一個端到端事務,Jaeger將其定義為“數據或執行穿過系統的路徑,可視為跨度的有向無環圖”。 

跨度上下文(Span context:這是分佈式調用跟蹤的上下文信息,包括Trace ID,Span ID以及其它需要傳遞到下游服務的內容。一個OpenTracing的實現需要將跨度上下文通過某種序列化機制在進程邊界上進行傳遞,以將不同進程中的跨度關聯到一個調用鏈上。在基於HTTP協議的分佈式調用中,通常使用HTTP Header來傳遞跨度上下文信息。Zipkin使用b3 HTTP Header,Jaeger使用 uber-trace-id HTTP Header。Istio/Envoy支持b3 HTTP Header和x-ot-context Header。 

跨度的數據結構中主要包括以下內容:

  • Name:Span所代表的操作名稱,例如REST接口對應的資源名稱。

  • Start timestamp:Span所代表操作的開始時間

  • Finish timestamp:Span所代表的操作的的結束時間

  • Tags:一系列標籤,每個標籤由一個鍵值對組成。該標籤可以是任何有利於調用鏈分析的信息,例如方法名,URL等。

  • SpanContext:用於跨進程邊界傳遞Span相關信息,在進行傳遞時需要結合一種序列化協議使用。

  • References:該Span引用的其它關聯Span,主要有兩種引用關係,Childof和FollowsFrom。

o   Childof: 最常用的一種引用關係,表示Parent Span和Child Span之間存在直接的依賴關係。例PRC服務端Span和RPC客戶端Span,或者數據庫SQL插入Span和ORM Save動作Span之間的關係。

o   FollowsFrom:如果Parent Span並不依賴Child Span的執行結果,則可以用FollowsFrom表示。例如網上商店購物付款後會向用戶發一個郵件通知,但無論郵件通知是否發送成功,都不影響付款成功的狀態,這種情況則適用於用FollowsFrom表示。

 

一條調用鏈(trace)可被認為是一個由多個跨度(span)組成的有向無環圖,多個跨度組成一個請求的完整調用鏈。而分佈式跟蹤系統要實現的,就是記錄每次發送和接受動作的標識符和時間戳,將一次請求涉及到的所有服務串聯起來,只有這樣才能搞清楚一次請求的完整調用鏈。圖6-1是一個分佈式調用的例子,客戶端發起請求,請求首先到達負載均衡器(load balancer),接着經過認證(auth)服務,計費(billing)服務,然後請求資源(resource),最後返回結果。

 

圖6-1. 一個分佈式調用示例

 

分佈式跟蹤系統負責採集和存儲調用鏈數據,然後通常會使用包含時間軸的時序圖來將這個調用鏈展現出來,橫坐標是時間,圓角矩陣是請求的各個執行階段,如圖6-2所示。

 

圖6-2. 分佈式跟蹤系統生成的時序圖 

6.1.2 Jaeger

Jaeger是Uber推出的一款開源分佈式跟蹤系統,兼容OpenTracing API,於2017年9月加入CNCF基金會,其架構如圖6-3所示。

  

 圖6-3. Jaeger架構 

Jaeger 主要由以下幾部分組成:

  • Client – Jaeger的客戶端,實現了符合OpenTracing API標準的SDK,支持主流編程語言。客戶端直接集成在應用代碼中,應用程序通過其API寫入數據,客戶端庫把調用鏈信息按照應用程序指定的採樣策略傳遞給Agent。在應用中調用Jaeger Client庫記錄跨度的過程通常被稱為埋點。

  • Agent – 它是一個監聽在UDP端口上接收跨度數據的網絡守護進程,它會將數據批量發送給Collector。它被設計成一個基礎組件,部署在宿主機上。Agent將Client 庫和Collector 解耦,為Client庫屏蔽了路由和發現Collector的細節。

  • Collector – 接收Agent發送來的數據,然後將數據寫入後端存儲。Collector被設計成無狀態的組件,因此您可以同時運行任意數量的Collector。

  • Data Store – 後端存儲被設計成一個可插拔的組件,支持將數據寫入Cassandra和Elastic search。

  • Query – 接收查詢請求,然後從後端存儲系統中檢索調用鏈並通過UI進行展示。Query 是無狀態的,您可以啟動多個實例,把它們部署在Nginx這樣的負載均衡器後面。

6.1.3 Istio對分佈式調用跟蹤的支持

Istio利用Envoy的分佈式調用跟蹤功能來為網格中的應用提供開箱即用的跟蹤能力。Istio支持接入多種跟蹤後端系統(tracing backend),包括Zipkin、Jaege和LightStep。Istio支持與分佈式跟蹤系統的兩種整合方式:

  • 基於Envoy的整合(Envoy-based)

  • 基於Mixer的整合(Mixer-based) 

Istio支持與LightStep、Zipkin以及與Zipkin API相兼容的後端比如Jaeger進行基於Envoy的整合。在這種整合中,Envoy邊車代理直接向後端跟蹤系統發送跟蹤信息。它負責:

  • 為每個流經它的請求產生請求ID(request ID)和跟蹤頭(trace headers,比如x3-B3-TraceID)

  • 為每個流經它的請求根據請求及其響應的元數據產生跟蹤跨度

  • 發送所產生的跟蹤跨度信息到跟蹤後端

  • 轉發跟蹤頭給被代理的應用 

以請求ID為例,Envoy使用x-request-id頭去唯一地定位一個請求,並為它做日誌和跟蹤。Envoy會為每個從外部進入網格的請求產生x-request-id並放到HTTP頭中,也會為不帶有此信息的內部請求產生此ID。 

Istio還支持以基於Mixer的方式與某些跟蹤後端進行整合,比如Stackdriver。在這種方式中,Envoy負責為每個流經它的請求產生請求ID和跟蹤頭(比如x3-B3-TraceID),並異步發送給Mixer,同時轉發跟蹤頭給被代理的應用;Mixer則負責為每個請求產生跟蹤跨度數據,並把這些數據發給所配置的跟蹤後端。 

儘管Envoy能夠自動產生跟蹤信息,它還是要依賴應用將跟蹤頭信息傳遞給後續請求。在應用中,應用需要從進來的請求中獲取以下信息並傳遞到出去的請求中:

·       x-request-id

·       x-b3-traceid

·       x-b3-spanid

·       x-b3-parentspanid

·       x-b3-sampled

·       x-b3-flags

·       x-ot-span-context 

對於某些應用,如果所選擇的框架支持自動傳遞這些HTTP頭,那麼就不用顯式傳遞跟蹤上下文了。比如,Spring Boot框架在github中有個開源項目https://github.com/opentracing-contrib/java-spring-cloud ,能支持自動跟蹤。我們customer和preference示例程序使用符合OpenTracing標準的TracerResolver庫(https://github.com/jaegertracing/jaeger-client-java/tree/master/jaeger-tracerresolver),它會被自動加載。 

在筆者的測試環境中,Istio採用基於Envoy的方式與後端跟蹤系統Jaeger整合。Jaeger的服務和pod名稱為istio-tracing,採用的Jaeger鏡像是docker.io/jaegertracing/all-in-one,它包含jaeger-agent、jaeger-collector和jaeger-query這三個組件。其中,Envoy代理被配置為自動地將跟蹤信息發送到jaeger-collector服務,jaeger-collector負責將跟蹤數據寫入存儲卷。要注意的是,這個存儲卷採用的是pod所在宿主機上的臨時文件夾。因此,當istio-tracing這個pod被重建後,所保存的數據都會丟失。因此,在生產系統中,要考慮使用持久存儲來保存數據。 

 

運行下面的命令來打開Jaeger界面:

    minishift openshift service tracing –in-browser 

你可以從下拉列表中選擇customer服務,再展開所產生的跟蹤,如圖6-4所示:

 

圖6-4. Jager中的customer-preference-recommendation跟蹤的展示 

Istio能為所有流經網格的請求產生跟蹤信息。這在開發階段會很有用,能幫助你進行充分的調試;但是在某些時候,比如性能測試時或在生產系統中,這會對系統性能帶來一定壓力,而且數量龐大的數據也會佔用大量存儲空間。為了解決這個問題,Jaeger支持設置採樣率。採樣率通過Istio Pilot的“PILOT_TRACING_SAMPLING”環境變量進行配置。當PILOT_TRACING_SAMPLING的值為100時,表示全採樣,也就是每一次請求都會採樣;當PILOT_TRACING_SAMPLING值為50時,表示1/2採樣,也就是每兩次請求會採樣一次。Istio中的PILOT_TRACING_SAMPLING的默認值為1,表示每100個請求採樣一次。具體請查閱Jaeger官方文檔。可通過下面的命令進行查看或修改:

    oc edit deployment istio-pilot -n istio-system

6.2 遙測(Metric)

Istio的另一個核心功能是網絡流量的可觀測性。因為網格內服務間的所有流量都會經過Envoy代理,Istio的控制平面就能從這些代理收集日誌和指標,從而讓你可深入地了解網格的狀況。Istio控制平面中的一組件為Mixer,其在K8S中有兩個獨立的部署,一個是istio-policy,另一個是istio-telemetry。前者提供控制策略,後者提供遙測數據收集。 

Istio網格中的每個pod中都會有一個Envoy代理,它負責在發出每個請求前調用istio-policy來檢查前置條件,並在請求結束後調用istio-telemetry來發送遙測數據。為提高性能,Envoy代理會在本地緩存策略和遙測數據,以減少調用Mixer的次數。Mixer可配置多種後端,其中Metric後端負責接收遙測數據。在Istio部署中,通常會使用Prometheus來作為遙測後端。Prometheus(普羅米修斯)是一款開源彈性監控解決方案,它將其數據存儲至時序數據庫,且提供了多維度的數據模型、強大的查詢語言和簡單的面板來生成被監控資源的報表。 

 

圖6-5. Mixer及其各種後端 

默認地,Isito會利用Prometheus和Grafana來存儲和展示服務網格中的測量數據。在Istio的默認部署中會部署Prometheus和Grafana服務,並做了基本配置,添加了若干度量指標,使得基本遙測數據能被收集到和展示出來。通過Istio提供的CRD,還能自定義度量指標,並使得它們被自動地收集到。Grafana是一款開源數據可視化看板,可指定多個數據源執行查詢,將枯燥的數據轉化為多維度的面板。Isito中的Grafana將Prometheus作為其數據源,提供了多個為Istio定製的面板(Dashboard),能從多個維度展示Istio服務網格的狀態。這些服務之間的基本交互過程如圖6-6所示。

  

 圖6-6. 有關服務之間的基本交互流程 

運行下面的命令可直接在瀏覽器中打開Prometheus面板: minishift openshift service prometheus –in-browser 

在Prometheus面板中,你可以自定義測量項並圖形化結果。比如,你可以查看recommendation服務的v2版本的總請求數,如圖6-7所示:

     istio_requests_total{destination_app=”recommendation”, destination_version=”v2″}

 

 圖6-7.Prometheus面板

 

你還可以查看pod的內存使用量:   container_memory_rss{container_name=”customer”} 

Prometheus是一個非常強大的從Kubernetes/OpenShift集群中收集和展現測量數據的工具。目前它是CNCF聯盟中頂級的已畢業項目之一。關於它的更多信息,請訪問Prometheus官網。 

運行下面的命令去獲得Grafana界面的URL:   minishift openshift service grafana –url 

在Grafana面板左上側選擇Istio Workload Dashboard,如圖6-8所示:

  

 圖6-8. Grafana中的Istio Workload 面板

6.3 服務圖(Service graph)

早期Istio就提供了開箱即用的基本的服務圖形化功能。現在,Istio有了一個新的功能更全面的服務圖形化工具和總體監控監控方案,那就是由紅帽團隊創建的Kiali,如圖6-9所示。Kiali項目為一些有趣的問題提供了答案:我的Istio服務網格中有哪些微服務?它們之間是如何連接的? 

本書寫作時,Kiali還需要被單獨安裝,安裝步驟還比較複雜。Kiali需要知道Jaeger和Granfana的URL,並需被設置給一些環境變量。Kiali安裝步驟如下:

    # URLS for Jaeger and Grafana

    export JAEGER_URL=”https://tracing-istio-system.$(minishift ip).nip.io”

    export GRAFANA_URL=”https://grafana-istio-system.$(minishift ip).nip.io”

    export IMAGE_VERSION=”v0.10.0″

    curl -L http://git.io/getLatestKiali | bash 

如果安裝時碰到問題,請訪問Kiali用戶論壇https://groups.google.com/forum/#!forum/kiali-users。象Istio一樣,Kiali也是一個快速發展中的項目。它的主菜單和Graph面板如圖6-9所示。

 

圖6-9. Kiali面板 

Kiali的架構如圖6-10所示。它包括兩個組件Kiali front-end和Kiali back-end。前者用於界面展示,它從Kiali back-end獲取數據並展現給用戶;後者和Istio通信,獲取和處理數據,並將數據通過Kiali front-end展現給用戶。Kiali依賴於Istio,它通過底層平台API和Prometheus獲取Istio的數據和配置。當前Kiali支持OKD和Kubernetes,利用它們的API去獲得集群和服務網格的配置,比如命名空間、服務、部署等等。Kiali直接與Prometheus通信,使用保存在Prometheus中的數據,計算出服務網格的拓撲結構,展示遙測數據,計算健康狀態以及展示存在的問題等。

  

 圖6-10. Kiali架構 

Kiali還可以與Grafana集成,在其Workload界面中添加View in Granfana鏈接,點擊後直接跳轉至Grafana界面,展示該應用的遙測數據,如圖6-11所示。

 

 圖6-11. 在Kiali中集成Grafana鏈接 

Kiali還可以與Jaeger集成,在其頁面中可以直接查看服務的分佈式調用跟蹤信息,如圖6-12所示。具體配置方法請查閱https://kiali.io/documentation/distributed-tracing/

  

 圖12. 在Kiali中查詢服務的分佈式調用跟蹤信息

 

在Istio中,Kiali與Grafana和Jaeger的集成,是在ConfigMap kiali中配置的。它會被掛載到kiali pod中,成為kiali的配置文件/kiali-configuration/config.yaml。在譯者的環境中,其內容如下:

istio_namespace: istio-system

auth:

  strategy: login

server:

  port: 20001

  web_root: /kiali

external_services:

  tracing:

    in_cluster_url: http://tracing.istio-system/jaeger

    url: http://tracing-istio-system.router.default.svc.cluster.local/jaeger

  grafana:

    url: http://grafana-istio-system.router.default.svc.cluster.local

  prometheus:

url: http://prometheus:9090 

本章中,你已經看到了好幾個開箱即用的工具和第三方工具,Istio使得你的應用的各個微服務組件變得越來越可視和可觀測。在前面章節中介紹了如何引入錯誤和網絡延遲,現在,通過這些工具,你就能更好地跟蹤問題在哪裡了。

 

書籍英文版下載鏈接為 https://developers.redhat.com/books/introducing-istio-service-mesh-microservices/,作者 Burr Sutter 和 Christian Posta

 

本中文譯稿版權由本人所有。水平有限,錯誤肯定是有的,還請海涵。

 

 感謝您的閱讀,歡迎關注我的微信公眾號: