天天看點

istio 三日談之二,路由規則

路由控制是 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      

繼續閱讀