目标
- 在阿裡雲容器服務 Kubernetes 叢集上部署 Istio 服務網格
- 實踐灰階釋出、故障注入、熔斷等 Istio 流量管理特性
準備工作
- 安裝和設定 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 在阿裡雲容器服務的部署及流量治理實踐 - 配置服務,服務名稱為
,類型為虛拟叢集 IP ,服務端口和容器端口均為8080istio-app-svc
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
在容器配置中使用以下鏡像:
registry.cn-beijing.aliyuncs.com/test-node/node-server:v2
在灰階政策中選擇基于流量比例釋出,流量比例 50%
- 送出灰階釋出後,檢視 sleep 應用的調用結果,可以看到,
和v1
版本的傳回結果v2
Hello from v1
Hello from v2
Hello from v1
Hello from v1
Hello from v2
Hello from v1
- 在 kiali 中檢視,可以确認,調用被分發到兩個版本中
故障注入
- 目前應用工作正常,我們為 istio-app-svc 注入故障,以測試整個應用的彈性。在 istio-app-svc 的管理界面中,打開故障注入政策,選擇注入中斷故障,百分比 50%,狀态碼 503
- 送出後,繼續檢視 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% 左右的失敗比例
- 除此之外,我們也可以為服務注入時延故障,例如在上述界面中,選擇時延故障,為 50% 的請求添加 5s 的時延
- 确認送出之後,我們可以看到,部分調用的耗時顯著增加。在 kiali 中也可以檢視調用的平均請求耗時
- 删除故障注入政策和灰階版本
v2
熔斷
當一個服務出現故障或者延遲增大時,如果不采取措施,問題可能會逐漸傳導到其他服務,導緻整個應用癱瘓。在這個場景下,我們可以通過為服務調用配置熔斷規則,來隔離故障。
在這一部分,我們為上述 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
。這意味着如果超過了一個連接配接同時發起請求,Istio 就會熔斷,阻止後續的請求或連接配接。是以我們以并發數為 3,發出 100 個請求:http1MaxPendingRequests: 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 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-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