控制 Ingress 流量git
到目前爲止,Istio提供了一個簡單的API來進行流量管理,該API包括了四種資源:RouteRule,DestinationPolicy,EgressRule和Ingress(直接使用了Kubernets的Ingress資源)。藉助此API,用戶能夠輕鬆管理Istio服務網格中的流量。該API容許用戶將請求路由到特定版本的服務,爲彈性測試注入延遲和失敗,添加超時和斷路器等等,全部這些功能都沒必要更改應用程序自己的代碼。github
雖然目前API的功能已被證實是Istio很是引人注目的一部分,但用戶的反饋也代表,這個API確實有一些缺點,尤爲是在使用它來管理包含數千個服務的很是大的應用程序,以及使用HTTP之外的協議時。 此外,使用Kubernetes Ingress資源來配置外部流量的方式已被證實不能知足需求。api
爲了解決上述缺陷和其餘的一些問題,Istio引入了新的流量管理API v1alpha3,新版本的API將徹底取代以前的API。 儘管v1alpha3和以前的模型在本質上是基本相同的,但它並不向後兼容的,基於舊API的模型須要進行手動轉換。 Istio接下來的幾個版本中會提供一個新舊模型的轉換工具。安全
爲了證實該非兼容升級的必要性,v1alpha3 API經歷了漫長而艱苦的社區評估過程,以但願新的API可以大幅改進,並經得起時間考驗。 在本文中,咱們將介紹新的配置模型,並試圖解釋其後面的一些動機和設計原則。服務器
設計原則
路由模型的重構過程當中遵循了一些關鍵的設計原則:cookie
v1alpha3中的配置資源
在一個典型的網格中,一般有一個或多個用於終結外部TLS連接,將流量引入網格的負載均衡器(咱們稱之爲gateway)。 而後流量經過邊車網關(sidecar gateway)流經內部服務。 應用程序使用外部服務的狀況也很常見(例如訪問Google Maps API),一些狀況下,這些外部服務可能被直接調用;但在某些部署中,網格中全部訪問外部服務的流量可能被要求強制經過專用的出口網關(Egress gateway)。 下圖描繪了網關在網格中的使用狀況。網絡
考慮到上述因素,v1alpha3引入瞭如下這些新的配置資源來控制進入網格,網格內部和離開網格的流量路由。架構
VirtualService,DestinationRule和ServiceEntry分別替換了原API中的RouteRule,DestinationPolicy和EgressRule。 Gateway是一個獨立於平臺的抽象,用於對流入專用中間設備的流量進行建模。負載均衡
下圖描述了跨多個配置資源的控制流程。 不一樣配置資源之間的關係ide
Gateway
Gateway用於爲HTTP / TCP流量配置負載均衡器,並無論該負載均衡器將在哪裏運行。 網格中能夠存在任意數量的Gateway,而且多個不一樣的Gateway實現能夠共存。 實際上,經過在配置中指定一組工做負載(Pod)標籤,能夠將Gateway配置綁定到特定的工做負載,從而容許用戶經過編寫簡單的Gateway Controller來重用現成的網絡設備。
對於入口流量管理,您可能會問: 爲何不直接使用Kubernetes Ingress API ? 緣由是Ingress API沒法表達Istio的路由需求。 Ingress試圖在不一樣的HTTP代理之間取一個公共的交集,所以只能支持最基本的HTTP路由,最終致使須要將代理的其餘高級功能放入到註解(annotation)中,而註解的方式在多個代理之間是不兼容的,沒法移植。
Istio Gateway 經過將L4-L6配置與L7配置分離的方式克服了Ingress的這些缺點。 Gateway只用於配置L4-L6功能(例如,對外公開的端口,TLS配置),全部主流的L7代理均以統一的方式實現了這些功能。 而後,經過在Gateway上綁定VirtualService的方式,可使用標準的Istio規則來控制進入Gateway的HTTP和TCP流量。
例如,下面這個簡單的Gateway配置了一個Load Balancer,以容許訪問host bookinfo.com的https外部流量入mesh中:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- bookinfo.com
tls:
mode: SIMPLE
serverCertificate: /tmp/tls.crt
privateKey: /tmp/tls.key
要爲進入上面的Gateway的流量配置相應的路由,必須爲同一個host定義一個VirtualService(在下一節中描述),並使用配置中的gateways字段綁定到前面定義的Gateway 上:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- bookinfo.com
gateways:
- bookinfo-gateway # <---- bind to gateway
http:
- match:
- uri:
prefix: /reviews
route:
...
Gateway能夠用於建模邊緣代理或純粹的內部代理,如第一張圖所示。 不管在哪一個位置,全部網關均可以用相同的方式進行配置和控制。
VirtualService
用一種叫作「Virtual services」的東西代替路由規則可能看起來有點奇怪,但對於它配置的內容而言,這事實上是一個更好的名稱,特別是在從新設計API以解決先前模型的可擴展性問題以後。
實際上,發生的變化是:在以前的模型中,須要用一組相互獨立的配置規則來爲特定的目的服務設置路由規則,並經過precedence字段來控制這些規則的順序;在新的API中,則直接對(虛擬)服務進行配置,該虛擬服務的全部規則以一個有序列表的方式配置在對應的VirtualService 資源中。
例如,以前在Bookinfo 應用程序的reviews服務中有兩個RouteRule資源,以下所示:
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: reviews-default
spec:
destination:
name: reviews
precedence: 1
route:
- labels:
version: v1
---
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: reviews-test-v2
spec:
destination:
name: reviews
precedence: 2
match:
request:
headers:
cookie:
regex: "^(.*?;)?(user=jason)(;.*)?$"
route:
- labels:
version: v2
在v1alph3,能夠在單個VirtualService資源中提供相同的配置:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
cookie:
regex: "^(.*?;)?(user=jason)(;.*)?$"
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
正如你所看到的, 和reviews服務相關的兩個規則集中寫在了一個地方。這個改變乍一看可能以爲並無什麼特別的優點, 然而,若是仔細觀察這個新模型,會發現它和以前的API之間存在着根本的差別,這使得v1alpha3功能更增強大。
首先,請注意VirtualService的目標服務是使用hosts字段(其實是重複字段)指定的,而後再在每一個路由的destination字段中指定。 這是與之前模型的重要區別。
VirtualService描述了一個或多個用戶可尋址目標到網格內實際工做負載之間的映射。在上面的示例中,這兩個地址是相同的,但實際上用戶可尋址目標能夠是任何用於定位服務的,具備可選通配符前綴或CIDR前綴的DNS名稱。 這對於應用從單體架構到微服務架構的遷移過程特別有用,單體應用被拆分爲多個獨立的微服務後,採用VirtaulService能夠繼續把多個微服務對外暴露爲同一個目標地址,而不須要服務消費者進行修改以適應該變化。
例如,如下規則容許服務消費者訪問Bookinfo應用程序的reviews和ratings服務,就好像它們是http://bookinfo.com/(虛擬)服務的一部分:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- bookinfo.com
http:
- match:
- uri:
prefix: /reviews
route:
- destination:
host: reviews
- match:
- uri:
prefix: /ratings
route:
- destination:
host: ratings
...
實際上在`VirtualService`中hosts部分設置只是虛擬的目的地,所以不必定是已在網格中註冊的服務。這容許用戶爲在網格內沒有可路由條目的虛擬主機的流量進行建模。 經過將VirtualService綁定到同一Host的Gateway配置(如前一節所述 ),可向網格外部暴露這些Host。
除了這個重大的重構以外, VirtualService還包括其餘一些重要的改變:
DestinationRule
DestinationRule配置將流量轉發到服務時應用的策略集。 這些策略應由由服務提供者撰寫,用於描述斷路器,負載均衡設置,TLS設置等。 除了下述改變外,DestinationRule與其前身DestinationPolicy大體相同。
DestinationRule的host能夠包含通配符前綴,以容許單個規則應用於多個服務。
DestinationRule定義了目的host的子集subsets (例如:命名版本)。 這些subset用於`VirtualService`的路由規則設置中,能夠將流量導向服務的某些特定版本。 經過這種方式爲版本命名後,能夠在不一樣的virtual service中明確地引用這些命名版本的ubset,簡化Istio代理髮出的統計數據,並能夠將subsets編碼到SNI頭中。 爲reviews服務配置策略和subsets的DestinationRule可能以下所示:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
- name: v3
labels:
version: v3
注意,與DestinationPolicy不一樣的是,可在單個DestinationRule中指定多個策略(例如上面實例中的缺省策略和v2版本特定的策略)。
ServiceEntry
ServiceEntry用於將附加條目添加到Istio內部維護的服務註冊表中。 它最經常使用於對訪問網格外部依賴的流量進行建模,例如訪問Web上的API或遺留基礎設施中的服務。
全部之前使用EgressRule進行配置的內容均可以經過ServiceEntry輕鬆完成。 例如,可使用相似這樣的配置來容許從網格內部訪問一個簡單的外部服務:
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: foo-ext
spec:
hosts:
- foo.com
ports:
- number: 80
name: http
protocol: HTTP
也就是說,ServiceEntry比它的前身具備更多的功能。首先,ServiceEntry不限於外部服務配置,它能夠有兩種類型:網格內部或網格外部。網格內部條目只是用於向網格顯式添加服務,添加的服務與其餘內部服務同樣。採用網格內部條目,能夠把本來未被網格管理的基礎設施也歸入到網格中(例如,把虛機中的服務添加到基於Kubernetes的服務網格中)。網格外部條目則表明了網格外部的服務。對於這些外部服務來講,mTLS身份驗證是禁用的,而且策略是在客戶端執行的,而不是在像內部服務請求同樣在服務器端執行策略。
因爲ServiceEntry配置只是將服務添加到網格內部的服務註冊表中,所以它能夠像註冊表中的任何其餘服務同樣,與VirtualService和/或DestinationRule一塊兒使用。例如,如下DestinationRule可用於啓動外部服務的mTLS鏈接:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: foo-ext
spec:
name: foo.com
trafficPolicy:
tls:
mode: MUTUAL
clientCertificate: /etc/certs/myclientcert.pem
privateKey: /etc/certs/client_private_key.pem
caCertificates: /etc/certs/rootcacerts.pem
除了擴展通用性之外,ServiceEntry還提供了其餘一些有關EgressRule改進,其中包括:
建立和刪除v1alpha3路由規則
因爲一個特定目的地的全部路由規則如今都存儲在單個VirtualService資源的一個有序列表中,所以爲該目的地添加新的規則不須要再建立新的RouteRule,而是經過更新該目的地的VirtualService資源來實現。
舊的路由規則:
$ istioctl create -f my-second-rule-for-destination-abc.yaml
v1alpha3路由規則:
$ istioctl replace -f my-updated-rules-for-destination-abc.yaml
刪除路由規則也使用istioctl replace完成,固然刪除最後一個路由規則除外(刪除最後一個路由規則須要刪除VirtualService)。
在添加或刪除引用服務版本的路由時,須要在該服務相應的DestinationRule更新subsets 。 正如你可能猜到的,這也是使用istioctl replace完成的。
總結
Istio v1alpha3路由API具備比其前身更多的功能,但不幸的是新的API並不向後兼容,舊的模型升級須要一次手動轉換。 Istio 0.9之後將再也不支持RouteRule,DesintationPolicy和EgressRule這些之前的配置資源 。Kubernetes用戶能夠繼續使用Ingress配置邊緣負載均衡器來實現基本的路由。 可是,高級路由功能(例如,跨兩個版本的流量分割)則須要使用Gateway ,這是一種功能更強大,Istio推薦的Ingress替代品。
致謝
感謝如下人員爲新版本的路由模型重構和實現工做作出的貢獻(按字母順序)
Frank Budinsky (IBM)
Zack Butcher (Google)
Greg Hanson (IBM)
Costin Manolache (Google)
Martin Ostrowski (Google)
Shriram Rajagopalan (VMware)
Louis Ryan (Google)
Isaiah Snell-Feikema (IBM)
Kuat Yessenov (Google)
原文
Introducing the Istio v1alpha3 routing API
參考:https://istio.io/zh/docs/tasks/traffic-management/ingress/
轉載:https://zhaohuabing.com/2018/06/04/introducing-the-istio-v1alpha3-routing-api/#原文
參考:https://www.yangcs.net/posts/istio-ingress/ (推薦看)
實例:https://github.com/4220182/k8s/tree/master/example/istio/gateway