歡迎光臨
每天分享高質量文章

談談微服務架構中的基礎設施:Service Mesh與Istio

微服務架構的演進

作為一種架構樣式,微服務將複雜系統切分為數十乃至上百個小服務,每個服務負責實現一個獨立的業務邏輯。這些小服務易於被小型的軟體工程師團隊所理解和修改,並帶來了語言和框架選擇靈活性,縮短應用開發上線時間,可根據不同的工作負載和資源要求對服務進行獨立縮擴容等優勢。
另一方面,當應用被拆分為多個微服務行程後,行程內的方法呼叫變成了了行程間的遠端呼叫。引入了對大量服務的連線、管理和監控的複雜性。 

該變化帶來了分散式系統的一系列問題,例如:
  • 如何找到服務的提供方?

  • 如何保證遠端方法呼叫的可靠性?

  • 如何保證服務呼叫的安全性?

  • 如何降低服務呼叫的延遲?

  • 如何進行端到端的除錯?

另外生產部署中的微服務實體也增加了運維的難度,例如:
  • 如何收集大量微服務的效能指標已進行分析?

  • 如何在不影響上線業務的情況下對微服務進行升級?

  • 如何測試一個微服務叢集部署的容錯和穩定性?

這些問題涉及到成百上千個服務的通訊、管理、部署、版本、安全、故障轉移、策略執行、遙測和監控等,要解決這些微服務架構引入的問題並非易事。
讓我們來回顧一下微服務架構的發展過程。在出現服務網格之前,我們最開始在微服務應用程式內理服務之間的通訊邏輯,包括服務發現、熔斷、重試、超時、加密、限流等邏輯。

在一個分散式系統中,這部分邏輯比較複雜,為了為微服務應用提供一個穩定、可靠的基礎設施層,避免大家重覆造輪子,並減少犯錯的可能,一般會透過對這部分負責服務通訊的邏輯進行抽象和歸納,形成一個程式碼庫供各個微服務應用程式使用,如下圖所示:

公共的程式碼庫減少了應用程式的開發和維護工作量,降低了由應用開發人員單獨實現微服務通訊邏輯出現錯誤的機率,但還是存在下述問題:
  • 微服務通訊邏輯對應用開發人員並不透明,應用開發人員需要理解並正確使用程式碼庫,不能將其全部精力聚焦於業務邏輯。

  • 需要針對不同的語言/框架開發不同的程式碼庫,反過來會影響微服務應用開發語言 和框架的選擇,影響技術選擇的靈活性。

  • 隨著時間的變化,程式碼庫會存在不同的版本,不同版本程式碼庫的相容性和大量執行環境中微服務的升級將成為一個難題。

可以將微服務之間的通訊基礎設施層和TCP/IP協議棧進行類比。TCP/IP協議棧為作業系統中的所有應用提供基礎通訊服務,但TCP/IP協議棧和應用程式之間並沒有緊密的耦合關係,應用只需要使用TCP/IP協議提供的底層通訊功能,並不關心TCP/IP協議的實現,如IP如何進行路由,TCP如何建立連結等。
同樣地,微服務應用也不應該需要關註服務發現,Load balancing、Retries、Circuit Breaker等微服務之間通訊的底層細節。如果將為微服務提供通訊服務的這部分邏輯從應用程式行程中抽取出來,作為一個單獨的行程進行部署,並將其作為服務間的通訊代理,可以得到如下圖所示的架構:

因為通訊代理行程伴隨應用行程一起部署,因此形象地把這種部署方式稱為“Sidecar”/邊車(即三輪摩托的挎鬥)。
應用間的所有流量都需要經過代理,由於代理以Sidecar方式和應用部署在同一臺主機上,應用和代理之間的通訊可以被認為是可靠的。由代理來負責找到目的服務並負責通訊的可靠性和安全等問題。
當服務大量部署時,隨著服務部署的Sidecar代理之間的連線形成了一個如下圖所示的網格,該網格成為了微服務的通訊基礎設施層,承載了微服務之間的所有流量,被稱之為Service Mesh(服務網格)。 

服務網格是一個基礎設施層,用於處理服務間通訊。雲原生應用有著複雜的服務拓撲,服務網格保證請求可以在這些拓撲中可靠地穿梭。在實際應用當中,服務網格通常是由一系列輕量級的網路代理組成的,它們與應用程式部署在一起,但應用程式不需要知道它們的存在。
William Morgan ,WHAT’S A SERVICE MESH? AND WHY DO I NEED ONE?
服務網格中有數量眾多的Sidecar代理,如果對每個代理分別進行設定,工作量將非常巨大。為了更方便地對服務網格中的代理進行統一集中控制,在服務網格上增加了控制面元件。

這裡我們可以類比SDN的概念,控制面就類似於SDN網管中的控制器,負責路由策略的指定和路由規則下發;資料面類似於SDN網路中交換機,負責資料包的轉發。
由於微服務的所有通訊都由服務網格基礎設施層提供,透過控制面板和資料面板的配合,可以對這些通訊進行監控、託管和控制,以實現微服務灰度釋出,呼叫分散式追蹤,故障註入模擬測試,動態路由規則,微服務閉環控制等管控功能。


Istio服務網格

Istio是一個Service Mesh開源專案,是Google繼Kubernetes之後的又一力作,主要參與的公司包括Google,IBM和Lyft。
憑藉Kubernetes良好的架構設計及其強大的擴充套件性,Google圍繞Kubernetes打造一個生態系統。Kubernetes用於微服務的編排(編排是英文Orchestration的直譯,用大白話說就是描述一組微服務之間的關聯關係,並負責微服務的部署、終止、升級、縮擴容等)。其向下用CNI(容器網路介面),CRI(容器執行時介面)標準介面可以對接不同的網路和容器執行時實現,提供微服務執行的基礎設施。向上則用Istio提供了微服務治理功能。
由下圖可見,Istio補充了Kubernetes生態圈的重要一環,是Google的微服務版圖裡一個裡程碑式的擴張。 

Google借Istio的力量推動微服務治理的事實標準,對Google自身的產品Google Cloud有極其重大的意義。其他的雲服務廠商,如Redhat、Pivotal、Nginx、Buoyant等看到大勢所趨,也紛紛跟進,宣佈自身產品和Istio進行整合,以避免自己被落下,丟失其中的市場機會。
可以預見不久的將來,對於雲原生應用而言,採用Kubernetes進行服務部署和叢集管理,採用Istio處理服務通訊和治理,將成為微服務應用的標準配置。
Istio服務包括網格由資料面和控制面兩部分。
  • 資料面由一組智慧代理(Envoy)組成,代理部署為邊車,調解和控制微服務之間所有的網路通訊。

  • 控制面負責管理和配置代理來路由流量,以及在執行時執行策略。

Istio控制面
Istio控制面板包括3個元件:Pilot、Mixer和Istio-Auth。
Pilot
Pilot維護了網格中的服務的標準模型,這個標準模型是獨立於各種底層平臺的。Pilot透過配接器和各底層平臺對接,以填充此標準模型。
例如Pilot中的Kubernetes配接器透過Kubernetes API伺服器得到Kubernetes中Pod註冊資訊的更改,入口資源以及儲存流量管理規則等資訊,然後將該資料被翻譯為標準模型提供給Pilot使用。透過配接器樣式,Pilot還可以從Mesos、Cloud Foundry、Consul中獲取服務資訊,也可以開發配接器將其他提供服務發現的元件整合到Pilot中。
除此以外,Pilo還定義了一套和資料面通訊的標準API,API提供的介面內容包括服務發現 、負載均衡池和路由表的動態更新。透過該標準API將控制面和資料面進行瞭解耦,簡化了設計並提升了跨平臺的可移植性。基於該標準API已經實現了多種Sidecar代理和Istio的整合,除Istio目前整合的Envoy外,還可以和Linkerd、Nginmesh等第三方通訊代理進行整合,也可以基於該API自己編寫Sidecar實現。
Pilot還定義了一套DSL(Domain Specific Language)語言,DSL語言提供了面向業務的高層抽象,可以被運維人員理解和使用。運維人員使用該DSL定義流量規則並下發到Pilot,這些規則被Pilot翻譯成資料面的配置,再透過標準API分發到Envoy實體,可以在執行期對微服務的流量進行控制和調整。 

Mixer
在微服務應用中,通常需要部署一些基礎的後端公共服務以用於支撐業務功能。這些基礎設施包括策略類如訪問控制,配額管理;以及遙測報告如APM、日誌等。微服務應用和這些後端支撐系統之間一般是直接整合的,這導致了應用和基礎設定之間的緊密耦合,如果因為運維原因需要對基礎設定進行升級或者改動,則需要修改各個微服務的應用程式碼,反之亦然。
為瞭解決該問題,Mixer在應用程式程式碼和基礎架構後端之間引入了一個通用中間層。該中間層解耦了應用和後端基礎設施,應用程式程式碼不再將應用程式程式碼與特定後端整合在一起,而是與Mixer進行相當簡單的整合,然後Mixer負責與後端系統連線。
Mixer主要提供了三個核心功能:
  • 前提條件檢查。允許服務在響應來自服務消費者的傳入請求之前驗證一些前提條件。前提條件可以包括服務使用者是否被正確認證,是否在服務的白名單上,是否透過ACL檢查等等。

  • 配額管理。 使服務能夠在分配和釋放多個維度上的配額,配額這一簡單的資源管理工具可以在服務消費者對有限資源發生爭用時,提供相對公平的(競爭手段)。Rate Limiting就是配額的一個例子。

  • 遙測報告。使服務能夠上報日誌和監控。在未來,它還將啟用針對服務運營商以及服務消費者的跟蹤和計費流。

Mixer的架構如圖所示:

首先,Sidecar會從每一次請求中收集相關資訊,如請求的路徑,時間,源IP,目地服務,tracing頭,日誌等,並請這些屬性上報給Mixer。Mixer和後端服務之間是透過配接器進行連線的,Mixer將Sidecar上報的內容透過配接器傳送給後端服務。
由於Sidecar只和Mixer進行對接,和後端服務之間並沒有耦合,因此使用Mixer配接器機制可以接入不同的後端服務,而不需要修改應用的程式碼,例如透過不同的Mixer配接器,可以把Metrics收集到Prometheus或者InfluxDB,甚至可以在不停止應用服務的情況下動態切換後臺服務。
其次,Sidecar在進行每次請求處理時會透過Mixer進行策略判斷,並根據Mixer傳回的結果決定是否繼續處理該次呼叫。透過該方式,Mixer將策略決策移出應用層,使運維人員可以在執行期對策略進行配置,動態控制應用的行為,提高了策略控制的靈活性。例如可以配置每個微服務應用的訪問白名單,不同客戶端的Rate limiting,等等。
邏輯上微服務之間的每一次請求呼叫都會經過兩次Mixer的處理:呼叫前進行策略判斷,呼叫後進行遙測資料收集。Istio採用了一些機制來避免Mixer的處理影響Envoy的轉發效率。
從上圖可以看到,Istio在Envoy中增加了一個Mixer Filter,該Filter和控制面的Mixer元件進行通訊,完成策略控制和遙測資料收集功能。Mixer Filter中儲存有策略判斷所需的資料快取,因此大部分策略判斷在Envoy中就處理了,不需要傳送請求到Mixer。另外Envoy收集到的遙測資料會先儲存在Envoy的快取中,每隔一段時間再透過批次的方式上報到Mixer。
Auth
Istio支援雙向SSL認證(Mutual SSL Authentication)和基於角色的訪問控制(RBAC),以提供端到端的安全解決方案。
認證
Istio提供了一個內部的CA(證書機構),該CA為每個服務頒發證書,提供服務間訪問的雙向SSL身份認證,併進行通訊加密,其架構如下圖所示: 

其工作機制如下:
部署時:
  • CA監聽Kubernetes API Server,為叢集中的每一個Service Account建立一對金鑰和證書,併傳送給Kubernetes API Server。註意這裡不是為每個服務生成一個證書,而是為每個Service Account生成一個證書。Service Account和Kubernetes中部署的服務可以是一對多的關係。Service Account被儲存在證書的SAN(Subject Alternative Name)欄位中。

  • 當Pod建立時,Kubernetes根據該Pod關聯的Service Account將金鑰和證書以Kubernetes Secrets資源的方式載入為Pod的Volume,以供Envoy使用。

  • Pilot生成資料面的配置,包括Envoy需使用的金鑰和證書資訊,以及哪個Service Account可以允許執行哪些服務,下發到Envoy。

備註:如果是虛機環境,則採用一個Node Agent生成金鑰,向Istio CA申請證書,然後將證書傳遞給Envoy。
執行時:
  • 服務客戶端的出站請求被Envoy接管。

  • 客戶端的Envoy和服務端的Envoy開始雙向SSL握手。在握手階段,客戶端Envoy會驗證服務端Envoy證書中的Service Account有沒有許可權執行該請求的服務,如沒有許可權,則認為服務端不可信,不能建立連結。

  • 當加密TSL連結建立好後,請求資料被髮送到服務端的Envoy,然後被Envoy透過一個本地的TCP連結傳送到服務中。

鑒權
Istio“基於角色的訪問控制”(RBAC)提供了名稱空間、服務、方法三個不同大小粒度的服務訪問許可權控制。其架構如下圖所示: 

管理人員可以定製訪問控制的安全策略,這些安全策略儲存在Istio Config Store中。 Istio RBAC Engine從Config Store中獲取安全策略,根據安全策略對客戶端發起的請求進行判斷,並傳回鑒權結果(允許或者禁止)。
Istio RBAC Engine目前被實現為一個Mixer Adapter,因此其可以從Mixer傳遞過來的背景關係中獲取到訪問請求者的身份(Subject)和操作請求(Action),並透過Mixer對訪問請求進行策略控制,允許或者禁止某一次請求。
Istio Policy中包含兩個基本概念:
  • ServiceRole,定義一個角色,併為該角色指定對網格中服務的訪問許可權。指定角色訪問許可權時可以在名稱空間,服務,方法的不同粒度進行設定。

  • ServiceRoleBinding,將角色系結到一個Subject,可以是一個使用者,一組使用者或者一個服務。

Istio資料面
Istio資料面以“邊車”(Sidecar)的方式和微服務一起部署,為微服務提供安全、快速、可靠的服務間通訊。由於Istio的控制面和資料面以標準介面進行互動,因此資料可以有多種實現,Istio預設使用了Envoy代理的擴充套件版本。
Envoy是以C++開發的高效能代理,用於調解服務網格中所有服務的所有入站和出站流量。Envoy的許多內建功能被Istio發揚光大,例如動態服務發現、負載均衡、TLS加密、HTTP/2 & gRPC代理、熔斷器、路由規則、故障註入和遙測等。
Istio資料面支援的特性如下:
Outbound特性 Inbound特性
Service authentication(服務認證) Service authentication(服務認證)
Load Balancing(負載均衡) Authorization(鑒權)
Retry and circuit breaker(重試和斷路器) Rate limits(請求限流)
Fine-grained routing(細粒度的路由) Load shedding(負載控制)
Telemetry(遙測) Telemetry(遙測)
Request Tracing(分散式追蹤) Request Tracing(分散式追蹤)
Fault Injection(故障註入) Fault Injection(故障註入)
備註:Outbound特性是指服務請求側的Sidecar提供的功能特性,而Inbound特性是指服務提供側Sidecar提供的功能特性。一些特性如遙測和分散式跟蹤需要兩側的Sidecar都提供支援;而另一些特性則只需要在一側提供,例如鑒權只需要在服務提供側提供,重試只需要在請求側提供。
典型應用場景
Istio服務管控包括下列的典型應用場景:
分散式呼叫追蹤
在微服務架構中,業務的呼叫鏈非常複雜,一個來自使用者的請求可能涉及到幾十個服務的協同處理。因此需要一個跟蹤系統來記錄和分析同一次請求在整個呼叫鏈上的相關事件,從而幫助研發和運維人員分析系統瓶頸,快速定位異常和最佳化呼叫鏈路。
Istio透過在Envoy代理上收集呼叫相關資料,實現了對應用無侵入的分散式呼叫跟蹤分析。 Istio實現分散式呼叫追蹤的原理如下圖所示:

Envoy收集一個端到端呼叫中的各個分段的資料,並將這些呼叫追蹤資訊傳送給Mixer,Mixer Adapter將追蹤資訊傳送給相應的服務後端進行處理。整個呼叫追蹤資訊的生成流程不需要應用程式介入,因此不需要將分散式跟蹤相關程式碼註入到應用程式中。
註意:應用仍需要在進行出口呼叫時將收到的入口請求中tracing相關的essay-header轉發出去,傳遞給呼叫鏈中下一個邊車進行處理。
度量收集
Istio 實現度量收集的原理如下圖所示:

Envoy收集指標相關的原始資料,如請求的服務、HTTP狀態碼、呼叫時延等,這些收集到的指標資料被送到Mixer,透過Mixer Adapters將指標資訊轉換後傳送到後端的監控系統中。由於Mixer使用了外掛機制,後端監控系統可以根據需要在執行期進行動態切換。
灰度釋出
當應用上線以後,運維面臨的一大挑戰是如何能夠在不影響已上線業務的情況下進行升級。無論進行了多麼完善的測試,都無法保證線下測試時發現所有潛在故障。在無法百分百避免版本升級故障的情況下,需要透過一種方式進行可控的版本釋出,把故障影響控制在可以接受的範圍內,並可以快速回退。
可以透過灰度釋出(又名金絲雀釋出)來實現業務從老版本到新版本的平滑過渡,並避免升級過程中出現的問題對使用者造成的影響。
Istio透過高度的抽象和良好的設計採用一致的方式實現了灰度釋出。在釋出新版本後,運維人員可以透過定製路由規則將特定的流量(如具有指定特徵的測試使用者)匯入新版本服務中以進行測試。透過漸進受控地向新版本匯入生產流量,可以最小化升級中出現的故障對使用者的影響。
採用Istio進行灰度釋出的流程如下圖所示:
首先,透過部署新版本的服務,並將透過路由規則將金絲雀使用者的流量匯入到新版本服務中。

測試穩定後,使用路由規則將生產流量逐漸匯入到新版本系統中,如按5%、10%、50%、80%逐漸匯入。 

如果新版本工作正常,則最後將所有流量匯入到新版本服務中,並將老版本服務下線;如中間出現問題,則可以將流量重新導回老版本,在新版本中修複故障後採用該流程重新釋出。 

斷路器
在微服務架構中,存在著許許多多的服務單元,若一個服務出現故障,就會因依賴關係形成故障蔓延,最終導致整個系統的癱瘓,這樣的架構相較傳統架構就更加的不穩定。為瞭解決這樣的問題,因此產生了斷路器樣式。
斷路器樣式指,在某個服務發生故障時,斷路器的故障監控向呼叫放傳回一個及時的錯誤響應,而不是長時間的等待。這樣就不會使得呼叫執行緒因呼叫故障被長時間佔用,從而避免了故障在整個系統中的蔓延。
Istio實現斷路器的原理如下圖所示:

管理員透過destination policy設定斷路觸發條件,斷路時間等引數。例如設定服務B發生10次5XX錯誤後斷路15分鐘。則當服務B的某一實體滿足斷路條件後,就會被從LB池中移除15分鐘。在這段時間內,Envoy將不再把客戶端的請求轉發到該服務實體。
Istio的斷路器還支援配置最大連結數,最大待處理請求數,最大請求數,每連結最大請求數,重試次數等引數。當達到設定的最大請求數後,新發起的請求會被Envoy直接拒絕。 

故障註入
對於一個大型微服務應用而言,系統的健壯性非常重要。在微服務系統中存在大量的服務實體,當部分服務實體出現問題時,微服務應用需要具有較高的容錯性,透過重試、斷路、自愈等手段保證系統能夠繼續對外正常提供服務。因此在應用釋出到生產系統強需要對系統進行充分的健壯性測試。
對微服務應用進行健壯性測試的一個最大的困難是如何對系統故障進行模擬。在一個部署了成百上千微服務的測試環境中,如果想透過對應用,主機或者交換機進行設定來模擬微服務之間的通訊故障是非常困難的。
Istio透過服務網格承載了微服務之間的通訊流量,因此可以在網格中透過規則進行故障註入,模擬部分微服務出現故障的情況,對整個應用的健壯性進行測試。
故障註入的原理如下圖所示:

測試人員透過Pilot向Envoy註入了一個規則,為發向服務MS-B的請求加入了指定時間的延遲。當客戶端請求發向MSB-B時,Envoy會根據該規則為該請求加入時延,引起客戶的請求超時。透過設定規則註入故障的方式,測試人員可以很方便地模擬微服務之間的各種通訊故障,對微服務應用的健壯性進行較為完整的模擬測試。


總結

服務網格為微服務提供了一個對應用程式透明的安全、可靠的通訊基礎設施層。採用服務網格後,微服務應用開發人員可以專註於解決業務領域問題,將一些通用問題交給服務網格處理。採用服務網格後,避免了程式碼庫帶來的依賴,可以充分發揮微服務的異構優勢,開發團隊可以根據業務需求和開發人員能力自由選擇技術棧。
Istio具有良好的架構設計,提供了強大的二次開發擴充套件性和使用者定製能力。雖然Istio目前還處於beta階段,但已經獲得眾多知名公司和產品的支援,是一個非常具有前景的開源服務網格開源專案。
參考
  • Istio online documentation:https://istio.io/docs/

  • Pattern: Service Mesh:http://philcalcado.com/2017/08/03/pattern_service_mesh.html

  • Mixer and the SPOF Myth:https://istio.io/blog/2017/mixer-spof-myth.html

作者簡介:趙化冰是一名程式員及開源軟體愛好者,目前在NFV&SDN編排開源社群ONAP擔任MSB專案負責人,致力於高效能,高可用性微服務架構在編排領域的應用。部落格連結:http://zhaohuabing.com/

Kubernetes零基礎進階培訓

本次培訓內容包括:容器原理、Docker架構及工作原理、Docker網路與儲存方案、Harbor、Kubernetes架構、元件、核心機制、外掛、核心模組、Kubernetes網路與儲存、監控、日誌、二次開發以及實踐經驗等,點選瞭解具體培訓內容

4月20日正式上課,點選閱讀原文連結即可報名。
贊(0)

分享創造快樂