Istio 流量管理

原文連接:Istio 流量管理php

Istio 從 0.8 版本開始出現了一個新的 API 組:networking.istio.io/v1alpha3,應該會替代現有的 config.istio.io/v1alpha2 API。新的 API 不論是結構上仍是功能上、以及命名上,都有很大差別。若是不做特殊說明,本文全部的示例將採用新版 API。node

本文將經過簡單的示例來演示經過 Istio 實現應用的金絲雀部署。mysql

正常狀況下 istioctl 和 kubectl 均可以用來操做這些對象,可是 kubectl 缺少驗證功能,所以調試階段使用 istioctl 會更方便一些。sql

1. Bookinfo 應用介紹

以 Bookinfo 應用爲示例,它由四個單獨的微服務構成,用來演示多種 Istio 特性。這個應用模仿在線書店的一個分類,顯示一本書的信息。頁面上會顯示一本書的描述,書籍的細節(ISBN、頁數等),以及關於這本書的一些評論。api

Bookinfo 應用分爲四個單獨的微服務:瀏覽器

  • productpageproductpage 微服務會調用 detailsreviews 兩個微服務,用來生成頁面。
  • details :這個微服務包含了書籍的信息。
  • reviews :這個微服務包含了書籍相關的評論。它還會調用 ratings 微服務。
  • ratingsratings 微服務中包含了由書籍評價組成的評級信息。

reviews 微服務有 3 個版本:bash

  • v1 版本不會調用 ratings 服務。
  • v2 版本會調用 ratings 服務,並使用 1 到 5 個黑色星形圖標來顯示評分信息。
  • v3 版本會調用 ratings 服務,並使用 1 到 5 個紅色星形圖標來顯示評分信息。

下圖展現了這個應用的端到端架構。架構

*Istio 注入以前的 Bookinfo 應用*

Bookinfo 是一個異構應用,幾個微服務是由不一樣的語言編寫的。這些服務對 Istio 並沒有依賴,可是構成了一個有表明性的服務網格的例子:它由多個服務、多個語言構成,而且 reviews 服務具備多個版本。app

2. 部署 Bookinfo 應用

要在 Istio 中運行這一應用,無需對應用自身作出任何改變。咱們只要簡單的在 Istio 環境中對服務進行配置和運行,具體一點說就是把 Envoy sidecar 注入到每一個服務之中。這個過程所需的具體命令和配置方法由運行時環境決定,而部署結果較爲一致,以下圖所示:負載均衡

全部的微服務都和 Envoy sidecar 集成在一塊兒,被集成服務全部的出入流量都被 sidecar 所劫持,這樣就爲外部控制準備了所需的 Hook,而後就能夠利用 Istio 控制平面爲應用提供服務路由、遙測數據收集以及策略實施等功能。

接下來能夠根據 Istio 的運行環境,按照下面的講解完成應用的部署。

  1. 進入 Istio 安裝目錄。

  2. 啓動應用容器:

    $ kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml)
    複製代碼

    istioctl kube-inject 命令用於在在部署應用以前修改 bookinfo.yaml

    $ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
    複製代碼

    上面的命令會啓動所有的四個服務,其中也包括了 reviews 服務的三個版本(v1v2 以及 v3

  3. 給應用定義 Ingress gateway:

    $ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
    複製代碼
  4. 確認全部的服務和 Pod 都已經正確的定義和啓動:

    $ kubectl get services
    
    NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                         AGE
    details       ClusterIP   10.254.86.98     <none>        9080/TCP                        3h
    kubernetes    ClusterIP   10.254.0.1       <none>        443/TCP                         149d
    productpage   ClusterIP   10.254.199.214   <none>        9080/TCP                        3h
    ratings       ClusterIP   10.254.102.147   <none>        9080/TCP                        3h
    reviews       ClusterIP   10.254.249.86    <none>        9080/TCP                        3h
    複製代碼
    $ kubectl get pods
    
    NAME                              READY     STATUS    RESTARTS   AGE
    details-v1-6456dbdb9-crqnw        2/2       Running   0          3h
    productpage-v1-6f6887645c-52qhn   2/2       Running   0          3h
    ratings-v1-648cf76d8f-g65s5       2/2       Running   0          3h
    reviews-v1-7dcbc85bb5-j748n       2/2       Running   0          3h
    reviews-v2-65fd78f5df-r8n6r       2/2       Running   0          3h
    reviews-v3-95c85969c-zmpfx        2/2       Running   0          3h
    複製代碼
  5. 肯定 Ingress 的 IP 和端口

    執行如下命令以肯定 ingressgateway 是否啓用了 NodePort 模式。

    $ kubectl -n istio-system get svc istio-ingressgateway
    
    NAME                   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                                                                     AGE
    istio-ingressgateway   NodePort   10.254.160.93   <none>        80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:25059/TCP,8060:36612/TCP,15030:25049/TCP,15031:36810/TCP   3h
    複製代碼

    肯定 ingress IP:

    $ export INGRESS_HOST=$(kubectl -n istio-system get po -l istio=ingressgateway -o go-template='{{range .items}}{{.status.hostIP}}{{end}}')
    複製代碼

    肯定端口:

    $ export INGRESS_PORT=$(kubectl -n istio-system get svc istio-ingressgateway -o go-template='{{range .spec.ports}}{{if eq .name "http"}}{{.nodePort}}{{end}}{{end}}')
    複製代碼
  6. 設置 GATEWAY_URL

    $ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
    複製代碼

下面能夠用 curl 命令來確認 Bookinfo 應用的運行狀況:

$ curl -o /dev/null -s -w "%{http_code}\n" http://${GATEWAY_URL}/productpage

200
複製代碼

還能夠用瀏覽器打開網址 http://$GATEWAY_URL/productpage,來瀏覽應用的 Web 頁面。若是刷新幾回應用的頁面,就會看到頁面中會隨機展現 reviews 服務的不一樣版本的效果(紅色、黑色的星形或者沒有顯示)。reviews 服務出現這種狀況是由於咱們尚未使用 Istio 來控制版本的路由。

3. 金絲雀部署

因爲 Bookinfo 示例部署了三個版本的 reviews 微服務,所以咱們須要設置默認路由。 不然,若是您當屢次訪問應用程序,您會注意到有時輸出包含星級評分,有時又沒有。 這是由於沒有爲應用明確指定缺省路由時,Istio 會將請求隨機路由到該服務的全部可用版本上。

此任務假定您還沒有設置任何路由。 若是您已經爲示例應用程序建立了存在衝突的路由規則,則須要在下面的命令中使用 replace 代替 create。 請注意:本文檔假設尚未設置任何路由規則。

首先將全部微服務的默認路由設置爲 v1。

$ istioctl create -f samples/bookinfo/networking/virtual-service-all-v1.yaml
複製代碼
$ istioctl create -f samples/bookinfo/networking/destination-rule-all.yaml
複製代碼

能夠經過下面的命令來顯示已建立的路由規則:

$ istioctl get virtualservices -o yaml
複製代碼
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: details
  ...
spec:
 hosts:
 - details
 http:
 - route:
 - destination:
 host: details
 subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: productpage
  ...
spec:
 gateways:
 - bookinfo-gateway
 - mesh
 hosts:
 - productpage
 http:
 - route:
 - destination:
 host: productpage
 subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: ratings
  ...
spec:
 hosts:
 - ratings
 http:
 - route:
 - destination:
 host: ratings
 subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: reviews
  ...
spec:
 hosts:
 - reviews
 http:
 - route:
 - destination:
 host: reviews
 subset: v1
---
複製代碼

因爲路由規則是經過異步方式分發到代理的,所以在嘗試訪問應用程序以前,您應該等待幾秒鐘,以便規則傳播到全部 pod 上。

如今在瀏覽器中打開 Bookinfo 應用程序的 URL (http://$GATEWAY_URL/productpage),你應該能夠看到 Bookinfo 應用程序的 productpage 頁面。 請注意, productpage 頁面顯示的內容中沒有評分星級,這是由於 reviews:v1 服務不會訪問 ratings 服務。

因爲新的 API 引入了一些新的配置資源,並且不向後兼容,因此頗有必要來解釋一下上面兩個 yaml 文件提到的兩個新概念:VirtualServiceDestinationRule

VirtualService

過去的路由分配比較簡單,使用標籤便可。新的版本中,提出了 VirtualService 的概念。VirtualService 由一組路由規則構成,用於對服務實體(在 K8S 中對應爲 Pod)進行尋址。一旦有流量符合其中規則的選擇條件,就會發送流量給對應的服務(或者服務的一個版本/子集)。

VirtualService 描述了一個或多個用戶可尋址目標到網格內實際工做負載之間的映射。其中可尋址的目標服務使用 hosts 字段來指定,而網格內的實際工做負載由每一個 route 配置項中的 destination 字段指定。在上面的示例中,這兩個地址是相同的,但實際上用戶可尋址目標能夠是任何用於定位服務的、具備可選通配符前綴或 CIDR 前綴的 DNS 名稱。

流量的特徵除了請求數據以外,還包括流量的來源,這樣就能根據一些上下文來進行靈活的定義了。

例如,如下規則定義來自打了標籤 app=sleep 的 Pod 對 php-server 的請求,都轉向 v1:

apiVersion: networking.istio.io/v1alpha3

kind: VirtualService

metadata:

 name: sleep-server-route

spec:

 hosts:

 - "php-server"

 http:

 - match:

 - sourceLabels:

 app: sleep

 route:

 - destination:

 name: php-server

 subset: v1

 - route:

 - destination:

 name: php-server

 subset: v2
複製代碼

這裏的匹配策略是具備從上到下的優先級的,也就是說,最下一條就是缺省路由。因此沒有打標籤 app=sleep 的 Pod 對 php-server 的請求,都轉向 v2。

而本文的 Bookinfo 示例中建立的路由規則表示:

  • 全部對 details 的請求,都轉向 details 的 v1 版本。
  • 全部對 productpage 的請求,都轉向 productpage 的 v1 版本。
  • 全部對 ratings 的請求,都轉向 ratings 的 v1 版本。
  • 全部對 reviews 的請求,都轉向 reviews 的 v1 版本。

能夠看到,match 中再也不包含 source,這裏使用標籤來過濾。寫完應用以後,咱們再次訪問 Bookinfo 應用程序的 URL (http://$GATEWAY_URL/productpage),會發現並無生效。這是由於,在 v3 版本的 API 中,目標規則再也不是透明瞭,路由定義必須以目標策略爲基礎。

DestinationRule

所以這裏須要定義一個 DestinationRule 對象,來知足上面的目標需求:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: productpage
spec:
 host: productpage
 subsets:
 - name: v1
 labels:
 version: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: reviews
spec:
 host: reviews
 subsets:
 - name: v1
 labels:
 version: v1
 - name: v2
 labels:
 version: v2
 - name: v3
 labels:
 version: v3
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: ratings
spec:
 host: ratings
 subsets:
 - name: v1
 labels:
 version: v1
 - name: v2
 labels:
 version: v2
 - name: v2-mysql
 labels:
 version: v2-mysql
 - name: v2-mysql-vm
 labels:
 version: v2-mysql-vm
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: details
spec:
 host: details
 subsets:
 - name: v1
 labels:
 version: v1
 - name: v2
 labels:
 version: v2
---
複製代碼

DestinationRule 用於配置在將流量轉發到服務時應用的策略集。這些策略應由服務提供者撰寫,用於描述斷路器、負載均衡、TLS 設置等。

  • DestinationRule 的 host 能夠包含通配符前綴,以容許單個規則應用於多個服務。
  • DestinationRule 定義了目的 host 的子集 subsets (例如:命名版本)。 這些 subset 用於 VirtualService 的路由規則設置中,能夠將流量導向服務的某些特定版本。經過這種方式爲版本命名後,能夠在不一樣的虛擬服務中明確地引用這些命名版本的 subset,簡化 Istio 代理髮出的統計數據,並能夠將 subsets 編碼到 SNI 頭中。

如今再次訪問 Bookinfo 應用程序的 URL (http://$GATEWAY_URL/productpage),會發現規則已經生效了。

示例一:將 10% 請求發送到 v2 版本而其他 90% 發送到 v1 版本

$ cat <<EOF | istioctl replace -f - apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: reviews
spec:
 hosts:
 - reviews
 http:
 - route:
 - destination:
 host: reviews
 subset: v1
 weight: 90
 - destination:
 host: reviews
 subset: v2
 weight: 10
EOF
複製代碼

如今的規則就是刷新 productpage 頁面,90% 的機率看到黑色星標的評論,10%的機率看不到星標。

**注意:**由於使用Envoy sidecar的實現,你須要刷新頁面不少次才能看到接近規則配置的機率分佈。

示例二:將 jason 用戶的請求所有發到 v2 版本

cat <<EOF | istioctl replace -f - apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: reviews
spec:
 hosts:
 - reviews
 http:
 - match:
 - headers:
 end-user:
 exact: jason
 route:
 - destination:
 host: reviews
 subset: v2
 - route:
 - destination:
 host: reviews
 subset: v1
EOF
複製代碼

使用 jason 用戶登錄 productpage 頁面,你能夠看到每一個刷新頁面時,頁面上都有一個1到5顆星的評級。若是你使用其餘用戶登錄的話,將因繼續使用 reviews:v1 而看不到星標評分。

示例三:所有切換到 v3 版本

cat <<EOF | istioctl replace -f - apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: reviews
spec:
 hosts:
 - reviews
 http:
 - route:
 - destination:
 host: reviews
 subset: v3
EOF
複製代碼

如今不論你使用什麼用戶登錄 productpage 頁面,你均可以看到帶紅色星標評分的評論了。

4. 參考

相關文章
相關標籤/搜索