目標
- [x] istio部署
- [x] dfb相關服務部署
- [x] 網關功能
- [x] 流量分配,按比例,header
- [x] 超時,重試
istio 的幾個基本資源對象:
- VirtualService
配置影響流量路由的參數,VirtualService 定義了對特定目標服務的一組流量規則。如其名字所示, VirtualService在形式上表示一個虛擬服務,將滿足條件的流量都轉發到對應的服務后端,這個服務后端可以是一個服務,也可以是在Dest in at i onRu l e 中定義的服務的子集 - DestinationRule
配置目標規則,DestinationRule定義了在路由發生后應用於服務流量的策略。這些規則指定負載平衡的配置,邊車的連接池大小以及離群值檢測設置,以從負載平衡池中檢測和清除不正常的主機。 - Gateway
服務網關,入口.Gateway描述了一個負載均衡器,該負載均衡器在網格的邊緣運行,以接收傳入或傳出的HTTP / TCP連接。 - Service Entry
外部服務配置,通過ServiceEntry,可以在Istio的內部服務注冊表中添加其他條目,以便網格中自動發現的服務可以訪問/路由到這些手動指定的服務。
網關功能 -- Gateway
Gateway 在網格邊緣接收外部訪問,並將流量轉發到網格內的服務。Istio 通過Gateway將網格內的服務發布成外部可訪問的服務,還可以通過Gateway 配置外部訪問的端口、協議及與內部服務的映射關系。
網關功能常見的應用
- 將網格內的HTTP 服務發布為HTTP 外部訪問
- 將網格內的HTTPS 服務發布為HTTPS 外部訪問
- 將網格內的HTTP 服務發布為HTTPS 外部訪問
- 將網格內的HTTP 服務發布為雙向HTTPS 外部訪問
- 將網格內的HTTP 服務發布為HTTPS 外部訪問和HTTPS 內部訪問
在實踐中。我們更多需要的是1,3兩個場景
在dfb服務中。 dfb-login 作為最外層的前端。是幾個服務中唯一和外部用戶產生交互的服務。 因此我們通過網關功能,將dfb-login 通過域名暴露給用戶
創建gateway 的yml文件
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: login-gateway
namespace: dfb-istio
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- istio-login.dfb.com
port:
name: https
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/dfb.pem
serverCertificate: /etc/istio/ingressgateway-certs/dfb.pem
- hosts:
- istio-login.dfb.com
port:
name: http
number: 80
protocol: HTTP
創建virtualservice.yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: dfb-login
namespace: dfb-istio
spec:
gateways:
- login-gateway
hosts:
- '*'
http:
- uri:
prefix: /
- route:
- destination:
host: dfb-login.dfb-istio.svc.cluster.local
我們創建了兩個資源對象,一個VirtualService 用來描述流量的路由關系。所有url 前綴為/ 的請求都route 到后端dfb-login.dfb-istio.svc.cluster.local 服務。
這個virtuaservice 通過gateways 字段和我們申明的另一個gateway 資源相互綁定。在Gateway 資源對象中。 定義了入口的域名,協議,以及TLS 相關的配置。在istio 中。默認的ingressgateway 會監聽gateway 資源對象的變更。多個ingressgateway 通過selector 進行選擇.默認ingressgateway 是一個loadbalancer的service 。 我們將這個ingressgateway 修改為宿主機網絡,並固定到一個單獨的節點。這樣我們就可以通過將域名解析到這個node節點的方式訪問部署好的入口
流量分配:按比例,根據請求內容
我們設置了兩個版本的login 服務。 V1 版本用戶登錄后顯示的余額是從數據庫取出來的。V2版本則是0。根據這兩個版本的差異來判斷流量的流向。
首先通過DestinationRule定義兩個版本
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: dfb-login
namespace: dfb-istio
spec:
host: dfb-login
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
根據比例
修改在網關功能中創建的virtualservice
kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
name: dfb-login
namespace: dfb-istio
spec:
hosts:
- '*'
gateways:
- login-gateway
http:
- match:
- uri:
prefix: /
route:
- destination:
host: dfb-login.dfb-istio.svc.cluster.local
subset: v1
weight: 50
- destination:
host: dfb-login.dfb-istio.svc.cluster.local
subset: v2
weight: 50
此時多次刷新頁面。可以看到用戶的現金賬戶余額在0 和真實額度之間變動
根據請求內容決定路由
kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
name: dfb-login
namespace: dfb-istio
spec:
hosts:
- '*'
gateways:
- login-gateway
http:
- match:
- headers:
version:
exact: v2
route:
- destination:
host: dfb-login.dfb-istio.svc.cluster.local
subset: v2
- route:
- destination:
host: dfb-login.dfb-istio.svc.cluster.local
subset: v1
修改上文yml 。 通過postman請求dfb服務/home頁面。默認情況下會路由指向V1版本的login服務。在請求頭添加version=v2的header。 則會轉到v2的服務。
超時,重試功能
我們首先在擴容dfb-api 這個服務為2個pod,在其中一個pod中攔截用戶資產接口, 直接返回500 ,另一個pod 正常返回。 此時在dfb-login服務中請求。 我們可以發現,接口500 和200 狀態碼交替出現。
location =/user/account/list/338fbcd2-1be6-4dde-9918-84b7629b1ba5 {
return 500;
}
此時應用下面的重試規則,再次調用接口。此時接口狀態碼一直返回200.
kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
name: dfb-api
namespace: dfb-istio
spec:
hosts:
- dfb-api.dfb-istio.svc.cluster.local
gateways: ~
http:
- route:
- destination:
host: dfb-api.dfb-istio.svc.cluster.local
port:
number: 80
weight: 100
retries:
attempts: 3
perTryTimeout: 2s
retryOn: 5xx,gateway-error,connect-failure,refused-stream
通過jaeger查看調用鏈,可以看到調用了兩次dfb-api。雖然中間調用失敗了,但是最終的狀態碼是200

istio 中硬編碼了retryOn 默認值為connect-failure,refused-stream(因為連接失敗和流拒接是安全的),如果攔截的時候返回502 , 則istio會自動重試。無法在應用重試規則前觀察到200和500 狀態碼交替出現。
