路由控制是 istio 的最常用功能了,經過前面的準備,我們已經基本可以進行這些内容的嘗試了。
注意下面的路由規則都忽略了對來源的過濾,會顯得比較呆闆或者說沒用,但是在加入過濾條件之後,就完全不可同日而語了。具體的過濾規則的寫法可以參考官方文檔或者 istio 中的 bookinfo 執行個體。
建立 frontend-v2
為了展示路由配置設定的能力,我們首先建立一個名為frontend-v2的Deployment,這個deploy跟之前的 v1 共享同一個 PVC,也就是共享同一套頁面。利用環境變量來控制輸出。
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: frontend-v2
spec:
replicas: 1
template:
metadata:
labels:
name: frontend
version: "2"
spec:
containers:
- name: php
image: 10.211.55.86:5000/php:7.1.7-apache
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- name: wwwroot
mountPath: /var/www/html
env:
- name: "SERVICE_VERSION"
value: "2"
volumes:
- name: wwwroot
persistentVolumeClaim:
claimName: frontend-v1
同前面的 v1 一樣,這個Deployment也需要使用istioctl kube-inject進行注入,最後使用kubectl apply -f 運作。
流量配置設定
首先建立如下路由規則
default.yaml
type: route-rule
name: frontend-default
spec:
destination: svc-frontend.default.svc.cluster.local
precedence: 1
route:
- tags:
version: "2"
weight: 100
- destination:必須是服務的 fqdn
- precedence:整數,優先級,越大越先
- route:數組
- tag:Pod 的标簽選擇器。
- weigh: 整數,權重,配置設定到目前路由的比率。
建立之後,使用istioctl create -f default.yaml,建立這一規則。接下來我們使用kubectl exec -it進入 tool pod 進行測試:
$ curl svc-frontend/index.php
-----------------------------
From: frontend-797054967-r12m5
Version: 1
傳回内容表明這一服務調用的是最初的 v1 版本的 frontend。
接下來修改 default.yaml 的version “1”為version “2”,然後用istioctl replace -f default.yaml更新路由規則。再次驗證:
$ curl svc-frontend/index.php
-----------------------------
From: frontend-v2-90739004-xpmrn
Version: 2
這裡可以看到,這一響應來自于 v2 版本的 Pod,并且傳回的版本号也是 2。
然後我們再次修改路由規則,測試一下路由配置設定:
type: route-rule
name: frontend-default
spec:
destination: svc-frontend.default.svc.cluster.local
precedence: 1
route:
- tags:
version: "2"
weight: 10
- tags:
version: "1"
weight: 90
根據上面的路由規則,對 svc-frontend 這一服務的通路,應該有 10% 流量分給版本 2,其餘的 90% 配置設定給了版本 1。我們在 tool pod 中使用如下腳本測試這一配置設定:
#!/bin/bash
for i in {1..100}
do
curl -s svc-frontend/index.php | grep Version
done
執行效果:
$ ./curl.batch.sh | grep 2 | wc -l
10
可以看到,完全符合之前我們的路由設定。
逾時政策
為了保障服務品質,我們有時會要求對某些服務的傳回時間進行限制
前面提到,我們生成了一個delay.php,用于進行延時測試,檔案内容如下:
<?php
header("Content-type: text/plain");
sleep(4);
echo "\n-----------------------------\n";
echo "\nFrom: ".gethostname()."\n";
echo "Version: ".$_ENV['SERVICE_VERSION']."\n";
正常執行time curl -s svc-frontend/delay.php,會傳回如下結果:
-----------------------------
From: frontend-797054967-r12m5
Version: 1
real 0m4.025s
user 0m0.005s
sys 0m0.004s
我們在這裡加入一個政策,兩秒逾時:
type: route-rule
name: front-timeout
spec:
destination: svc-frontend.default.svc.cluster.local
precedence: 9
route:
- tags:
version: "1"
httpReqTimeout:
simpleTimeout:
timeout: 2s
再次測試,則會傳回逾時的結果:
upstream request timeout
real 0m2.015s
user 0m0.006s
sys 0m0.003s
重試政策
在服務逾時的時候,我們可能會希望請求自動重試。
這一測試要求保留前面的逾時政策,以便形成失敗結果:
政策檔案如下:
type: route-rule
name: front-timeout
spec:
destination: svc-frontend.default.svc.cluster.local
precedence: 9
route:
- tags:
version: "1"
httpReqRetries:
simpleRetry:
attempts: 3
perTryTimeout: 2s
這裡表示每次嘗試的逾時時間是兩秒,重試三次。使用 curl 測試:
$ time curl -s svc-frontend/delay.php
upstream request timeout
real 0m8.136s
user 0m0.005s
sys 0m0.006s
時間為 8 秒,相當于四次逾時的時間。
Rewrite
和反向代理的情況類似,有時我們需要對進入服務的 URL 進行重寫,下面的路由政策會将 /front 替換為 / 進行通路:
type: route-rule
name: front-timeout
spec:
destination: svc-frontend.default.svc.cluster.local
precedence: 9
match:
httpHeaders:
uri:
prefix: "/front/"
rewrite:
uri: "/"
route:
- tags:
version: "1"
注意這裡對uri的操作,是使用 rewrite 中的 uri 替換 match 中的 uri,二者的對應關系是強制的。
在 tool 裡面進行測試通路:
$ curl http://svc-frontend/front/index.php
-----------------------------
From: frontend-797054967-r12m5
Version: 1
故障注入
微服務測試過程中,能夠自動生成一些錯誤,無疑是個很有幫助的事情。目前 istio 支援兩種故障的模拟:時延和中斷
時延
下面的規則會為每個對該服務的請求都生成 7 秒的時延:
type: route-rule
name: fdelay
spec:
destination: svc-frontend.default.svc.cluster.local
precedence: 9
route:
- tags:
version: "1"
httpFault:
delay:
percent: 100
fixedDelay: 7s
- percent: 産生時延的比例
- fixedDelay: 時間
使用 curl 驗證,可以看到的确多出了 7 秒的處理時間。
$ time curl -s http://svc-frontend/index.php
-----------------------------
From: frontend-797054967-r12m5
Version: 1
real 0m7.028s
user 0m0.007s
sys 0m0.003s
中斷
這一功能可以模拟服務中斷的情景,下面的 yaml 定義了該服務 100% 會傳回 403 錯誤。
type: route-rule
name: fdelay
spec:
destination: svc-frontend.default.svc.cluster.local
precedence: 9
route:
- tags:
version: "1"
httpFault:
abort:
percent: 100
httpStatus: 403
curl 的驗證結果如下:
$ curl -v svc-frontend/error.php
* Connected to svc-frontend (10.100.186.68) port 80 (#0)
> GET /error.php HTTP/1.1
> User-Agent: curl/7.38.0
> Host: svc-frontend
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< date: Fri, 28 Jul 2017 01:27:52 GMT
* Server envoy is not blacklisted
< server: envoy
< content-length: 0
<
* Connection #0 to host svc-frontend left intact