1. 程式人生 > >istio 三日談之二,路由規則_Kubernetes中文社群

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