路由這個功能是流量控制裏面很是重要,也是最經常使用的一個功能。在Istio裏通常經過Virtual Service(虛擬服務)以及Destination Rule(目標規則)這兩個API資源進行動態路由的設置。nginx
虛擬服務(Virtual Service):web
目標規則(Destination Rule):算法
在上一篇Service Mesh - Istio安裝與部署文章中,咱們演示了BookInfo這個Demo應用的部署,而且能夠發現其中的 reviews 服務共有三個不一樣的版本。如今咱們的需求是將請求路由到 reviews 服務的指定版本上。例如,路由到版本1上,以下圖:
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 服務:
緩存
那麼配置是如何生效的呢?咱們先來看看這兩個API資源它們的一些具體配置項:
安全
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資源的一些配置選項:
建立 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:
而後應用配置文件,建立咱們所定義的網關和虛擬服務:
[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 ~]#
經過網關和虛擬服務暴露接口後,再從新訪問一下該接口,能夠看到能正常訪問了:
一樣,health
接口也能夠被訪問到:
Gateway 的應用場景:
官方文檔:
什麼是服務入口(ServiceEntry):
接下來咱們實踐一下,將 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 ~]#
服務入口的配置選項:
官方文檔:
藍綠部署簡單理解就是當須要部署新版本時,不會去動老版本的服務,而是在另外一個環境部署相同數量的新服務,而後當新的服務測試確認 OK 後,把流量切到新的服務這邊來。
其實這種部署方式,就是咱們說的預發環境。生產線上有兩套相同的集羣,一套是 Prod 是真實服務的,另外一套是 Stage 是預發環境,發佈發 Stage,而後把流量切到 Stage 這邊,因而 Stage 就成了 Prod,而以前的 Prod 則成了 Stage。有點像換頁似的。
這種方式的優勢是沒有停機,實時發佈和升級,也避免有新舊版本同時在線的問題。但這種部署的問題就是有點浪費,由於須要使用雙倍的資源(不過,這只是在物理機時代,在雲計算時代沒事,由於虛擬機部署完就能夠釋放了)。
另外,若是咱們的服務中有狀態,好比一些緩存什麼的,停機部署和藍綠部署都會有問題。
金絲雀部署又叫灰度部署,其得名來源於礦井中的金絲雀。17 世紀,英國礦井工人發現,金絲雀對瓦斯這種氣體十分敏感。空氣中哪怕有極其微量的瓦斯,金絲雀也會中止歌唱。而當瓦斯含量超過必定限度時,雖然魯鈍的人類毫無察覺,金絲雀卻早已毒發身亡。當時在採礦設備相對簡陋的條件下,工人們每次下井都會帶上一隻金絲雀做爲 」 瓦斯檢測指標 「,以便在危險情況下緊急撤離。
灰度部署是指逐漸將生產環境流量從老版本切換到新版本。一般流量是按比例分配的。例如 90% 的請求流向老版本,10% 的請求流向新版本。而後沒有發現問題,就逐步擴大新版本上的流量,減小老版本上的流量。
除了切流量外,對於多租戶的平臺,例如雲計算平臺,灰度部署也能夠將一些新的版本先部署到一些用戶上,若是沒有問題,擴大部署,直到所有用戶。通常的策略是,從內部用戶開始,而後是通常用戶,最後是大客戶。
這個技術大多數用於缺乏足夠測試,或者缺乏可靠測試,或者對新版本的穩定性缺少信心的狀況下。把一部分用戶切到新版上來,而後看一下有沒有問題。若是沒有問題就繼續擴大升級,直到所有升級完成。
AB 測試和藍綠部署或是金絲雀灰度部署徹底是不同的。AB 測試是同時上線兩個版本,而後作相關的比較。它是用來測試應用功能表現的方法,例如可用性、受歡迎程度、可見性等。
藍綠部署是爲了避免停機,灰度部署是對新版本的質量沒信心。而 AB 測試是對新版的功能沒信心。注意,一個是質量,一個是功能。
好比,網站 UI 大改版,推薦算法的更新,流程的改變,咱們不知道新的版本否會獲得用戶青睞或是能獲得更好的用戶體驗,咱們須要收集必定的用戶數據才能知道。
因而咱們須要在生產線上發佈兩個版本,拉一部分用戶過來當小白鼠,而後經過科學的觀測得出來相關的結論。AB 測試旨在經過科學的實驗設計、採樣樣本表明性、流量分割與小流量測試等方式來得到具備表明性的實驗結論,並確信該結論在推廣到所有流量時可信。
咱們能夠看到 AB 測試,其包含了灰度發佈的功能。也就是說,咱們的觀測若是隻是觀測有沒有 bug,那就是灰度發佈了。固然,若是咱們複雜一點,要觀測用戶的一些數據指標,這徹底也可能作成自動化的,若是新版本數據好,就自動化地切一點流量過來,若是不行,就換一批用戶(樣本)再試試。
對於灰度發佈或是 AB 測試可使用下面的技術來選擇用戶:
在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版本:
下篇: