istio 三日談之二,路由規則_Kubernetes中文社群
路由控制是 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