1. 程式人生 > 實用技巧 >istio-http流量管理

istio-http流量管理

1. 定義目標與規則
istio 服務網格中對服務進行了進一步抽象:
可以使用 Pod 標籤對具體的服務程序進行分組;
可以定義服務的負載均衡策略;
可以為服務指定 TLS 要求;
可以為服務設定連線池大小。
istio 中,同一服務不同組別的後端被稱為 子集(Subset) ,也經常被稱為 服務版本 。
在 istio 中,建議為每個網格都設定明確的目標訪問規則,在通過 istio 流量控制之後,會選擇明確的子集,根據規則或在子集中規定的流量策略來進行訪問,
這種規則被稱為 DestinationRule ,樣例如下:

cat flaskapp-destinationrule.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: flaskapp
spec:
  host: flaskapp.default.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      simple: LEAST_CONN
  subsets:
  - name: v1
    labels:
      version: v1
    trafficPolicy:
      loadBalancer: ROUND_ROBIN
  - name: v2
    labels:
      version: v2

規則需要注意的地方如下:
host: 必要欄位,代表1個 Service 資源,或1個 ServiceEntry 定義的外部服務。
建議:為防止不同名稱空間服務重名,可以使用完全限定名。
trafficPolicy: 流量策略,在 DestinationRule 與 Subset 都可以定義,Subset 中的級別更高。
subsets: 該欄位使用標籤選擇器定義不同的子集。
2. 定義預設路由
2.1 定義預設路由
建議每個服務都建立1個預設路由,在沒有特定的路由規則時,使用預設路由規則訪問指定子集,一以此確保服務在預設情況下的行為穩定性,樣例如下:

cat flaskapp-default-vs.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: flaskapp
spec:
  hosts:
  - flaskapp.default.svc.cluster.local
  http:
  - route:
    - destination:
        host: flaskapp.default.svc.cluster.local
        subset: v1

VirtualService: istio 流量控制過程中的樞紐,負責對流量進行甄別與轉發。
針對主機名工作,但 hosts 欄位是一個數組內容,可以針對多個主機名進行工作。
可以為多種協議的流量提供服務,如 http ,tcp ,tls等。
在 http 的下一級,即具體的路由規則。
支援多條路由。
2.2 驗證
# 應用目標規則與預設路由

kubectl apply -f flaskapp-destinationrule.yaml
kubectl apply -f flaskapp-default-vs.yaml

# 驗證,可同步觀察 kiali & Jaeger 等

kubectl exec -it -c sleep $(kubectl get pod -l app=sleep,version=v1 -o jsonpath='{.items..metadata.name}') /bin/bash
bash-4.4# for i in `seq 100` ; do http --body http://flaskapp.default/env/version ; done

2.3 總結
在 istio 中部署1個業務應用時,建議:

使用 app 標籤表明應用身份;
使用 version 標籤表明應用版本;
建立目標規則;
建立預設路由規則,預設路由得配置清單應該成為服務網格環境下的必要部署內容。
3. 流量拆分與遷移
3.1 權重

cat flaskapp-default-vs.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: flaskapp
spec:
  hosts:
  - flaskapp.default.svc.cluster.local
  http:
  - route:
    - destination:
        host: flaskapp.default.svc.cluster.local
        subset: v1
      weight: 70
    - destination:
        host: flaskapp.default.svc.cluster.local
        subset: v2
      weight: 30
      
# 應用
kubectl apply -f flaskapp-default-vs.yaml

# 驗證,可同步觀察 kiali & Jaeger 等
# 因是權重的原因,驗證時樣本量需要大一些

kubectl exec -it -c sleep $(kubectl get pod -l app=sleep,version=v1 -o jsonpath='{.items..metadata.name}') /bin/bash
bash-4.4# for i in `seq 100` ; do http --body http://flaskapp.default/env/version ; done | awk -F "v1" '{print NF-1}'

注意點:

流量分配是有權重的,且權重總和必須是 100 ;
如果不顯示宣告權重,則預設值是 100 。
3.2 獲取 istio 物件
kubectl get , kubectl api-resources 列出當前叢集支援的所有物件型別
Kiali --> Istio Config

4. 金絲雀部署
金絲雀部署:在釋出新版本時,部署的新版本並不對外開放,而選擇一小部分使用者為測試目標,這部分使用者對服務的訪問會指向特定的版本,通過對這些金絲雀使用者的使用情況的觀察,來確定新版本服務的釋出效果,在確定結果之前,所有其他使用者都繼續使用原有版本。

4.1 金絲雀部署

cat flaskapp-default-vs-canary.yaml 
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: flaskapp
spec:
  hosts:
  - flaskapp.default.svc.cluster.local
  http:
  - match:
    - headers:
        lab:
          exact: canary
    route:
    - destination:
        host: flaskapp.default.svc.cluster.local
        subset: v2
  - route:
    - destination:
        host: flaskapp.default.svc.cluster.local
        subset: v1

注意點:
match 欄位提供來豐富的匹配功能,匹配範圍不僅包括 http header , 還包含 uri , scheme , method , authority , 埠 , 來源標籤及 gateway 等;
exact 代表完全匹配,另有 prefix 代表字首, regex 代表正則表示式的匹配方式
4.2 驗證

bash-4.4# for i in `seq 10` ; do http --body http://flaskapp.default/env/version lab:canary ; done

5. 根據來源服務進行路由

cat flaskapp-default-vs-src.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: flaskapp
spec:
  hosts:
  - flaskapp.default.svc.cluster.local
  http:
  - match:
    - sourceLabels:
        app: sleep
        version: v1
    route:
    - destination:
        host: flaskapp.default.svc.cluster.local
        subset: v1
  - route:
    - destination:
        host: flaskapp.default.svc.cluster.local
        subset: v2
# 應用
kubectl apply -f flaskapp-default-vs-src.yaml

測試
# 驗證
# sleep v1

kubectl exec -it -c sleep $(kubectl get pod -l app=sleep,version=v1 -o jsonpath='{.items..metadata.name}') /bin/bash
bash-4.4# for i in `seq 10` ; do http --body http://flaskapp.default/env/version; done

# sleep v2

kubectl exec -it -c sleep $(kubectl get pod -l app=sleep,version=v2 -o jsonpath='{.items..metadata.name}') /bin/bash
bash-4.4# for i in `seq 10` ; do http --body http://flaskapp.default/env/version; done

6. 對URI進行重定向
6.1 redirect

cat flaskapp-default-vs-uri.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: flaskapp
spec:
  hosts:
  - flaskapp.default.svc.cluster.local
  http:
  - match:
    - sourceLabels:
        app: sleep
        version: v1
      uri:
        exact: "/env/HOSTNAME"
    redirect:
      uri: "/env/version"
  - route:
    - destination:
        host: flaskapp.default.svc.cluster.local
        subset: v2

# 應用
kubectl apply -f flaskapp-default-vs-uri.yaml

測試
# 驗證 sleep v2,正常返回

kubectl exec -it -c sleep $(kubectl get pod -l app=sleep,version=v2 -o jsonpath='{.items..metadata.name}') -- \
http http://flaskapp.default/env/HOSTNAME

HTTP/1.1 200 OK
content-length: 28
content-type: text/html; charset=utf-8
date: Wed, 12 Jun 2019 08:05:25 GMT
server: envoy
x-envoy-upstream-service-time: 1

flaskapp-v2-59b5b6cb94-jdfp4

# 驗證 sleep v1
# 返回 "301" 重定向程式碼

kubectl exec -it -c sleep $(kubectl get pod -l app=sleep,version=v1 -o jsonpath='{.items..metadata.name}') -- \
http http://flaskapp.default/env/HOSTNAME

HTTP/1.1 301 Moved Permanently
content-length: 0
date: Wed, 12 Jun 2019 08:06:17 GMT
location: http://flaskapp.default/ev/version
server: envoy

# "--follow" 跟隨重定向指令,重驗證

kubectl exec -it -c sleep $(kubectl get pod -l app=sleep,version=v1 -o jsonpath='{.items..metadata.name}') -- \
http --follow http://flaskapp.default/env/HOSTNAME

HTTP/1.1 200 OK
content-length: 2
content-type: text/html; charset=utf-8
date: Wed, 12 Jun 2019 08:09:26 GMT
server: envoy
x-envoy-upstream-service-time: 2

v2
注意點:
redirect 指令會把 URI 整體替換,靈活性不高;
301 指令無法支援 Post 方法, istio 提供了 rewrite 方式來提供這種在呼叫前進行 URI 重寫的支援。
6.2 rewrite

cat httpbin-default-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - httpbin.default.svc.cluster.local
  http:
  - match:
    - uri:
      exact: "/get"
    rewrite:
      uri: "/post"
    route:
    - destination:
        host: httpbin.default.svc.cluster.local
  - route:
    - destination:
        host: httpbin.default.svc.cluster.local

測試
# 訪問測試

kubectl exec -it -c sleep $(kubectl get pod -l app=sleep,version=v2 -o jsonpath='{.items..metadata.name}') -- http -f POST http://httpbin:8000/get data=nothing

# 返回資訊
HTTP/1.1 405 Method Not Allowed
access-control-allow-credentials: true
access-control-allow-origin: *
allow: GET, OPTIONS, HEAD
content-length: 178
content-type: text/html
date: Wed, 12 Jun 2019 12:39:28 GMT
server: envoy
x-envoy-upstream-service-time: 5

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>405 Method Not Allowed</title>
<h1>Method Not Allowed</h1>
<p>The method is not allowed for the requested URL.</p>
注意點:
rewrite 方法與 redirect 方法的不同之處在於: 在 rewrite 方法的 match 欄位必須包含對目標的定義;
rewrite 方法與 redirect 方法不能共存。

轉載於:

https://www.cnblogs.com/netonline/p/12609021.html
https://www.cnblogs.com/netonline/p/13237722.html

如有侵權請聯絡刪除