上一篇文章中,我們介紹了Istio針對單集群的三種主流部署安裝方式:使用Istioctl安裝、使用Helm自定義安裝、獨立Operator安裝。本文將向大家介紹kubernetes 中的應用接入Istio。主要包括kubernetes 中應用接入Istio使用實例、應用技巧、基本知識點總結和需要注意事項。
用什么姿勢接入 istio?
雖然 istio 能解決那么多的問題,但是引入 istio 并不是沒有代價的。最大的問題是 istio 的復雜性,強大的功能也意味著 istio 的概念和組件非常多,要想理解和掌握 istio ,并成功在生產環境中部署需要非常詳細的規劃。一般情況下,集群管理團隊需要對 kubernetes 非常熟悉,了解常用的使用模式,然后采用逐步演進的方式把 istio 的功能分批掌控下來。
我們設定以下目標:
istio部署
dfb相關服務部署
網關功能
流量分配,按比例,header
超時,重試
Istio的幾個基本資源對象:
1. VirtualService配置影響流量路由的參數,VirtualService 定義了對特定目標服務的一組流量規則。如其名字所示, VirtualService在形式上表示一個虛擬服務,將滿足條件的流量都轉發到對應的服務后端,這個服務后端可以是一個服務,也可以是在Dest in at i onRu l e 中定義的服務的子集。
2. DestinationRule配置目標規則,DestinationRule定義了在路由發生后應用于服務流量的策略。這些規則指定負載平衡的配置,邊車的連接池大小以及離群值檢測設置,以從負載平衡池中檢測和清除不正常的主機。
3. Gateway服務網關,入口.Gateway描述了一個負載均衡器,該負載均衡器在網格的邊緣運行,以接收傳入或傳出的HTTP / TCP連接。
4. Service Entry外部服務配置,通過ServiceEntry,可以在Istio的內部服務注冊表中添加其他條目,以便網格中自動發現的服務可以訪問/路由到這些手動指定的服務。
網關功能:Gateway
Gateway 在網格邊緣接收外部訪問,并將流量轉發到網格內的服務。Istio 通過Gateway將網格內的服務發布成外部可訪問的服務,還可以通過Gateway 配置外部訪問的端口、協議及與內部服務的映射關系。
網關功能常見的應用:
1. 將網格內的HTTP 服務發布為HTTP 外部訪問
2. 將網格內的HTTPS 服務發布為HTTPS 外部訪問
3. 將網格內的HTTP 服務發布為HTTPS 外部訪問
4. 將網格內的HTTP 服務發布為雙向HTTPS 外部訪問
5. 將網格內的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 {
return500;
}
此時應用下面的重試規則,再次調用接口。此時接口狀態碼一直返回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。