1. 程式人生 > >Istio Routing 實踐掌握virtualservice/gateway/destinationrule/AB版本釋出/金絲雀釋出

Istio Routing 實踐掌握virtualservice/gateway/destinationrule/AB版本釋出/金絲雀釋出

[原文](https://medium.com/google-cloud/istio-routing-basics-14feab3c040e) 在學習像 Istio 這樣的新技術時,看一下示例應用程式總是一個好主意。 Istio repo 有一些示例應用程式,但它們似乎有各種不足。 文件中的 BookInfo 是一個很好的示例。 但是,對於我而言,它太冗長,服務太多,而且文件似乎專注於管理 BookInfo 應用程式,而不是從頭開始構建。 有一個較小的 hellohttp 例子,但它更多的是關於自動伸縮而不是其他。 在這篇文章中,我想介紹一下基礎知識,並向您展示如何從頭開始構建支援 Istio 的“hellohttp”應用程式。 要記住的一點是,Istio 只管理您應用的流量。 在這種情況下,應用程式生命週期由底層平臺 Kubernetes 管理。 因此,您需要了解容器和 Kubernetes 基礎知識,並且需要了解 Istio Routing 原語,例如 Gateway,VirtualService,DestinationRule。 我假設大多數人都知道容器和 Kubernetes 基礎知識。 我將在本文中專注於 Istio Routing。 ## 基礎步驟 以下這些大致就是您需要遵循的,以獲得 Istio 的“hellohttp”應用程式的步驟: 1. 建立一個 Kubernetes 叢集並安裝帶有 sidecare 自動注入的 Istio。 2. 使用您選擇的語言建立 Hellohttp 應用程式,建立 Docker 映象並將其推送到公共映象倉庫。 3. 為你的容器建立 Kubernetes deployment 和 service。 4. 建立 Gateway 以啟用到群集的 HTTP(S)流量。 5. 建立 VirtualService,通過 Gateway 公開 Kubernetes 服務。 6. (可選)如果要建立多個版本應用程式,請建立 DestinationRule 以定義可從 VirtualService 引用的 subsets。 7. (可選)如果要在服務網格外部呼叫其他外部服務,請建立 ServiceEntry。 我不會在本文中介紹步驟 1 和 2,因為它們不是特定於 Istio 的。 如果您需要有關這些步驟的幫助,可以檢視我在本文末尾提到的文章。 第 3 步也不是 Istio 特定的,但它是其他一切的先決條件,所以讓我們從那開始。 ## Deployment 和 Service 正如我所提到的,應用程式生命週期由 Kubernetes 管理。 因此,您需要從建立 Kubernetes deployment 和 service 開始。 我的情況如下,我有一個容器化的 ASP.NET 核心應用程式,其映象我已經推送到谷歌映象倉庫。 讓我們從建立一個`hellohttp-deploy.yaml.yaml`檔案開始: ```yaml apiVersion: v1 kind: Service metadata: name: hellohttp-service labels: app: hellohttp spec: ports: - port: 80 name: http selector: app: hellohttp --- apiVersion: apps/v1 kind: Deployment metadata: name: hellohttp-v1 spec: replicas: 1 selector: matchLabels: app: hellohttp version: v1 template: metadata: labels: app: hellohttp version: v1 spec: containers: - name: hellohttp image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "echo 'hello httpd v1' > /var/www/index.html; httpd -f -p 80 -h /var/www/"] ports: - containerPort: 80 ``` 建立 Deployment 和 Service: ```shell $ kubectl apply -f hellohttp-deploy.yaml service "hellohttp-service" created deployment.extensions "hellohttp-v1" created ``` 到目前為止沒有任何特定的針對 Istio 的內容。 ## Gateway 我們現在可以開始研究 Istio Routing。 首先,我們需要為服務網格啟用 HTTP/HTTPS 流量。 為此,我們需要建立一個閘道器。 Gateway 描述了在邊緣執行的負載均衡,用於接收傳入或傳出的 HTTP/TCP 連線。 讓我們建立一個`hellohttp-gateway.yaml`檔案: ```yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: hellohttp-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "hellohttp.com" ``` 建立 Gateway: ```shell $ kubectl apply -f hellohttp-gateway.yaml gateway.networking.istio.io "hellohttp-gateway" created ``` 此時,我們為叢集啟用了 HTTP 流量。 我們需要將之前建立的 Kubernetes 服務對映到 Gateway。 我們將使用 VirtualService 執行此操作。 ## VirtualService VirtualService 實際上將 Kubernetes 服務連線到 Istio 閘道器。 它還可以執行更多操作,例如定義一組流量路由規則,以便在主機被定址時應用,但我們不會深入瞭解這些細節。 讓我們建立一個`hellohttp-virtualservice.yaml`檔案: ```yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hellohttp-virtualservice spec: hosts: - "hellohttp.com" gateways: - hellohttp-gateway http: - route: - destination: host: hellohttp-service ``` 請注意,VirtualService 與特定閘道器繫結,並定義引用 Kubernetes 服務的主機。 建立 VirtualService: ```shell $ kubectl apply -f hellohttp-virtualservice.yaml virtualservice.networking.istio.io "hellohttp-virtualservice" created ``` ## 測試 V1 版本 APP 我們準備測試我們的應用程式了。 我們需要獲取 Istio Ingress Gateway 的 IP 地址: ```shell $ istio-ingressgateway NodePort 10.109.111.38 15020:32105/TCP,80:30824/TCP,443:32478/TCP,31400:32419/TCP,15443:30884/TCP 4d ``` 當我們在瀏覽器中開啟`NodePort-IP`時,我們應該看到 hellohttp ASP.NET Core 應用程式: ![](https://raw.githubusercontent.com/PassZhang/passzhang.github.io/images-picgo/20200818155844.png) ## DestinationRule 在某些時候,您希望將應用更新為新版本。 也許你想分割兩個版本之間的流量。 您需要建立一個 DestinationRule 來定義是哪些版本,在 Istio 中稱為 subset。 首先,更新 `hellohttp-deploy.yaml` 檔案以使用 v2 版本的容器定義 v2 的 deployment: ```yaml apiVersion: v1 kind: Service metadata: name: hellohttp-service labels: app: hellohttp spec: ports: - port: 80 name: http selector: app: hellohttp --- apiVersion: apps/v1 kind: Deployment metadata: name: hellohttp-v1 spec: replicas: 1 selector: matchLabels: app: hellohttp version: v1 template: metadata: labels: app: hellohttp version: v1 spec: containers: - name: hellohttp image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "echo 'hello httpd v1' > /var/www/index.html; httpd -f -p 80 -h /var/www/"] ports: - containerPort: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: hellohttp-v2 spec: replicas: 1 selector: matchLabels: app: hellohttp version: v2 template: metadata: labels: app: hellohttp version: v2 spec: containers: - name: hellohttp image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "echo 'hello httpd v2' > /var/www/index.html; httpd -f -p 80 -h /var/www/"] ports: - containerPort: 80 ``` 建立新的 Deployment: ```shell $ kubectl apply -f hellohttp-deploy.yaml service "hellohttp-service" unchanged deployment.extensions "hellohttp-v1" unchanged deployment.extensions "hellohttp-v2" created ``` 如果使用 EXTERNAL-IP 重新整理瀏覽器,您將看到應用程式的 v1 和 v2 版本交替出現: ![](https://raw.githubusercontent.com/PassZhang/passzhang.github.io/images-picgo/20200818155844.png) ![](https://raw.githubusercontent.com/PassZhang/passzhang.github.io/images-picgo/20200818160012.png) 這是符合預期的,因為兩個版本都暴露在相同的 Kubernetes 服務之後:hellohttp-service。 如果您想將服務僅指向 v2,該怎麼辦? 這可以通過在 VirtualService 中指定 subset 來完成,但我們需要首先在 DestinationRules 中定義這些 subset。 DestinationRule 本質上是將標籤對映到 Istio 的 subset。 建立一個`hellohttp-destinationrule.yaml`檔案: ```yaml apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: hellohttp-destinationrule spec: host: hellohttp-service trafficPolicy: tls: mode: ISTIO_MUTUAL subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 ``` 建立 DestinationRule: ```shell $ kubectl apply -f hellohttp-destinationrule.yaml destinationrule.networking.istio.io "hellohttp-destinationrule" created ``` 現在你可以從 VirtualService 來引用 v2 subset: ```yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hellohttp-virtualservice spec: hosts: - "hellohttp.com" gateways: - hellohttp-gateway http: - route: - destination: host: hellohttp-service subset: v2 ``` 更新 VirtualService: ```shell $ kubectl apply -f hellohttp-virtualservice.yaml virtualservice.networking.istio.io "hellohttp-virtualservice" configured ``` 如果您現在繼續瀏覽 EXTERNAL-IP,您現在應該只能看到應用程式的 v2 版本。 ## 測試AB版本更新 可以從 VirtualService 來引用v2 subset和v1 subset ```yaml [root@localhost hello-world]# cat hellohttp-virtualservice.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hellohttp-virtualservice spec: hosts: - "hellohttp.com" gateways: - hellohttp-gateway http: - route: - destination: host: hellohttp-service subset: v1 weight: 75 - destination: host: hellohttp-service subset: v2 weight: 25 ``` **上面的配置就是通過VirtualService 呼叫DestinationRule 裡面定義的host分類,來進行AB 版本的流量分離,進行AB 版本更新。** 對於生產環境裡面的版本更新可以進行header 主機頭匹配,進行版本區分,基礎的金絲雀釋出更新版本就是這樣實現的。 ## ServiceEntry 我想在 Istio Routing 中提到的最後一件事是 ServiceEntry。 預設情況下,Istio 中的所有外部流量都被阻止。 如果要啟用外部流量,則需要建立 ServiceEntry 以列出為外部流量啟用的協議和主機。 我不會在這篇文章中展示一個例子,但你可以在[這裡](https://istio.io/docs/reference/config/istio.networking.v1alpha3/#ServiceEntry)閱讀更多相關內容。 希望這篇文章對你有用! 如果您想了解更多資訊,可以使用 codelab 系列以下兩部分,其中所有這些概念和更多內容將在逐步的詳細教程中進行說明: - [Deploy ASP.NET Core app to Google Kubernetes Engine with Istio (Part 1)](https://codelabs.developers.google.com/codelabs/cloud-istio-hellohttp-part1) - [Deploy ASP.NET Core app to Google Kubernetes Engine with Istio (Part 2)](https://codelabs.developers.google.com/codelabs/cloud-istio-hellohtt