Service Mesh - Istio流量控制篇(上)

動態路由:用Virtual Service和Destination Rule設置路由規則

路由這個功能是流量控制裏面很是重要,也是最經常使用的一個功能。在Istio裏通常經過Virtual Service(虛擬服務)以及Destination Rule(目標規則)這兩個API資源進行動態路由的設置。nginx

基本概念

虛擬服務(Virtual Service):web

  • 定義路由規則,匹配請求
  • 描述知足條件的請求去哪裏

目標規則(Destination Rule):算法

  • 定義子集、策略
  • 描述到達目標的請求怎麼處理

Service Mesh - Istio流量控制篇(上)

實踐動態路由

在上一篇Service Mesh - Istio安裝與部署文章中,咱們演示了BookInfo這個Demo應用的部署,而且能夠發現其中的 reviews 服務共有三個不一樣的版本。如今咱們的需求是將請求路由到 reviews 服務的指定版本上。例如,路由到版本1上,以下圖:
Service Mesh - Istio流量控制篇(上)api

實現該需求很簡單,官方已經提供了配置清單文件,咱們只需執行以下命令應用路由規則便可:瀏覽器

[root@m1 ~]# kubectl apply -f /usr/local/istio-1.8.1/samples/bookinfo/networking/virtual-service-all-v1.yaml    # 建立虛擬服務
virtualservice.networking.istio.io/productpage created
virtualservice.networking.istio.io/reviews created
virtualservice.networking.istio.io/ratings created
virtualservice.networking.istio.io/details created
[root@m1 ~]# kubectl apply -f /usr/local/istio-1.8.1/samples/bookinfo/networking/destination-rule-all.yaml   # 建立目標規則
destinationrule.networking.istio.io/productpage created
destinationrule.networking.istio.io/reviews created
destinationrule.networking.istio.io/ratings created
destinationrule.networking.istio.io/details created
[root@m1 ~]#

而後回到應用頁面上測試下規則是否生效,正常狀況下,此時不管怎麼刷新頁面,訪問的都是版本1的 reviews 服務:
Service Mesh - Istio流量控制篇(上)緩存

那麼配置是如何生效的呢?咱們先來看看這兩個API資源它們的一些具體配置項:
Service Mesh - Istio流量控制篇(上)安全

  • Virtual Service
    • hosts:對應 DestinationRule 所配置的host,可配置多個
    • gateways:用來和配置的網關進行匹配使用的,若是是服務網關內部的虛擬服務就不須要配置這一項
    • http:配置http請求的路由規則與 HTTPRoute 對應
    • tls:配置tls請求的路由規則
    • tcp:配置tcp請求的路由規則
    • exportTo:給虛擬服務設置它的可見性,例如設置爲全部的Namspace均可見
  • HTTPRoute:
    • match:設置匹配知足什麼樣條件的請求,對應 HTTPMatchRequest 對象配置項
    • route:匹配到的請求通過route配置的規則進行路由
  • HTTPRouteDestination:
    • destination:經過該字段將虛擬服務與目標規則進行綁定
  • Destination Rule
    • host:最終路由到的具體目標地址
    • subset:子集,通常主要是給服務限定版本

virtual-service-all-v1.yaml 文件中針對 reviews 服務建立的虛擬服務配置內容以下:bash

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService  # 資源類型
metadata:
  name: reviews   # 虛擬服務的名稱
spec:
  hosts:
  - reviews   # 虛擬服務的主機名,可定義多個
  http:  # 沒有定義match表明匹配任意的請求
  - route:
    - destination:
        host: reviews   # 服務名稱,與目標規則中的host配置對應
        subset: v1      # 經過子集限定了服務版本

destination-rule-all.yaml 文件中針對 reviews 服務建立的目標規則配置內容以下:cookie

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule  # 資源類型
metadata:
  name: reviews   # 目標規則的名稱
spec:
  host: reviews   # 指向k8s中的服務名稱,k8s平臺的dns機制能夠解析出具體的服務地址
  subsets:   # 定義子集,對應該服務的三個版本,虛擬服務就是根據在這裏定義的子集來路由對應的版本的
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3

Virtual Service 和 Destination Rule 的應用場景:app

  • 按服務版本路由
  • 按比例切分流量
  • 根據匹配規則進行路由
  • 定義各類策略(負載均衡、鏈接池等)

網關:用Gateway管理進入網格的流量

什麼是網關(Gateway)

  • 一個運行在網格邊緣的負載均衡器
  • 接收外部請求,轉發給網格內的服務
  • 配置對外的端口、協議與內部服務的映射關係
  • Istio中的Ingress網關控制入口流量,Egress網關控制出口流量,在網關只定義入口點不定義具體的路由
  • 與k8s中的Ingress同樣,Istio中的Gateway也只是一種資源,須要配合一個真正工做的組件使用,在k8s中一般是ingress-nginx,在Istio中則是基於envoy的istio-ingressgateway / istio-egressgateway
    Service Mesh - Istio流量控制篇(上)
  • 官方文檔

實踐建立網關

咱們來建立一個入口網關,配合虛擬服務對外暴露一些服務接口:
Service Mesh - Istio流量控制篇(上)

Gateway資源的一些配置選項
Service Mesh - Istio流量控制篇(上)

  • Gateway:
    • servers:定義入口點列表
    • selector:選擇器,用於經過label選擇集羣中Istio網關的Pod
  • Server:
    • port:暴露給外部訪問的端口信息,包括端口號、名稱、協議
    • hosts:暴露給外部可訪問的host列表
  • VirtualService:
    • gateways:用於配置關聯哪些Gateway資源,經過名稱指定

建立 test-gateway.yaml 文件,內容以下:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway   # 資源類型爲網關
metadata:
  name: test-gateway   # 網關的名稱
spec:
  selector:   # 配置選擇器,指向istio-ingressgateway的pod
    istio: ingressgateway
  servers:  # 定義對外暴露的入口點,主要配置哪些host和端口容許訪問
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"

---

# 因爲在網關只定義入口點不定義具體的路由,因此咱們須要定義虛擬服務來配置路由規則
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService   # 資源類型爲虛擬服務
metadata:
  name: test-gateway    # 虛擬服務的名稱
spec:
  hosts:
  - "*"
  gateways:   # 配置gateway的名稱,用於關聯具體的gateway
  - test-gateway
  http:
  - match:   # 定義路由匹配規則,即暴露哪些接口
    - uri:
        prefix: /details
    - uri:
        exact: /health
    route:
    - destination:   # 將請求轉發到哪些目標
        host: details
        port:
          number: 9080

在應用該配置文件以前,咱們先到瀏覽器上訪問 details 接口,此時返回的狀態碼將會是404:
Service Mesh - Istio流量控制篇(上)

而後應用配置文件,建立咱們所定義的網關和虛擬服務:

[root@m1 ~]# kubectl apply -f service-mash/test-gateway.yaml
gateway.networking.istio.io/test-gateway created
virtualservice.networking.istio.io/test-gateway created
[root@m1 ~]#

經過網關和虛擬服務暴露接口後,再從新訪問一下該接口,能夠看到能正常訪問了:
Service Mesh - Istio流量控制篇(上)

一樣,health 接口也能夠被訪問到:
Service Mesh - Istio流量控制篇(上)

Gateway 的應用場景:

  • 暴露網格內服務給外界訪問
  • 訪問安全(HTTPS、mTLS 等)
  • 統一應用入口,API 聚合

服務入口:用Service Entry擴展你的網格服務

官方文檔:

什麼是服務入口(ServiceEntry):

  • 服務入口與網關正好是相反的概念,服務入口是用於添加外部服務到網格內
  • 管理到外部服務的請求,對外部服務進行抽象,使得能夠像訪問內部服務同樣訪問外部服務
  • 擴展網格,例如須要給多個集羣共享同一個Mesh的場景
    Service Mesh - Istio流量控制篇(上)

接下來咱們實踐一下,將 httpbin.org 註冊爲網格內部的服務,並配置流控策略。httpbin.org 這個網站能測試 HTTP 請求和響應的各類信息,好比 cookie、ip、headers 和登陸驗證等,且支持 GET、POST 等多種方法,對 web 開發和測試頗有幫助,咱們能夠將它做爲一個外部的服務進行測試。

因爲咱們以前部署的Bookinfo應用的全部服務中都沒有 curl 命令,所以咱們想要模擬內部服務調用外部服務,就須要額外添加一個 sleep 服務。官方已經給咱們準備好了配置文件,使用以下命令應用一下便可:

[root@m1 ~]# kubectl apply -f /usr/local/istio-1.8.1/samples/sleep/sleep.yaml
serviceaccount/sleep created
service/sleep created
deployment.apps/sleep created
[root@m1 ~]#

經過 sleep 服務來訪問一下 httpbin 這個外部服務:

[root@m1 ~]# kubectl exec -it sleep-854565cb79-gm6hj -c sleep -- curl http://httpbin.org/headers
{
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "0", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/7.69.1", 
    "X-Amzn-Trace-Id": "Root=1-5fe0b2c6-0940d09657bb9faf42e9f49e", 
    "X-B3-Sampled": "1", 
    "X-B3-Spanid": "c8f80494e0358f1f", 
    "X-B3-Traceid": "46b7447441931824c8f80494e0358f1f", 
    "X-Envoy-Attempt-Count": "1", 
    "X-Envoy-Peer-Metadata": "ChkKDkFQUF9DT05UQUlORVJTEgcaBXNsZWVwChoKCkNMVVNURVJfSUQSDBoKS3ViZXJuZXRlcwoYCg1JU1RJT19WRVJTSU9OEgcaBTEuOC4xCt8BCgZMQUJFTFMS1AEq0QEKDgoDYXBwEgcaBXNsZWVwChkKDGlzdGlvLmlvL3JldhIJGgdkZWZhdWx0CiEKEXBvZC10ZW1wbGF0ZS1oYXNoEgwaCjg1NDU2NWNiNzkKJAoZc2VjdXJpdHkuaXN0aW8uaW8vdGxzTW9kZRIHGgVpc3RpbwoqCh9zZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1uYW1lEgcaBXNsZWVwCi8KI3NlcnZpY2UuaXN0aW8uaW8vY2Fub25pY2FsLXJldmlzaW9uEggaBmxhdGVzdAoaCgdNRVNIX0lEEg8aDWNsdXN0ZXIubG9jYWwKIAoETkFNRRIYGhZzbGVlcC04NTQ1NjVjYjc5LWdtNmhqChYKCU5BTUVTUEFDRRIJGgdkZWZhdWx0CkkKBU9XTkVSEkAaPmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9kZWZhdWx0L2RlcGxveW1lbnRzL3NsZWVwChcKEVBMQVRGT1JNX01FVEFEQVRBEgIqAAoYCg1XT1JLTE9BRF9OQU1FEgcaBXNsZWVw", 
    "X-Envoy-Peer-Metadata-Id": "sidecar~172.22.152.249~sleep-854565cb79-gm6hj.default~default.svc.cluster.local"
  }
}
[root@m1 ~]#

從輸出結果能夠看到,從 sleep 服務的內部可以直接訪問外部的 httpbin 服務,緣由是Istio裏默認容許全部的網格內的服務直接訪問外部服務。因此爲了測試服務入口這個API資源,咱們須要把這種容許訪問外部服務的行爲給關掉,使得只有註冊過的服務才能訪問外部服務。

使用以下命令可關閉出流量可訪問權限(outboundTrafficPolicy = REGISTRY_ONLY):

[root@m1 ~]# istioctl install --set profile=demo -y --set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY

此時再經過 sleep 訪問 httpbin 就訪問不到了,沒有任何輸出:

[root@m1 ~]# kubectl exec -it sleep-854565cb79-gm6hj -c sleep -- curl http://httpbin.org/headers
[root@m1 ~]#

如今咱們來爲外部服務(httpbin)配置 ServiceEntry ,讓 sleep 服務經過服務入口來訪問外部服務。具體命令以下:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry   # 資源類型爲服務入口
metadata:
  name: httpbin-ext   # 服務入口的名稱 
spec:
  hosts:   # 外部服務的訪問地址列表,域名或ip
  - httpbin.org
  ports:   # 配置外部服務的訪問端口信息
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS   # 指定服務發現機制
  location: MESH_EXTERNAL  # 定義該服務位於網格內部仍是網格外部
EOF

經過以下命令可查看已建立的服務入口:

[root@m1 ~]# kubectl get se
NAME          HOSTS             LOCATION        RESOLUTION   AGE
httpbin-ext   ["httpbin.org"]   MESH_EXTERNAL   DNS          97s
[root@m1 ~]#

測試從 sleep 服務訪問 httpbin :

[root@m1 ~]# kubectl exec -it sleep-854565cb79-gm6hj -c sleep -- curl http://httpbin.org/headers
{
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "0", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/7.69.1", 
    "X-Amzn-Trace-Id": "Root=1-5fe0bd82-51a06204013c7006305ac384", 
    "X-B3-Sampled": "1", 
    "X-B3-Spanid": "3cdd9036d7815b35", 
    "X-B3-Traceid": "08d1682631d190293cdd9036d7815b35", 
    "X-Envoy-Attempt-Count": "1", 
    "X-Envoy-Decorator-Operation": "httpbin.org:80/*", 
    "X-Envoy-Peer-Metadata": "ChkKDkFQUF9DT05UQUlORVJTEgcaBXNsZWVwChoKCkNMVVNURVJfSUQSDBoKS3ViZXJuZXRlcwoYCg1JU1RJT19WRVJTSU9OEgcaBTEuOC4xCt8BCgZMQUJFTFMS1AEq0QEKDgoDYXBwEgcaBXNsZWVwChkKDGlzdGlvLmlvL3JldhIJGgdkZWZhdWx0CiEKEXBvZC10ZW1wbGF0ZS1oYXNoEgwaCjg1NDU2NWNiNzkKJAoZc2VjdXJpdHkuaXN0aW8uaW8vdGxzTW9kZRIHGgVpc3RpbwoqCh9zZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1uYW1lEgcaBXNsZWVwCi8KI3NlcnZpY2UuaXN0aW8uaW8vY2Fub25pY2FsLXJldmlzaW9uEggaBmxhdGVzdAoaCgdNRVNIX0lEEg8aDWNsdXN0ZXIubG9jYWwKIAoETkFNRRIYGhZzbGVlcC04NTQ1NjVjYjc5LWdtNmhqChYKCU5BTUVTUEFDRRIJGgdkZWZhdWx0CkkKBU9XTkVSEkAaPmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9kZWZhdWx0L2RlcGxveW1lbnRzL3NsZWVwChcKEVBMQVRGT1JNX01FVEFEQVRBEgIqAAoYCg1XT1JLTE9BRF9OQU1FEgcaBXNsZWVw", 
    "X-Envoy-Peer-Metadata-Id": "sidecar~172.22.152.249~sleep-854565cb79-gm6hj.default~default.svc.cluster.local"
  }
}
[root@m1 ~]#

服務入口的配置選項
Service Mesh - Istio流量控制篇(上)


流量轉移:灰度發佈是如何實現的?

官方文檔:

藍綠部署

Service Mesh - Istio流量控制篇(上)

藍綠部署簡單理解就是當須要部署新版本時,不會去動老版本的服務,而是在另外一個環境部署相同數量的新服務,而後當新的服務測試確認 OK 後,把流量切到新的服務這邊來。

其實這種部署方式,就是咱們說的預發環境。生產線上有兩套相同的集羣,一套是 Prod 是真實服務的,另外一套是 Stage 是預發環境,發佈發 Stage,而後把流量切到 Stage 這邊,因而 Stage 就成了 Prod,而以前的 Prod 則成了 Stage。有點像換頁似的。

這種方式的優勢是沒有停機,實時發佈和升級,也避免有新舊版本同時在線的問題。但這種部署的問題就是有點浪費,由於須要使用雙倍的資源(不過,這只是在物理機時代,在雲計算時代沒事,由於虛擬機部署完就能夠釋放了)。

另外,若是咱們的服務中有狀態,好比一些緩存什麼的,停機部署和藍綠部署都會有問題。

灰度發佈(金絲雀發佈)

Service Mesh - Istio流量控制篇(上)

金絲雀部署又叫灰度部署,其得名來源於礦井中的金絲雀。17 世紀,英國礦井工人發現,金絲雀對瓦斯這種氣體十分敏感。空氣中哪怕有極其微量的瓦斯,金絲雀也會中止歌唱。而當瓦斯含量超過必定限度時,雖然魯鈍的人類毫無察覺,金絲雀卻早已毒發身亡。當時在採礦設備相對簡陋的條件下,工人們每次下井都會帶上一隻金絲雀做爲 」 瓦斯檢測指標 「,以便在危險情況下緊急撤離。

灰度部署是指逐漸將生產環境流量從老版本切換到新版本。一般流量是按比例分配的。例如 90% 的請求流向老版本,10% 的請求流向新版本。而後沒有發現問題,就逐步擴大新版本上的流量,減小老版本上的流量。

除了切流量外,對於多租戶的平臺,例如雲計算平臺,灰度部署也能夠將一些新的版本先部署到一些用戶上,若是沒有問題,擴大部署,直到所有用戶。通常的策略是,從內部用戶開始,而後是通常用戶,最後是大客戶。

這個技術大多數用於缺乏足夠測試,或者缺乏可靠測試,或者對新版本的穩定性缺少信心的狀況下。把一部分用戶切到新版上來,而後看一下有沒有問題。若是沒有問題就繼續擴大升級,直到所有升級完成。

A/B 測試

Service Mesh - Istio流量控制篇(上)

AB 測試和藍綠部署或是金絲雀灰度部署徹底是不同的。AB 測試是同時上線兩個版本,而後作相關的比較。它是用來測試應用功能表現的方法,例如可用性、受歡迎程度、可見性等。

藍綠部署是爲了避免停機,灰度部署是對新版本的質量沒信心。而 AB 測試是對新版的功能沒信心。注意,一個是質量,一個是功能。

好比,網站 UI 大改版,推薦算法的更新,流程的改變,咱們不知道新的版本否會獲得用戶青睞或是能獲得更好的用戶體驗,咱們須要收集必定的用戶數據才能知道。

因而咱們須要在生產線上發佈兩個版本,拉一部分用戶過來當小白鼠,而後經過科學的觀測得出來相關的結論。AB 測試旨在經過科學的實驗設計、採樣樣本表明性、流量分割與小流量測試等方式來得到具備表明性的實驗結論,並確信該結論在推廣到所有流量時可信。

咱們能夠看到 AB 測試,其包含了灰度發佈的功能。也就是說,咱們的觀測若是隻是觀測有沒有 bug,那就是灰度發佈了。固然,若是咱們複雜一點,要觀測用戶的一些數據指標,這徹底也可能作成自動化的,若是新版本數據好,就自動化地切一點流量過來,若是不行,就換一批用戶(樣本)再試試。

對於灰度發佈或是 AB 測試可使用下面的技術來選擇用戶:

  • 瀏覽器 cookie、查詢參數、地理位置。技術支持,如瀏覽器版本、屏幕尺寸、操做系統等。客戶端語言

實踐基於權重的路由

在Istio中咱們能夠配置基於權重的路由,將請求按比例路由到對應的服務版原本實現灰度發佈的效果。接下來咱們利用 reviews 服務的多版本,模擬灰度發佈。官方demo已經提供了該配置文件,執行以下命令應用便可:

[root@m1 ~]# kubectl apply -f /usr/local/istio-1.8.1/samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
virtualservice.networking.istio.io/reviews configured
[root@m1 ~]#

virtual-service-reviews-50-v3.yaml 文件的內容以下,就是經過 Virtual Service 配置了權重:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 50   # 權重配置,表示50%的流量轉發到v1版本
    - destination:
        host: reviews
        subset: v3
      weight: 50   # 表示50%的流量轉發到v3版本

此時到應用頁面上進行一下測試,能夠發現請求基本按照50%的比例轉發到v1和v3版本:
Service Mesh - Istio流量控制篇(上)
Service Mesh - Istio流量控制篇(上)


下篇:

相關文章
相關標籤/搜索