原文連接: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
以 Bookinfo 應用爲示例,它由四個單獨的微服務構成,用來演示多種 Istio 特性。這個應用模仿在線書店的一個分類,顯示一本書的信息。頁面上會顯示一本書的描述,書籍的細節(ISBN、頁數等),以及關於這本書的一些評論。api
Bookinfo 應用分爲四個單獨的微服務:瀏覽器
productpage
:productpage
微服務會調用 details
和 reviews
兩個微服務,用來生成頁面。details
:這個微服務包含了書籍的信息。reviews
:這個微服務包含了書籍相關的評論。它還會調用 ratings 微服務。ratings
:ratings
微服務中包含了由書籍評價組成的評級信息。reviews
微服務有 3 個版本:bash
ratings
服務。ratings
服務,並使用 1 到 5 個黑色星形圖標來顯示評分信息。ratings
服務,並使用 1 到 5 個紅色星形圖標來顯示評分信息。下圖展現了這個應用的端到端架構。架構
Bookinfo 是一個異構應用,幾個微服務是由不一樣的語言編寫的。這些服務對 Istio 並沒有依賴,可是構成了一個有表明性的服務網格的例子:它由多個服務、多個語言構成,而且 reviews
服務具備多個版本。app
要在 Istio 中運行這一應用,無需對應用自身作出任何改變。咱們只要簡單的在 Istio 環境中對服務進行配置和運行,具體一點說就是把 Envoy sidecar 注入到每一個服務之中。這個過程所需的具體命令和配置方法由運行時環境決定,而部署結果較爲一致,以下圖所示:負載均衡
全部的微服務都和 Envoy sidecar 集成在一塊兒,被集成服務全部的出入流量都被 sidecar 所劫持,這樣就爲外部控制準備了所需的 Hook,而後就能夠利用 Istio 控制平面爲應用提供服務路由、遙測數據收集以及策略實施等功能。
接下來能夠根據 Istio 的運行環境,按照下面的講解完成應用的部署。
進入 Istio 安裝目錄。
啓動應用容器:
$ kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml)
複製代碼
istioctl kube-inject 命令用於在在部署應用以前修改 bookinfo.yaml
kubectl
就能完成服務的部署。$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
複製代碼
上面的命令會啓動所有的四個服務,其中也包括了 reviews
服務的三個版本(v1
、v2
以及 v3
)
給應用定義 Ingress gateway:
$ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
複製代碼
確認全部的服務和 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
複製代碼
肯定 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}}')
複製代碼
設置 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 來控制版本的路由。
因爲 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 文件提到的兩個新概念:VirtualService
和 DestinationRule
。
過去的路由分配比較簡單,使用標籤便可。新的版本中,提出了 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 示例中建立的路由規則表示:
能夠看到,match
中再也不包含 source
,這裏使用標籤來過濾。寫完應用以後,咱們再次訪問 Bookinfo 應用程序的 URL (http://$GATEWAY_URL/productpage
),會發現並無生效。這是由於,在 v3 版本的 API 中,目標規則再也不是透明瞭,路由定義必須以目標策略爲基礎。
所以這裏須要定義一個 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 設置等。
host
能夠包含通配符前綴,以容許單個規則應用於多個服務。subsets
(例如:命名版本)。 這些 subset 用於 VirtualService
的路由規則設置中,能夠將流量導向服務的某些特定版本。經過這種方式爲版本命名後,能夠在不一樣的虛擬服務中明確地引用這些命名版本的 subset,簡化 Istio 代理髮出的統計數據,並能夠將 subsets 編碼到 SNI 頭中。如今再次訪問 Bookinfo 應用程序的 URL (http://$GATEWAY_URL/productpage
),會發現規則已經生效了。
$ 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的實現,你須要刷新頁面不少次才能看到接近規則配置的機率分佈。
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
而看不到星標評分。
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 頁面,你均可以看到帶紅色星標評分的評論了。