Istio技術與實踐05:如何用istio實現流量管理

華為雲發表於2018-09-04

Istio是什麼?

Istio 1.0版本於8月1號凌晨準點釋出,核心特性已支援上生產環境,各大微信公眾號、部落格紛紛發文轉載。那麼 Istio 到底是什麼?能解決問題什麼?

  • Istio 是 Google 繼 Kubernetes 之後的又一開源力作,主要參與的公司包括 Google,IBM,Lyft 等,它提供了完整的非侵入式的微服務治理解決方案,解決微服務的管理、網路連線以及安全管理等應用網路治理問題
  • 它無需修改任何程式碼就能夠實現微服務的負載均衡,服務與服務之間的認證授權以及流量監控和治理。從整個基礎設施角度上看,可以將它理解為 PaaS 平臺上的一個面向微服務管理平臺的補充。

Istio技術與實踐05:如何用istio實現流量管理

Istio與Kubernetes

Kubernetes 提供了部署、升級和有限的執行流量管理能力,利用 service 的機制來做服務註冊和發現,轉發,通過 kubeproxy 有一定的轉發和負載均衡能力。但並不具備上層如熔斷、限流降級、呼叫鏈治理等能力。 Istio 則很好的補齊了 k8s 在微服務治理上的這部分能力,同時是基於 k8s 構建的,但不是像 SpringCloud Netflix 等完全重新做一套。Istio 是谷歌微服務治理上的非常關鍵的一環。

Istio技術與實踐05:如何用istio實現流量管理

Istio流量管理能力介紹

Istio,用於連線、保護、控制和觀測服務。今天,我們就來談談 Istio 第一主打功能——連線服務。那麼,便引出3個問題:

  • Istio 如何實現服務之間的連線?
  • 連線後具備哪些流量管理能力?
  • 如何告訴 Istio 發揮這些能力?

1、 Istio 如何實現服務的連線?

Istio技術與實踐05:如何用istio實現流量管理
如上圖所示的 Istio 架構圖,讓我們關注控制面的 Pilot,它是 Istio 實現流量管理的核心元件。 而在資料面,每個 Service,都會被注入1個 Proxy。Istio 通過 Pilot 下發配置資訊給資料面每1個 Service 的 Proxy,從而通過這些 Proxy,間接地控制每1個Service之間以及和外部的連線。Proxy 通常採用另一個知名的開源專案 Envoy 來實現。 1個 Pilot 和(N+N)個( Service + Proxy )組合,便形成了 Service Mesh,即服務網格。有了這一套服務網格系統,對服務之間的流量進行管理,便不在話下。

2、連線後具備哪些流量管理能力?

從服務間的流量管理角度而言,Istio可以實現這4項功能:請求路由、服務發現和負載均衡、故障處理和故障注入。

A.請求路由

Istio技術與實踐05:如何用istio實現流量管理
如上圖所示,Istio 引入了服務版本的概念,可以通過(Current Version,Canary Version )2個版本對服務進行進一步的細分。基於這種劃分,通過 Pilot,可以下發配置到 Service A 的 Proxy,使得其95%的流量路由至 Service B的 Current 版本,5%的流量路由至 Service B 的 Canary 版本。當然也可以選擇雨露均沾,各分50%流量,或者霸道總裁,讓 Canary 版本佔有100%的流量。

Istio技術與實踐05:如何用istio實現流量管理
如上圖所示,除了按照百分比在不同版本之間分發流量,你還可以按照請求內容,將請求路由至不同的版本。例如,你可以釋出一個 Canary 版本,只讓用著 Macbook 筆記本,且安裝了 windows 作業系統,還使用著360瀏覽器的使用者能夠訪問到。 這一切改變,都只需要你改動一個叫 VirtualService 的配置檔案(詳見下章),眨個眼的功夫,Istio 就已經通過 Pilot 幫你把新的配置下發下去了。

B.服務發現和負載均衡

Istio技術與實踐05:如何用istio實現流量管理
如上圖所示,服務網格存在3個生命週期的動態迴圈:服務註冊、服務發現、負載均衡。

通常 kubernetes,mesos 等容器管理平臺已經提供了服務登錄檔,以跟蹤服務的負載例項,所以 Pilot 能輕而易舉地獲知服務網格內的所有服務註冊資訊,並將這些資訊告知所有服務裡的 Proxy,Proxy 根據這些資訊執行服務發現,並相應地動態更新其負載均衡池。一個服務通常有多個負載例項,Service A 請求 ServiceB 時,可以配置不同的負載均衡模式:輪詢、隨機和帶權重的最少請求。假設此時Service B的某個負載例項出現故障,因為 Service A 中的 Proxy 會定期地執行服務發現,從而能及時將故障例項從其負載均衡池裡排出。

C.故障處理

Envoy 提供了一套開箱即用,可選的故障處理功能,對應用中的服務大有裨益。這些功能包括:

  • 超時
  • 具備超時預算,並進行有限重試,重試之間的時長可抖動
  • 併發連線數和上游服務請求數限制
  • 對負載均衡池中的每個成員進行主動(定期)執行健康檢查
  • 細粒度熔斷器(被動健康檢查)- 適用於負載均衡池中的每個例項

以 Service A 請求呼叫 Service B 為例。

對於功能1。若 Service B 明確地知道10s以後的超時,必定會帶來失敗,那將超時時長縮短,使得 Service A 可以更快得知結果並作出應對,不失為一個明智之舉。

對於功能2。對超載的 Service B 來說,重試之間的抖動極大的降低了重試造成的影響,而超時預算確保 Service A在可預測的時間範圍內獲得響應(成功/失敗)。

對於功能3。限制 Service A 或其他服務對 Service B的連線數和請求數,可以使得 Service B免於遭遇 DDOS 攻擊,或承受過重的流量負擔而崩潰。

對於功能4和5。主動和被動健康檢查的組合最大限度地減少了在負載平衡池中訪問不健康例項的機會。當與平臺級健康檢查(例如由 Kubernetes 或 Mesos 支援的檢查)相結合時,應用程式可以確保將不健康的負載例項快速地從服務網格中去除,從而最小化請求失敗和延遲產生影響。

總之,這些功能使得服務網格能夠耐受故障節點,並防止本地故障導致的其他節點的穩定性下降。

D.故障注入

雖然 Proxy 為在 Istio 上執行的服務提供了上節所言的大量故障處理機制,但測試整個服務網格所組成應用的端到端的故障恢復能力依然是必須的。錯誤配置的故障恢復策略(例如,跨服務呼叫的不相容/限制性超時)可能導致應用程式中的關鍵服務持續不可用,從而破壞使用者體驗。

Istio 能在不殺死負載例項的情況下,將協議特定的故障注入到網路中,在 TCP 層製造資料包的延遲或損壞。我們的理由是,無論網路級別的故障如何,應用層觀察到的故障都是一樣的,並且可以在應用層注入更有意義的故障(例如,HTTP 經典的4xx和5xx錯誤程式碼),以檢驗和改善應用的韌性。

運維人員可以為符合特定條件的請求配置故障,還可以進一步限制遭受故障的請求的百分比。可以注入兩種型別的故障:延遲和中斷。延遲是計時故障,模擬網路延遲上升或上游服務超載的情況。中斷是模擬上游服務的崩潰故障。中斷通常以 HTTP 錯誤程式碼或 TCP 連線失敗的形式表現。

依舊以 Service A 請求呼叫 Service B 為例。

若給 Service B設定了10s的延時或503中斷,則 Service A將至少10s後才能得到請求的響應或請求的響應為503錯誤,通過多種場景覆蓋測試,可以得到 Service A 面對這些場景時的綜合表現情況,從而做出針對性的改良,增加其韌性。

3、如何告訴Istio發揮這些能力?

Istio有4個配置檔案,幫我們全方位地定製以上所有流量管理需求: VirtualService, DestinationRule, ServiceEntry和 Gateway:

  • 通過配置 VirtualService,可以實現請求路由的功能;
  • 通過配置 DestinationRule,可以實現服務發現和負載均衡、故障處理和故障注入的功能;
  • 通過配置 ServiceEntry,讓服務網格內的服務,可以看到外面的世界;
  • 通過配置 Gateway,讓服務網格的服務,可以被全世界看到;

有了以上4大法寶,我們對服務網格進行流量管理的所有需求,都可以被滿足了。

限於篇幅,讓我們舉3個簡單的栗子:

假設我們的服務網格存在1個服務 explorer,只有1個v1版本;存在另1個服務 helloworld,有v1,v2兩個版本。

①若要使得 explorer 發起的所有請求,以75%的概率走向 helloworld 的v1版本,以25%走向v2版本,只要配置如下兩個檔案 VirtualService 和 DestinationRule,便可實現:

apiVersion:networking.Istio.io/v1alpha3
kind:VirtualService
metadata:
  name:helloworld
spec:
  hosts:
    - helloworld
  http:
  - route:
    - destination:
        host:helloworld
        subset:v1
      weight:75
    - destination:
        host: helloworld
        subset: v2
     weight: 25

apiVersion:networking.Istio.io/v1alpha3
kind:DestinationRule
metadata:
  name: helloworld
spec:
  host: helloworld
  subsets:
  - name:v1
    labels:
      version: v1
  - name: v2
   labels:
      version: v2
複製程式碼

②如果 helloworld 內部需要通過訪問www.google.com 來獲取一些資訊,才能告訴 explorer 這個世界是怎麼樣的,需要配置如下2個檔案 ServiceEntry 和 DestinationRule:

apiVersion:networking.Istio.io/v1alpha3
kind:ServiceEntry
metadata:
  name: googleapis
spec:
  hosts:
  - "*.google.com"
  ports:
  - number:443
    name:https
    protocol:http
 
apiVersion:networking.Istio.io/v1alpha3
kind:DestinationRule
metadata:
 name: googleapis
spec:
  host: "*.google.com"
複製程式碼

③如果 helloworld 需要被服務網格外,而不僅僅是 explorer 服務訪問到,則需要配置如下2個檔案 Gateway 和 VirtualService:

apiVersion:networking.Istio.io/v1alpha3
kind:Gateway
metadata:
 name: helloworld-gateway
spec:
   selector:
     Istio:ingressgateway
 servers:
 - port:
     number: 80
     name: http
     protocol: HTTP
   hosts:
   - 'helloworld.com'
  
apiVersion:networking.Istio.io/v1alpha3
kind:VirtualService
metadata:
name: bookinfo
spec:
hosts:
   - 'helloworld.com'
 gateways:
 - helloworld-gateway
 http:
 - route:
  - destination:
       host: helloworld
       port:
         number: 9080
複製程式碼

至此,我們做一個簡單的總結:Istio 提供的 Pilot 和 Proxy,將成百上千個服務組成了一個服務網格。基於此,我們可以實現請求路由、服務發現和負載均衡、故障處理以及故障注入等流量管理能力,這一切,我們只需要通過對 VirtualService, DestinationRule, ServiceEntry 和 Gateway 這4個資源做簡單的配置,即可實現。

相關文章