10 個 Istio 流量管理 最常用的例子,強(qiáng)烈建議收藏起來,以備不時之需。
為了方便理解,以Istio官方提供的Bookinfo應(yīng)用示例為例,引出 Istio 流量管理的常用例子。
Bookinfo應(yīng)用的架構(gòu)圖如下:

其中,包含四個單獨的微服務(wù):
-
productpage:調(diào)用details和reviews兩個服務(wù),用來生成頁面。 -
details:包含了書籍的信息。 -
reviews:包含了書籍相關(guān)的評論。它還會調(diào)用 ratings 微服務(wù)。 -
rating:包含了由書籍評價組成的評級信息。
其中,reviews 服務(wù)有 3 個版本:
- v1 版本不會調(diào)用
ratings服務(wù)。 - v2 版本會調(diào)用
ratings服務(wù),并使用 1 到 5 個黑色星形圖標(biāo)來顯示評分信息。 - v3 版本會調(diào)用
ratings服務(wù),并使用 1 到 5 個紅色星形圖標(biāo)來顯示評分信息。
流量轉(zhuǎn)移
目標(biāo)1:把
reviews服務(wù)的所有流量都路由到v1版本。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v3
name: v3
目標(biāo)2:把
reviews服務(wù)的50%流量轉(zhuǎn)移到v3版本。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 50
- destination:
host: reviews
subset: v3
weight: 50
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v3
name: v3
目標(biāo)3:把
reviews服務(wù)的所有流量都路由到v3版本。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v3
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v3
name: v3
基于用戶身份的路由
目標(biāo):來自名為 OneMore 的用戶的所有流量都路由到v2版本,其他流量都路由到v1版本。
Istio 對用戶身份沒有任何特殊的內(nèi)置機(jī)制。在應(yīng)用示例中,productpage服務(wù)在所有到 reviews 服務(wù)的 HTTP 請求中都增加了一個自定義的 end-user 請求頭,其值為用戶名。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: OneMore
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v3
name: v3
注入 HTTP 延遲故障
目標(biāo):用戶 OneMore 訪問時,
ratings服務(wù)注入一個 2 秒的延遲,productpage頁面在大約 2 秒鐘加載完成并且沒有錯誤。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
- headers:
end-user:
exact: OneMore
fault:
delay:
percentage:
value: 100.0
fixedDelay: 2s
route:
- destination:
host: ratings
subset: v1
- route:
- destination:
host: ratings
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: ratings
spec:
host: ratings
subsets:
- labels:
version: v1
name: v1
注入 HTTP 中止故障
目標(biāo):用戶 OneMore 訪問時,
ratings服務(wù)注入一個503的中止故障,productpage頁面能夠立即被加載,同時顯示 “Ratings service is currently unavailable” 這樣的消息。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
abort:
httpStatus: 503
percentage:
value: 100
match:
- headers:
end-user:
exact: OneMore
route:
- destination:
host: ratings
subset: v1
- route:
- destination:
host: ratings
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: ratings
spec:
host: ratings
subsets:
- labels:
version: v1
name: v1
設(shè)置請求超時
首先,用戶 OneMore 訪問時, ratings 服務(wù)注入一個 2 秒的延遲,productpage頁面在大約 2 秒鐘加載完成并且沒有錯誤。
按照上文注入 HTTP 延遲故障進(jìn)行操作,不再贅述。
目標(biāo):用戶 OneMore 訪問時,
reviews服務(wù)的請求超時設(shè)置為 1 秒,同時顯示 “Sorry, product reviews are currently unavailable for this book.” 這樣的消息。
kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: OneMore
route:
- destination:
host: reviews
subset: v2
timeout: 1s
- route:
- destination:
host: reviews
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v3
name: v3
在Jaeger可以看到具體的調(diào)用鏈如下:

設(shè)置請求重試
首先,用戶 OneMore 訪問時, ratings 服務(wù)注入一個 2 秒的延遲,productpage頁面在大約 2 秒鐘加載完成并且沒有錯誤。
按照上文注入 HTTP 延遲故障進(jìn)行操作,不再贅述。
目標(biāo):用戶 OneMore 訪問時,
reviews服務(wù)的請求重試次數(shù)為2次,重試超時時間為 0.5 秒,同時顯示 “Sorry, product reviews are currently unavailable for this book.” 這樣的錯誤消息。
kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: OneMore
route:
- destination:
host: reviews
subset: v2
retries:
attempts: 2
perTryTimeout: 0.5s
- route:
- destination:
host: reviews
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v3
name: v3
拒絕目標(biāo)IP的請求
目標(biāo):除了IP為
10.201.240.131的客戶端可以訪問/api/v1/products/1,其他客戶端拒絕請求。
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-by-ip
spec:
selector:
matchLabels:
app: productpage
action: DENY
rules:
- to:
- operation:
paths: ["/api/v1/products/1"]
when:
- key: remote.ip
notValues: ["10.201.240.131"]
熔斷
目標(biāo):設(shè)置
details服務(wù)的并發(fā)上限為1。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: details
spec:
host: details
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
可以使用 Fortio 進(jìn)行負(fù)載測試,發(fā)送并發(fā)數(shù)為 2 的連接(-c 2),請求 20 次(-n 20):
kubectl exec fortio-deploy-684b6b47f8-tzsg8 -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 20 -loglevel Warning http://details:9080/details/0
其中,fortio-deploy-684b6b47f8-tzsg8是Fortio的Pod名稱,效果如下:

流量鏡像
目標(biāo):把流量全部路由到reviews服務(wù)的 v2 版本,再把流量全部鏡像到 v3 版本。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
mirror:
host: reviews
subset: v3
mirrorPercentage:
value: 100.0
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v3
name: v3
執(zhí)行如下命令查看reviews服務(wù) v3 版本的 Envoy 訪問日志:
kubectl logs -l app=reviews,version=v3 -c istio-proxy
可以看到reviews服務(wù) v3 版本被調(diào)用的日志:
{
"authority": "reviews-shadow:9080",
"bytes_received": 0,
"bytes_sent": 375,
"connection_termination_details": null,
"downstream_local_address": "10.1.1.64:9080",
"downstream_remote_address": "10.1.1.59:0",
"duration": 1914,
"method": "GET",
"path": "/reviews/0",
"protocol": "HTTP/1.1",
"request_id": "b79cefe6-1277-9c39-b398-f94a704840cc",
"requested_server_name": "outbound_.9080_.v3_.reviews.default.svc.cluster.local",
"response_code": 200,
"response_code_details": "via_upstream",
"response_flags": "-",
"route_name": "default",
"start_time": "2022-06-27T07:34:19.129Z",
"upstream_cluster": "inbound|9080||",
"upstream_host": "10.1.1.64:9080",
"upstream_local_address": "127.0.0.6:59837",
"upstream_service_time": "1913",
"upstream_transport_failure_reason": null,
"user_agent": "curl/7.79.1",
"x_forwarded_for": "10.1.1.59"
}
Ingress的路由
目標(biāo):請求頭
app-id為details的所有流量都路由到details服務(wù)中。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- '*'
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
- match:
- headers:
app-id:
exact: details
route:
- destination:
host: details
port:
number: 9080
使用curl命令驗證一下:
curl -H "app-id: details" -v http://127.0.0.1/details/2
返回結(jié)果如下:
* Trying 127.0.0.1:80...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET /details/2 HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.79.1
> Accept: */*
> app-id: details
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-type: application/json
< server: istio-envoy
< date: Tue, 28 Jun 2022 07:14:40 GMT
< content-length: 178
< x-envoy-upstream-service-time: 4
<
{"id":2,"author":"William Shakespeare","year":1595,"type":"paperback","pages":200,"publisher":"PublisherA","language":"English","ISBN-10":"1234567890","ISBN-13":"123-1234567890"}
* Connection #0 to host 127.0.0.1 left intact
返回結(jié)果可以看出,訪問的是details服務(wù)。
最后,感謝你這么帥,還給我點贊。