天天看點

Istio 在阿裡雲容器服務的部署及流量治理實踐

目标

  • 在阿裡雲容器服務 Kubernetes 叢集上部署 Istio 服務網格
  • 實踐灰階釋出、故障注入、熔斷等 Istio 流量管理特性

準備工作

  1. 安裝和設定 kubectl 用戶端,請參考不同的作業系統,如果已經安裝請忽略:
  • macOS
curl -LO https://kubectl.oss-cn-hangzhou.aliyuncs.com/macos/kubectl
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
kubectl --help           
  • Linux
curl -LO https://kubectl.oss-cn-hangzhou.aliyuncs.com/linux/kubectl
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
kubectl --help           
  • Windows

https://kubectl.oss-cn-hangzhou.aliyuncs.com/windows/kubectl.exe

放到系統PATH路徑下

kubectl --help           

配置 kubectl 連接配接 Kubernetes 叢集的配置,可參考文檔

通過kubectl連接配接Kubernetes叢集

實驗步驟

部署Istio

  • 登入容器服務控制台,在叢集清單中選擇一個叢集,打開更多 - 部署 Istio
    Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 保持預設配置,點選"部署 Istio"
    Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 等待完成後,Istio 已經成功部署在 Kubernetes 叢集中
  • 使用 kiali 檢視服務網格可視化
kubectl port-forward -n istio-system "$(kubectl get -n istio-system pod --selector=app=kiali -o jsonpath='{.items..metadata.name}')" 20001           

在本地浏覽器中通路

http://localhost:20001

,使用預設賬戶 admin/admin 登入

灰階釋出

  • 建立命名空間并開啟 Sidecar 自動注入:單擊左側導航欄中的叢集 > 命名空間,進入指令空間頁面,建立一個名稱為

    demo

    的命名空間,并為其添加一個

    istio-injection:enabled

    的标簽
    Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 單擊左側導航欄中服務網格 > 虛拟服務,進入虛拟服務(Virtual Service)頁面,點選建立,建立一個簡單的示例應用,指定應用名稱為

    istio-app

    ,指定應用版本為

    v1

    ,選擇剛剛建立的命名空間

    demo

    Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 配置應用容器,使用如下鏡像:

    registry.cn-beijing.aliyuncs.com/test-node/node-server:v1

    Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 配置服務,服務名稱為

    istio-app-svc

    ,類型為虛拟叢集 IP ,服務端口和容器端口均為8080
    Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 送出應用配置,将會自動建立 Deployment、Service、DestinationRule、VirtualService
    Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 單擊導航欄中的應用 > 容器組,确認所有的 Pod 都已經正确的定義和啟動
    Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 建立服務用戶端測試應用
kubectl apply -n demo -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: sleep
  labels:
    app: sleep
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: sleep
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: sleep
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sleep
    spec:
      containers:
      - name: sleep
        image: registry.cn-hangzhou.aliyuncs.com/aliacs/curl
        command: ["/bin/sleep", "3650d"]
        imagePullPolicy: IfNotPresent
EOF           
  • 在測試應用的 Pod 中通路 Istio 應用:登入到 sleep 應用的 Pod 中
kubectl exec -it -n demo "$(kubectl get -n demo pod --selector=app=sleep -o jsonpath='{.items..metadata.name}')" sh           

執行如下指令調用之前部署的 Istio 應用:

for i in `seq 1000`
do
curl http://istio-app-svc.demo:8080;
echo '';
sleep 1;
done;           

可以看到傳回的資訊:

Hello from v1
Hello from v1
Hello from v1           
  • 單擊左側導航欄中服務網格 > 虛拟服務,進入虛拟服務(Virtual Service)頁面,找到

    istio-app-svc

    服務,點選管理,在版本管理中,點選增加灰階版本,新的版本指定為

    v2

Istio 在阿裡雲容器服務的部署及流量治理實踐

在容器配置中使用以下鏡像:

registry.cn-beijing.aliyuncs.com/test-node/node-server:v2

Istio 在阿裡雲容器服務的部署及流量治理實踐

在灰階政策中選擇基于流量比例釋出,流量比例 50%

Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 送出灰階釋出後,檢視 sleep 應用的調用結果,可以看到,

    v1

    v2

    版本的傳回結果
Hello from v1
Hello from v2
Hello from v1
Hello from v1
Hello from v2
Hello from v1           
  • 在 kiali 中檢視,可以确認,調用被分發到兩個版本中
Istio 在阿裡雲容器服務的部署及流量治理實踐

故障注入

  • 目前應用工作正常,我們為 istio-app-svc 注入故障,以測試整個應用的彈性。在 istio-app-svc 的管理界面中,打開故障注入政策,選擇注入中斷故障,百分比 50%,狀态碼 503
Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 送出後,繼續檢視 sleep 應用的調用結果,即可看到 istio-app-svc 服務約有 50% 的機率無法通路,輸出

    fault filter abort

Hello from v1
Hello from v1
Hello from v1
fault filter abort
fault filter abort
fault filter abort
Hello from v1
Hello from v2
fault filter abort
Hello from v2
Hello from v2           

同時,在 kiali 可視化界面中,也可以看到 sleep 服務對 istio-app-svc 服務的調用有 50% 左右的失敗比例

Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 除此之外,我們也可以為服務注入時延故障,例如在上述界面中,選擇時延故障,為 50% 的請求添加 5s 的時延
Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 确認送出之後,我們可以看到,部分調用的耗時顯著增加。在 kiali 中也可以檢視調用的平均請求耗時
Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 删除故障注入政策和灰階版本

    v2

Istio 在阿裡雲容器服務的部署及流量治理實踐

熔斷

當一個服務出現故障或者延遲增大時,如果不采取措施,問題可能會逐漸傳導到其他服務,導緻整個應用癱瘓。在這個場景下,我們可以通過為服務調用配置熔斷規則,來隔離故障。

在這一部分,我們為上述 istio-app-svc 服務配置連接配接池限制,使其具備熔斷能力。

  • 使用 kubectl,在 DestinationRule 中設定熔斷規則:
kubectl delete destinationrule -n demo istio-app-svc
kubectl apply -n demo -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: istio-app-svc
spec:
  host: istio-app-svc
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
  subsets:
  - labels:
      version: v1
    name: v1
EOF           
  • 部署一個 HTTP 用戶端,用于負載測試
kubectl apply -n demo -f https://istio-demo.oss-cn-hangzhou.aliyuncs.com/yaml/fortio-deploy.yaml           
  • 首先使用用戶端發出 100 個 HTTP 請求,并發數為 1
FORTIO_POD=$(kubectl -n demo get pod | grep fortio | awk '{ print $1 }')
kubectl -n demo exec -it $FORTIO_POD  -c fortio /usr/bin/fortio -- load -c 1 -qps 0 -n 100 -loglevel Warning http://istio-app-svc:8080           

此時所有的請求都成功傳回,沒有觸發熔斷,符合我們配置的連接配接池參數。

Code 200 : 100 (100.0 %)           
  • 在上面的熔斷設定中指定了

    maxConnections: 1

    以及

    http1MaxPendingRequests: 1

    。這意味着如果超過了一個連接配接同時發起請求,Istio 就會熔斷,阻止後續的請求或連接配接。是以我們以并發數為 3,發出 100 個請求:
FORTIO_POD=$(kubectl -n demo get pod | grep fortio | awk '{ print $1 }')
kubectl -n demo exec -it $FORTIO_POD  -c fortio /usr/bin/fortio -- load -c 3 -qps 0 -n 100 -loglevel Warning http://istio-app-svc:8080           

從結果中,可以看到,有超過 40% 的請求被 Istio 阻斷了。

Code 200 : 57 (57.0 %)
Code 503 : 43 (43.0 %)
Response Header Sizes : count 100 avg 130.53 +/- 113.4 min 0 max 229 sum 13053
Response Body/Total Sizes : count 100 avg 242.14 +/- 0.9902 min 241 max 243 sum 24214
All done 100 calls (plus 0 warmup) 0.860 ms avg, 2757.6 qps           

在 kiali 中觀察可以發現,這部分請求并沒有真正到達 istio-app-svc 的 Pod

Istio 在阿裡雲容器服務的部署及流量治理實踐
  • 通過查詢 istio-proxy 的狀态,可以獲得更多資訊,

    upstream_rq_pending_overflow

    的值即為被熔斷政策阻止的請求數
kubectl -n demo exec -it $FORTIO_POD -c istio-proxy -- sh -c 'curl localhost:15000/stats' | grep istio-app-svc | grep pending

cluster.outbound|8080|v1|istio-app-svc.demo-ab.svc.cluster.local.upstream_rq_pending_active: 0
cluster.outbound|8080|v1|istio-app-svc.demo-ab.svc.cluster.local.upstream_rq_pending_failure_eject: 0
cluster.outbound|8080|v1|istio-app-svc.demo-ab.svc.cluster.local.upstream_rq_pending_overflow: 99
cluster.outbound|8080|v1|istio-app-svc.demo-ab.svc.cluster.local.upstream_rq_pending_total: 199           

清理實驗環境

執行以下指令:

kubectl delete ns demo