Istio中的路由包含以下幾種常見的對(duì)象:
- VirtualService:Istio服務(wù)網(wǎng)格中定義的路由規(guī)則,控制流量路由到service的規(guī)則
- DestinationRule:配置將流量轉(zhuǎn)發(fā)到實(shí)際工作負(fù)載時(shí)應(yīng)用的策略集
- ServiceEntry:用于在 Istio 服務(wù)網(wǎng)格之外啟用的服務(wù)請(qǐng)求
- Gateway:為 HTTP/TCP 流量配置負(fù)載均衡器,最常見的是作用于網(wǎng)格邊緣,以處理應(yīng)用程序的入口/出口流量
- EnvoyFilter:用于定制Envoy配置
- Sidecar:用于定義入網(wǎng)和出網(wǎng)流量的可達(dá)性
VirtualService
首先是一個(gè)例子:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews.prod.svc.cluster.local
http:
- name: "reviews-v2-routes"
match:
- uri:
prefix: "/wpcatalog"
- uri:
prefix: "/consumercatalog"
rewrite:
uri: "/newcatalog"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v2
- name: "reviews-v1-route"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v1
上面的例子表示對(duì)于一個(gè)service:reviews.prod.svc.cluster.local收到的http流量,將被轉(zhuǎn)發(fā)到兩個(gè)目標(biāo)service:如果這個(gè)http請(qǐng)求的路徑包含/wpcatalog或/consumercatalog,那么流量將被發(fā)送給reviews服務(wù)的v2子集(v2子集是什么將在稍后解釋,可以看成擁有特定label的reviews服務(wù));否則,流量被發(fā)送給reviews服務(wù)的v1子集。
下面是一些關(guān)鍵配置項(xiàng):
- hosts:接收請(qǐng)求的主機(jī)。它可以是一個(gè)DNS或IP地址。這兒的reviews.prod.svc.cluster.local是reviews service在K8s中的域名。因此,所有通向reviews服務(wù)的流量都將被這個(gè)virtualService重新路由。注意,如果這兒直接使用"reviews"而非"reviews.prod.svc.cluster.local",那么Istio會(huì)根據(jù)這個(gè)virtualService所在的命名空間來解析這個(gè)reviews服務(wù)的全限定名。例如這個(gè)virtualService定義在default namespace中,那么"reviews"會(huì)被視為 reviews.default.svc.cluster.local,而不會(huì)是這個(gè) reviews 服務(wù)所在真實(shí)的命名空間。為了避免可能的錯(cuò)誤配置,建議使用服務(wù)的全限定名(FQDN)來進(jìn)行服務(wù)引用。
- hosts 配置的服務(wù)的名字只是表示該配置是針對(duì)于reviews服務(wù)的路由規(guī)則,但是具體將對(duì)該服務(wù)的訪問的流量路由到哪些服務(wù)的哪些實(shí)例上,就是要通過 destination 進(jìn)行配置。
- destination.host 應(yīng)該明確指向服務(wù)注冊(cè)表中的一個(gè)服務(wù)。Istio 的服務(wù)注冊(cè)表除包含平臺(tái)服務(wù)注冊(cè)表中的所有服務(wù)(例如 Kubernetes 服務(wù)、Consul 服務(wù))之外,還包含了 ServiceEntry 資源所定義的服務(wù)。subset 用于配置流量目的地的子集,這個(gè)子集具體包含了哪些服務(wù),是通過DestinationRule來定義的。
- 另外,還可以為每個(gè)destination添加weight,來實(shí)現(xiàn)路由的權(quán)重切分。
DestinationRule
subset 是服務(wù)端點(diǎn)的集合,可以用于 A/B 測(cè)試或者分版本路由等場(chǎng)景。對(duì)于 Kubernetes 中的服務(wù),一個(gè) subset 相當(dāng)于使用 label 的匹配條件選出來的 service。下面是一個(gè)DestinationRule的定義:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews-destination
spec:
host: reviews.prod.svc.cluster.local
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
這個(gè)例子中為reviews服務(wù)定義了兩個(gè)子集:v1和v2,因此在VirtualService中可以通過subset:v1和subset:v2來引用這兩個(gè)服務(wù)。子集v1表示所有擁有 version=v1 的label的reviews服務(wù),而子集v2表示所有擁有 version=v2的label的reviews服務(wù)。
因此,DestinationRule 定義了目標(biāo) host 的子集 subsets (或者稱之為命名版本)。 這些 subset 用于 VirtualService 的路由規(guī)則設(shè)置中,可以將流量導(dǎo)向服務(wù)的某些特定版本。
ServiceEntry
Istio 服務(wù)網(wǎng)格內(nèi)部會(huì)維護(hù)一個(gè)與平臺(tái)無關(guān)的使用通用模型表示的服務(wù)注冊(cè)表,當(dāng)你的服務(wù)網(wǎng)格需要訪問外部服務(wù)的時(shí)候,就需要使用 ServiceEntry 來添加服務(wù)注冊(cè)。類似于K8s中ExternalName類型的Service。
Gateway
Gateway描述了在網(wǎng)絡(luò)邊緣運(yùn)行的負(fù)載均衡器,用于接收傳入或傳出的HTTP / TCP連接。下面是一個(gè)例子:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
app: my-gateway-controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- uk.bookinfo.com
這個(gè)例子表示Istio會(huì)監(jiān)聽spec.selector選中的pod的80端口,并且允許包含了uk.bookinfo.com域名的http請(qǐng)求進(jìn)入。
Gateway 為 HTTP/TCP 流量配置了一個(gè)負(fù)載均衡,多數(shù)情況下在網(wǎng)格邊緣進(jìn)行操作,用于啟用一個(gè)服務(wù)的入口(ingress)流量,相當(dāng)于前端代理。與 Kubernetes 的 Ingress 不同,Istio Gateway 只配置四層到六層的功能(例如開放端口或者 TLS 配置),而 Kubernetes 的 Ingress 是七層的。將VirtualService 綁定到 Gateway 上,用戶就可以使用標(biāo)準(zhǔn)的 Istio 規(guī)則來控制進(jìn)入的 HTTP 和 TCP 流量。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo-rule
namespace: bookinfo-namespace
spec:
hosts:
- reviews.prod.svc.cluster.local
- uk.bookinfo.com
- eu.bookinfo.com
gateways:
- some-config-namespace/my-gateway
http:
- match:
- headers:
cookie:
exact: "user=dev-123"
route:
- destination:
port:
number: 7777
host: reviews.qa.svc.cluster.local
- match:
- uri:
prefix: /reviews/
route:
- destination:
port:
number: 9080 # can be omitted if it's the only port for reviews
host: reviews.prod.svc.cluster.local
weight: 80
- destination:
host: reviews.qa.svc.cluster.local
weight: 20
如這個(gè)例子所示,通過VirtualService綁定一個(gè)gateway能夠?qū)ateway進(jìn)入的流量路由到目標(biāo)service中。
EnvoyFilter
EnvoyFilter用于定制由Istio Pilot自動(dòng)生成的Envoy配置。通過EnvoyFilter能夠修改Envoy中的特配置,添加新的filter,listener,cluster等等。這個(gè)功能必須小心使用,因?yàn)椴徽_的配置可能會(huì)導(dǎo)致整個(gè)mesh奔潰。下面是一個(gè)例子:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: custom-protocol
namespace: istio-config # as defined in meshConfig resource.
spec:
configPatches:
- applyTo: NETWORK_FILTER
match:
context: SIDECAR_OUTBOUND # will match outbound listeners in all sidecars
listener:
portNumber: 9307
filterChain:
filter:
name: "envoy.tcp_proxy"
patch:
operation: INSERT_BEFORE
value:
name: "envoy.config.filter.network.custom_protocol"
config:
...
- applyTo: NETWORK_FILTER # http connection manager is a filter in Envoy
match:
# context omitted so that this applies to both sidecars and gateways
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
patch:
operation: MERGE
value:
typed_config:
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager"
idle_timeout: 30s
上面的例子在istio-config命名空間下定義了一個(gè)EnvoyFilter對(duì)象,這樣這些配置會(huì)作用于整個(gè)系統(tǒng)中的sidecar。它在原有的envoy.tcp_proxy filter前增加了一些配置,配置內(nèi)容省略。另外,又在envoy.http_connection_manager fileter中融合了一個(gè)新功能,即通過 envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager 增加一個(gè)30s的延遲。這就是一個(gè)EnvoyFilter的簡(jiǎn)單的使用例子。
Sidecar
Sidecar用于控制pod能夠接收什么流量和能夠向何處發(fā)送流量。
Sidecar是具有命名空間的資源。每個(gè)Sidecar應(yīng)用到命名空間的一個(gè)和多個(gè)工作負(fù)載,工作負(fù)載的選擇通過workloadSelector進(jìn)行,如果不指定workloadSelector(每個(gè)命名空間只能有一個(gè)這樣的Sidecar)則Sidecar應(yīng)用到命名空間的所有(沒有被其它帶有workloadSelector的Sidecar匹配的)工作負(fù)載。
如果命名空間包含多個(gè)沒有workloadSelector的Sidecar,或者多個(gè)Sidecar的workloadSelector匹配同一工作負(fù)載,則網(wǎng)格的行為是未定義的。
apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
name: default
namespace: prod-us1
spec:
# 入站流量規(guī)則
ingress:
# 對(duì)于從9080端口入站的HTTP流量,將其轉(zhuǎn)發(fā)給Sidecar關(guān)聯(lián)的工作負(fù)載監(jiān)聽的UDS
- port:
number: 9080
protocol: HTTP
name: somename
defaultEndpoint: unix:///var/run/someuds.sock
# 出站流量規(guī)則
egress:
# 允許針對(duì)istio-system命名空間的出站流量
- hosts:
- "istio-system/*"
# 允許針對(duì)prod-us1命名空間的9080端口的HTTP流量
- port:
number: 9080
protocol: HTTP
name: egresshttp
hosts:
- "prod-us1/*"
參考文章
- https://istio.io/docs/reference/config/networking/
- https://www.servicemesher.com/blog/istio-service-visibility/
- https://blog.gmem.cc/istio-study-note
- https://cloud.tencent.com/developer/article/1525435
- https://www.servicemesher.com/blog/istio-routing-basics/
- https://jimmysong.io/istio-handbook/concepts/traffic-management-basic.html
- https://www.kubernetes.org.cn/6296.html