乾貨分享|使用 Istio 實現灰度釋出

2022-09-20 18:00:51

Kubernetes 作為基礎平臺,提供了強大的容器編排能力。但是在其上部署業務和服務治理上,仍然會面對一些複雜性和侷限性。在服務治理上,已經有許多成熟的 ServiceMesh 框架用於擴充其能力,如 Istio、Linkerd、Dapr 等。本文將主要介紹如何使用 Istio 擴充 Kubernetes 灰度釋出的能力。

而在部署上,則會利用開源專案 Rainbond 作為基礎平臺來進行實踐。Rainbond 是一個雲原生應用管理平臺,它使用以應用為中心的設計模式。基於這一設計模式抽象出了標準化的應用模型。從使用的體驗上不需要學習和編寫YAML,即可實現業務應用的全生命週期管理。因此使用它簡化業務的部署和管理。同時 Rainbond 支援 ServiceMesh 框架的替換,使我們可以按需選擇與業務最匹配的 ServiceMesh 框架進行服務治理。

Kubernetes 中如何實現灰度釋出

當你在 Kubernetes 叢集中部署業務時,可以利用 Kubernetes 原生提供的灰度釋出的方式去上線業務。這種方式是通過在舊版本和新版本的服務之間,定義一個差異化的 Label,根據不同版本之間的公共 Label 負載流量到後端 Pod,最終實現根據 Pod 的副本數控制流量的百分比。

如下圖所示:使用者定義了兩個 Deployment 物件,其中舊版本名為 frontend-stable,有3個副本。新版本為 frontend-canary,有1個副本。此時定義了一個 Service 物件,使用它們之間公共的 Label 進行選擇。這就使得使用者存取 frontend 這個 Service 時,能以 3:1 的比例同時存取到兩個版本。並且還可以通過調整副本數持續控制流量比例,最終達到完整上線。

Kubernetes 預設的實現方式在簡單的部署場景下很有效,但是在一些複雜場景中,仍然會有較大的侷限,如:

  1. 業務設定自動伸縮後,會直接影響灰度釋出的流量比例

  2. 低百分比的流量控制佔用資源高,如 1 % 的流量到達新版本,則至少需要 100 個副本

  3. 精確的流量分發控制,使存取到新版本中的使用者一直是同一批,而不是某個使用者存取時隨機切換

Istio 灰度釋出簡述

由於 Kubernetes 提供的灰度釋出方式的侷限性,在一些複雜場景下,我們就需要使用 Istio 來實現更精細的灰度釋出策略。在使用 Istio 進行灰度釋出時,我們需要了解兩個重要概念:

  1. Virtual services: 虛擬服務定義了請求到服務的路徑。可以包含一組路由規則,使匹配到對應規則的請求能到達指定目標。

  2. Destination rules: 目標規則可以管理到達該目標的流量,如對服務後端所對應的範例池進行分組,再結合 Virtual services 定義的路由規則,最終將流量轉發到正確的範例上。

如下圖所示,以 istio 官網提供的 Bookinfo 範例程式為例,給出了 virtual services 和 destination rules 的主要定義。其中 virtual services 主要分為兩塊,主機名和路由規則。主機名是使用者端向服務傳送請求時使用的一個或多個地址。當請求到達 virtual services 時,則會根據其定義的路由規則匹配。圖中就定義了郵箱以 gmail.com 結尾的使用者流量只會到達 v3 版本的範例上。而其他使用者則以 1:9 的比例分別存取到 v1 和 v2 版本的服務。這種方式實現了精確的流量分發控制。

當用戶流量來到 reviews.demo.svc.cluster.local 這個 Service 上時,可以看到 destination rules 的規則定義中根據 version 這個 label 定義了不同的範例集,實現了流量比例與副本數的解耦。不管 reviews-v1 有多少範例。始終只有 10% 的流量到達 destination rules 的 v1 子集中。這就解決了業務副本數與流量比例的衝突問題,也使得資源使用更加合理。

Istio 灰度釋出在 Rainbond 上的實踐

基於以上理解,我們接下來以 BookInfo 為例來體驗 Istio 的灰度釋出。

1. 準備工作:

在開始之前,我們需要提前安裝好所需要的環境。

  1. 安裝 Rainbond

參考 Rainbond 官方檔案 快速安裝,安裝完成後可以通過對接 Helm 商店一鍵安裝 Istio 以及相應元件。

  1. 安裝 Istio 以及 Kiali

登入到 Rainbond 控制檯後,先建立一個團隊,團隊英文名對應 Kubernetes 中的名稱空間,Istio 預設安裝的名稱空間為 istio-system ,因此團隊英文名填寫istio-system,名稱可以填寫為 istio專案。接下來對接 Helm 商店,通過 應用市場 -> 點選➕號 -> Helm 商店 對接。商店名稱隨意填寫,地址填寫 https://openchart.goodrain.com/goodrain/rainbond。商店對接完成後,我們即可點選安裝 istio、kiali 等應用。詳細可參考 Istio 安裝

2. 部署 BookInfo 應用

在部署 BookInfo 之前,我們需要在 Rainbond 中建立一個團隊和應用,並將應用的治理模式切換為 Istio 治理模式。在 Rainbond 中應用治理模式切換是指可以無侵入地變更應用下元件間通訊治理模式。

如下圖所示,一個完整應用會包含多個微服務模組,而 ServiceMesh 框架則是對所有業務容器注入 Proxy,根據注入Proxy的差異可以支援多種型別的 ServiceMesh 實現,比如:Istio、Linkerd、Dapr,應用可以按需開啟 ServiceMesh 能力,或更換實現框架。為了讓 BookInfo 這個應用使用到 Istio 的治理能力,所以需要切換到 Istio 治理模式

  1. 準備映象

BookInfo 這個應用程式由 6 個微服務組成,它們之間的依賴如下圖所示。其中 Productpage 這個服務提供了存取頁面,從 Details 這個服務中獲得書籍詳細資訊。從 Reviews 服務中獲得書籍評價。其中 Reviews-v2 和 Reviews-v3 會從 Ratings 這個服務中獲得書籍的評級資訊。這六個微服務的映象如下:

docker.io/istio/examples-bookinfo-productpage-v1:1.17.0
docker.io/istio/examples-bookinfo-details-v1:1.17.0
docker.io/istio/examples-bookinfo-reviews-v1:1.17.0
docker.io/istio/examples-bookinfo-reviews-v2:1.17.0
docker.io/istio/examples-bookinfo-reviews-v3:1.17.0
docker.io/istio/examples-bookinfo-ratings-v1:1.17.0

  1. 部署元件

我們在應用下,選擇新增元件 -> 指定映象 -> 填寫映象地址 -> 新建元件 -> 確認建立,即可依次建立出這 5 個微服務對應的元件。

  1. 生成可用的 Service

剛剛我們僅完成了所有服務的部署,還未定義這些微服務的存取策略。以 Productpage 為例,我們通過點選拓撲圖中 Productpage 這個元件,即可進入這個服務的管理頁面。找到 埠 -> 新增埠 -> 埠號填寫9080 -> 開啟對外服務 -> 點選生成的路由,即可存取成功。 此時會發現 Productpage 這個元件的頁面還無法拉取到書籍評價資訊。這是由於它預設使用 details 和 reviews 這兩個 Service 名稱連線到它依賴的元件。此時我們部署的 Reviews-v1 等元件還沒有正確的 Service 名稱。因此還是進入元件管理頁面,元件埠 -> 新增埠 -> 埠號填寫9080 -> 修改使用別名 -> 內部域名填寫為 reviews-v1 -> 開啟對內服務。details、reviews-v2、ratings 等元件都是如此,填寫其對應的 Service 名稱後,開啟對內服務即可。

最後在應用的 K8s 資源下,我們還需要建立一個如下的 Service,用來在 Reviews 的三個版本之間負載流量。

apiVersion: v1
kind: Service
metadata:
  labels:
    app: reviews
    service: reviews
  name: reviews
spec:
  ports:
  - name: http
    port: 9080
    protocol: TCP
    targetPort: 9080
  selector:
    component: reviews # 需要在 Reviews 三個版本中,均新增 Kubernetes 屬性,設定上該 Label,才能正確生效
  sessionAffinity: None
  type: ClusterIP
  1. 編排依賴關係

完成以上操作後,存取 Productpage 應用,可以看到書籍評論能正確在三個版本中切換了。此時,可以在應用檢視下,切換到編排模式,根據上述 BookInfo 應用的架構圖進行連線,實現拓撲圖的編排。如下圖所示,這樣編排的好處是後期可以將這個應用整體釋出出去,其他使用者直接安裝下來即可得到一樣的拓撲關係,再也不用擔心找不到各個服務依賴的元件。

3. 灰度釋出

在完成以上部署操作後,我們得到了一個完整的 BookInfo 程式,但此時還未定義 Istio 相關設定,所以還需要通過 Kiali 去定義流量規則。實現灰度釋出。

  1. 設定路由規則

存取 Kiali 管理頁面,即可看到該應用。在左側邊欄選擇 Services,找到 reviews 這個 Service,點選進入,右上角 Actions 選擇 Traffic Shifting,即可看到如下設定:拖動滾軸選擇流量比例。下圖中 30% 的流量將會存取到 reviews-v1 上,70% 的流量存取到 reviews-v2上。點選建立後,即可看見頁面左下角,Kiali 自動為你生成了 virtual services 和 destination rules 資源。你可以點選進去根據自己需求再次編輯。

  1. 驗證路由規則是否生效

找到最開始部署的元件 Productpage,進入元件管理頁面,點選右上角存取入口,可以看到書籍詳情和評級,反覆重新整理頁面,可以看到不帶星級的評價資訊(reviews-v1)與黑色星級評價資訊(reviews-v2)出現的比例大概是 3:7。紅色星級評價資訊(reviews-v3)從未出現。

  1. 驗證元件擴容對流量的影響

找到部署的元件 reviews-v1 ,進入元件管理頁面 -> 伸縮 -> 範例數量設定為4,此時再次存取 Productpage 頁面,反覆重新整理頁面,可以看到 reviews-v1 擴容後,存取到 reviews-v1 與 reviews-v2 的比例仍為 3:7,元件範例數的多少對流量分發策略沒有影響。