Istio調用鏈埋點原理剖析—是否真的“零修改”分享實錄(上)
關於Istio調用鏈的分享。
前言
大家好,我是idouba,來自華為Cloud BU,當前在做Istio服務網格在華為雲容器服務的產品化工作。今天跟大家分享的主題是Istio調用鏈相關內容。通過剖析Istio的架構機制與Istio中調用鏈的工作原理來解答一個大家經常問道的一個問題:Istio是否像其官方文檔中宣傳的一樣,對業務代碼完全的無侵入,無需用做任何修改就可以完成所有的治理能力,包括調用鏈的埋點?
關於這個問題,可以提前透漏下,答案是讓人有點沮喪的,得改點。在Isito中你不用在自己的代碼裏使用各種埋點的SDK來做埋點的邏輯,但是必須要有適當的配合的修改。
為什麽本來無侵入的Service Mesh形態的技術卻要求我們開發者修改些代碼,到底要做哪些修改?Istio中調用鏈到底是怎麽工作的?在下面的內容中將逐個回答這些問題。
本次分享的主題包括兩部分: 第一部分作為背景和基礎,介紹Istio的架構和機制;第二部分將重點介紹Istio調用鏈的相關內容,解答前面提出的幾個問題。
Isito的架構和機制
Service Mesh
如官方介紹,Istio是一個用於連接、控制、保護和觀測服務的一個開放平臺。即:智能控制服務間的流量和API調用;提供授權、認證和通信加密機制自動保護服務安全;並使用各種策略來控制調用者對服務的訪問;另外可以擴展豐富的調用鏈、監控、日誌等手段來對服務的與性能進行觀測。
Istio是Google繼Kubernetes之後的又一重要項目,提供了Service Mesh方式服務治理的完整的解決方案。2017年5月發布第一個版本 0.1, 2018年6月1日發布了0.8版本,第一個LTS版本,當前在使用的1.0版本是今年7.31發布,對外宣傳可用於生產。最新的1.1版本將2018.11中旬最近發布(當時規劃實際已延遲,作者註)。
Istio屬於Service Mesh的一種實現。通過一張典型圖來了解下Service Mesh。如圖示深色是Proxy,淺色的是服務,所有流入流出服務的都通過Proxy。Service Mesh正是由這一組輕量代理組成,和應用程序部署在一起,但是應用程序感知不到他的存在。特別對於雲原生應用,服務間的應用訪問拓撲都比較復雜,可以通過Service Mesh來保證服務間的調用請求在可靠、安全的傳遞。在實現上一般會有一個統一的控制面,對這些代理有個統一的管理,所有的代理都接入一個控制面。對代理進行生命期管理和統一的治理規則的配置。
這裏是對Service Mesh特點的一個一般性描述,後面結合Isito的架構和機制可以看下在Istio中對應的實現。
可以看到Service Mesh最核心的特點是在Proxy中實現治理邏輯,從而做到應用程序無感知。其實這個形態也是經過一個演變的過程的:
最早的治理邏輯直接由業務代碼開發人員設計和實現,對服務間的訪問進行管理,在代碼裏其實也不分治理和業務,治理本身就是業務的一部分。這種形態的缺點非常明顯就是業務代碼和治理的耦合,同時公共的治理邏輯有大量的重復。
很容易想到封裝一個公共庫,就是所謂的SDK,使用特定的SDK開發業務,則所有治理能力就內置了。Spring Cloud和Netflix都是此類的工具,使用比較廣泛,除了治理能力外,SDK本身是個開發框架,基於一個語言統一、風格統一的開發框架開發新的項目非常好用。但這種形態語言相關,當前Java版本的SDK比較多。另外對於開發人員有一定的學習成本,必須熟悉這個SDK才能基於他開發。最重要的是推動已經在用的成熟的系統使用SDK重寫下也不是個容易的事情。比如我們客戶中就有用C開發的系統,運行穩定,基本不可能重寫。對這類服務的治理就需要一個服務外面的治理方式。
於是考慮是否可以繼續封裝,將治理能力提到進程外面來,作為獨立進程。即Sidecar方式,也就是廣泛關註的Service Mesh 的。真正可以做到對業務代碼和進程0侵入,這對於原來的系統完全不用改造,直接使用Sidecar進行治理。
用一段偽代碼來表示以上形態的演變:
可以看到隨著封裝越來越加強,從公共庫級別,到進程級別。對業務的侵入越來越少,SDK的公共庫從業務代碼中解耦,Sidecar方式直接從業務進程解耦了。對應的治理位置越來越低,即生效的位置更加基礎了。尤其是Service Mesh方式下面訪問通過 Proxy執行治理,所以Service Mesh的方式也已被稱為一種應用的基礎設施層,和TCP/IP的協議棧一樣。TCP/IP負責將字節流可靠地在網絡節點間傳遞;而應用基礎設施則保證服務間的請求在安全、可靠、可被管控的傳遞。這也對應了前面Istio作為Service Mesh一種實現的定位。
Istio 關鍵能力
Istio官方介紹自己的關鍵能力如上所示,我把它分為兩部分:一部分是功能,另有一部分提供的擴展能力。
功能上包括流量管理、策略執行、安全和可觀察性。也正好應對了首頁的連接、保護、控制和觀測四大功能。
流量管理:是Istio中最常用的功能。可以通過配置規則和訪問路由,來控制服務間的流量和API調用。從而實現負載均衡、熔斷、故障註入、重試、重定向等服務治理功能,並且可以通過配置流量規則來對將流量切分到不同版本上從而實現灰度發布的流程。
策略執行:指Istio支持支持訪問控制、速率限制、配額管理的能力。這些能力都是通過可動態插入的策略控制後端實現。
安全:Istio提供的底層的安全通道、管理服務通信的認證、授權,使得開發任務只用關註業務代碼中的安全相關即可。
可觀察性:較之其他系統和平臺,Istio比較明顯的一個特點是服務運行的監控數據都可以動態獲取和輸出,提供了強大的調用鏈、監控和調用日誌收集輸出的能力。配合可視化工具,運維人員可以方便的看到系統的運行狀況,並發現問題進而解決問題。我們這次分享的主題調用鏈也正是Isito可觀察性的一個核心能力。
後面分析可以看到以上四個特性從管理面看,正好對應Istio的三個重要組件。
擴展性:主要是指Istio從系統設計上對運行平臺、交互的相關系統都盡可能的解耦,可擴展。這裏列出的特性:
平臺支持:指Istio可以部署在各種環境上,支持Kubernetes、Consul等上部署的服務,在之前版本上還支持註冊到Eureka上的Service,新版本對Eureka的支持被拿掉了;
集成和定制:指的Istio可以動態的對接各種如訪問控制、配額管理等策略執行的後端和日誌監控等客觀性的後端。支持用戶根據需要按照模板開發自己的後端方便的集成進來。
其實這兩個擴展性的能力正好也對應了Istio的兩個核心組件Pilot和Mixer,後面Isito架構時一起看下。
Istio 總體架構
以上是Isito的總體架構。上面是數據面,下半部分是控制面。
數據面Envoy是一個C++寫的輕量代理,可以看到所有流入流出服務的流量都經過Proxy轉發和處理,前面Istio中列出的所有的治理邏輯都是在Envoy上執行,正是攔截到服務訪問間的流量才能進行各種治理;另外可以看到Sidecar都連到了一個統一的控制面。
Istio其實專指控制面的幾個服務組件:
Pilot:Pilot幹兩個事情,一個是配置,就是前面功能介紹的智能路由和流量管理功能都是通過Pilot進行配置,並下發到Sidecar上去執行;另外一個是服務發現,可以對接不同的服務發現平臺維護服務名和實例地址的關系並動態提供給Sidecar在服務請求時使用。Pilot的詳細功能和機制見後面組件介紹。
Mixer:Mixer是Istio中比較特殊,當前甚至有點爭議的組件。前面Isito核心功能中介紹的遙測和策略執行兩個大特性均是Mixer提供。而Istio官方強調的集成和定制也是Mixer提供。即可以動態的配置和開發策略執行與遙測的後端,來實現對應的功能。Mixer的詳細功能和機制見後面組件介紹。
Citadel:主要對應Istio核心功能中的安全部分。配合Pilot和Mixer實現秘鑰和證書的管理、管理授權和審計,保證客戶端和服務端的安全通信,通過內置的身份和憑證提供服務間的身份驗證,並進而該通基於服務表示的策略執行。
Isito主要組件Pilot
如Istio架構中簡介,Pilot實現服務發現和配置管理的功能。
作為服務發現,Pilot中定義了一個抽象的服務模型,包括服務、服務實例、版本等。並且只定義的服務發現的接口,並未實現服務發現的功能,而是通過Adapter機制以一種可擴展的方式來集成各種不同的服務發現,並轉換成Istio通用的抽象模型。 如在Kubernetes中,Pilot中的Kubernetes適配器通過Kube-APIServer服務器得到Kubernetes中對應的資源信息。而對於像Eureka這種服務註冊表,則是使用一個Eureka的HTTP Client去訪問Eureka的名字服務的集群,獲取服務實例的列表。不管哪種方式最終都轉換成Pilot的標準服務發現定義,進而通過標準接口提供給Sidecar使用。
而配置管理,則是定義並維護各種的流量規則,來實現負載均衡、熔斷、故障註入、流量拆分等功能。並轉換成Envoy中標準格式推送給Envoy,從而實現治理功能。所有的這些功能用戶均不用修改代碼接口完成。詳細的配置方式可以參照Istio Traffic Routing中的規則定義。重點關註:VirtualService、 DestinationRule、 Gateway等規則定義。如可以使用流量規則來配置各種灰度發布,也可以通過註入一個故障來測試故障場景;可以配置熔斷來進行故障恢復;並且可以對HTTP請求根據我們的需要進行重定向、重寫,重試等操作。
Istio主要組件Mixer
Mixer是Isito特有的一個組件。主要做兩個功能Check和Report,分別對應Istio官方宣傳的兩個重大特性策略執行和遙測功能。邏輯上理解每次服務間的請求都會通過proxy連接Mixer來進行處理,由Mixer來將請求派發到對應的後端上處理。通過擴展不同的後端來增強Mixer的能力。如可以做訪問控制、配額等這樣的控制,也可以對接不同的監控後端來做監控數據的收集,進而提供網格運行的可觀察性能力。
Mixer通過使用通用插件模型實現的對接不同後端,避免了proxy為了完成不同的功能而去對接各種不同的後端。每個插件都被稱為Adapter。對於每個請求Sidecar會從每一次請求中收集相關信息,如請求的路徑,時間,源IP,目地服務,tracing頭,日誌等,並請這些屬性上報給Mixer。Mixer和後端服務之間是通過適配器進行連接的,Mixer將Sidecar上報的內容通過適配器發送給後端服務。可以在不停止應用服務的情況下動態切換後臺服務。
除了可以通過adapter機制接入不同的後端,mixer還支持根據需要定義收集的metric,和對metric的處理方式,如樣例所示,可以自定義監控指標。
後面我們會看到Istio中調用鏈的數據也可以通過Mixer來收集。
Istio和Kubernetes的天然結合
盡管Isito強調自己的可擴展性的重要一點就是可以適配各種不同的平臺,但實際場景上,甚至看Istio當前代碼、設計可以發現其所有重要的能力都是基於Kubernetes展開的。Istio與Kubernetes結合之緊密,甚至有描述說看上去是一個團隊開發的。即Istio就是基於Kubernetes之上,對Kubernetes能力的補齊。
從功能場景看,Kubernetes提供了部署、升級和有限的運行流量管理能力;利用Service的機制來做服務註冊和發現,轉發,通過Kubeproxy有一定的轉發和負載均衡能力。但是往上的如熔斷、限流降級、調用鏈等治理能力就沒有了。前面的功能介紹可以發現Istio很好的補齊了Kubernetes在服務治理上的這部分能力。即Kubernetes提供了基礎服務運行能力,而Istio基於其上提供服務治理能力,對Kubernetes服務的治理能力。
除了功能互補外,從形態上看Istio也是基於Kubernetes構建的。包括: Sicecar 運行在Kubernetes Pod裏,作為一個Proxy和業務容器部署在一起,部署過程對用戶透明。Mesh中要求業務程序的運行感知不到Sidecar的存在,基於Kubernetes的pod的設計這部分做的更徹底,對用戶更透明,通過Isito的自動註入用戶甚至感知不到部署Sidecar的這個過程,和部署一個一般的Deployment沒有任何差別。試想如果是通過VM上部署一個Agent,不會有這麽方便。
另外Istio的服務發現也是非常完美基於Kubernetes的域名訪問機制構建。Isito中的服務就是Kubernetes的服務,避免了之前使用獨立的微服務框架在Kubernetes上運行時兩套名字服務的尬尷和困惑。機制上Pilot通過在kubernetes裏面註冊一個controller來監聽事件,從而獲取Service和Kubernetes的Endpoint以及Pod的關系,並將這些映射關系轉換成為Istio的統一抽象模型下發到Envoy進行轉發。
Istio所有的我們熟悉的路由規則、控制策略都是通過Kubernetes CRD表達,不需要一個單獨的APIserver和後端的配置管理。所以Istio APIServer就是Kubernetes的KubeAPIServer,數據也當然的存在了對應Kubernetes的ETCD中。
就連Istio的命令行工具Istioctl都是類似Kubectl風格的功能,提供基於命令行的配置功能。
Istio調用鏈埋點原理剖析—是否真的“零修改”分享實錄(上)