在本模組中,我們將開始使用 Istio 服務網格在服務之間進行流量路由。使用流量路由,我們將學習如何部署新版本的服務,並在已釋出的生產版本的服務旁邊執行,而不干擾生產流量。隨著兩個服務版本的部署,我們將逐步釋出(金絲雀釋出)新版本,並開始將一定比例的傳入流量路由到最新版本。
使用服務網格Istio進行流量路由的前提是已經安裝好了istio,關於istio的安裝部署,請檢視部落格《Istio(二):在Kubernetes(k8s)叢集上安裝部署istio1.14》https://www.cnblogs.com/renshengdezheli/p/16836404.html
伺服器版本 | docker軟體版本 | Kubernetes(k8s)叢集版本 | Istio軟體版本 | CPU架構 |
---|---|---|---|---|
CentOS Linux release 7.4.1708 (Core) | Docker version 20.10.12 | v1.21.9 | Istio1.14 | x86_64 |
Kubernetes叢集架構:k8scloude1作為master節點,k8scloude2,k8scloude3作為worker節點
伺服器 | 作業系統版本 | CPU架構 | 程序 | 功能描述 |
---|---|---|---|---|
k8scloude1/192.168.110.130 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico | k8s master節點 |
k8scloude2/192.168.110.129 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker節點 |
k8scloude3/192.168.110.128 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker節點 |
我們可以使用 VirtualService 資源在 Istio 服務網格中進行流量路由。通過 VirtualService,我們可以定義流量路由規則,並在使用者端試圖連線到服務時應用這些規則。例如向 dev.example.com
傳送一個請求,最終到達目標服務。
讓我們看一下在叢集中執行 customers
應用程式的兩個版本(v1 和 v2)的例子。我們有兩個 Kubernetes 部署,customers-v1
和 customers-v2
。屬於這些部署的 Pod 有一個標籤 version:v1
或一個標籤 version:v2
的設定。
路由到 Customers如下所示:
我們想把 VirtualService 設定為將流量路由到應用程式的 V1 版本。70% 的傳入流量應該被路由到 V1 版本。30% 的請求應該被傳送到應用程式的 V2 版本。
下面是上述情況下 VirtualService 資源的yaml檔案:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: customers-route
spec:
hosts:
- customers.default.svc.cluster.local
http:
- name: customers-v1-routes
route:
- destination:
host: customers.default.svc.cluster.local
subset: v1
weight: 70
- name: customers-v2-routes
route:
- destination:
host: customers.default.svc.cluster.local
subset: v2
weight: 30
在 hosts
欄位下,我們要定義流量被傳送到的目標主機。在我們的例子中,這就是 customers.default.svc.cluster.local
Kubernetes 服務。
下一個欄位是 http
,這個欄位包含一個 HTTP 流量的路由規則的有序列表。destination
是指服務登入檔中的一個服務,也是路由規則處理後請求將被傳送到的目的地。Istio 的服務登入檔包含所有的 Kubernetes 服務,以及任何用 ServiceEntry資 源宣告的服務。
我們也在設定每個目的地的權重(weight
)。權重等於傳送到每個子集的流量的比例。所有權重的總和應該是 100。如果我們有一個單一的目的地,權重被假定為 100。
通過 gateways
欄位,我們還可以指定我們想要繫結這個 VirtualService 的閘道器名稱。比如說:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: customers-route
spec:
hosts:
- customers.default.svc.cluster.local
gateways:
- my-gateway
http:
...
上面的 YAML 檔案將 customers-route
這個VirtualService 繫結到名為 my-gateway
的閘道器上。這有效地暴露了通過閘道器的目標路由。
當一個 VirtualService 被附加到一個閘道器上時,只允許在閘道器資源中定義的主機。下表解釋了閘道器資源中的 hosts
欄位如何作為過濾器,以及 VirtualService 中的 hosts
欄位如何作為匹配。
Gateway Hosts | VirtualService Hosts | 行為 |
---|---|---|
* |
customers.default.svc.cluster.local |
流量通過 VirtualService 傳送,因為 * 允許所有主機 |
customers.default.svc.cluster.local |
customers.default.svc.cluster.local |
hosts 匹配,流量將被傳送 |
hello.default.svc.cluster.local |
customers.default.svc.cluster.local |
hosts 不匹配,無效 |
hello.default.svc.cluster.local |
["hello.default.svc.cluster.local", "customers.default.svc.cluster.local"] |
只允許 hello.default.svc.cluster.local 。它絕不允許 customers.default.svc.cluster.local 通過閘道器。然而,這仍然是一個有效的設定,因為 VirtualService 可以連線到第二個閘道器,該閘道器的 hosts 欄位中包含 *.default.svc.cluster.local |
目的地指的是不同的子集(subset)或服務版本。通過子集,我們可以識別應用程式的不同變體。在我們的例子中,我們有兩個子集,v1
和 v2
,它們對應於我們 customer 服務的兩個不同版本。每個子集都使用鍵/值對(標籤)的組合來確定哪些 Pod 要包含在子集中。我們可以在一個名為 DestinationRule
的資源型別中宣告子集。
下面是定義了兩個子集的 DestinationRule 資源的yaml檔案。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: customers-destination
spec:
host: customers.default.svc.cluster.local
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
讓我們看看我們可以在 DestinationRule 中設定的流量策略。
通過 DestinationRule,我們可以定義設定,如負載均衡設定、連線池大小、區域性異常檢測等,在路由發生後應用於流量。我們可以在 trafficPolicy
欄位下設定流量策略。以下是這些設定:
通過負載均衡器設定,我們可以控制目的地使用哪種負載均衡演演算法。下面是一個帶有流量策略的 DestinationRule 的例子,它把目的地的負載均衡演演算法設定為 round-robin
(輪詢)。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: customers-destination
spec:
host: customers.default.svc.cluster.local
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
我們還可以設定基於雜湊的負載均衡,並根據 HTTP 頭、cookies 或其他請求屬性提供對談親和性。下面是一個流量策略的片段,它設定了基於雜湊的負載均衡,並使用一個叫做 location
的 cookie 來實現親和力。
trafficPolicy:
loadBalancer:
consistentHash:
httpCookie:
name: location
ttl: 4s
這些設定可以在 TCP 和 HTTP 層面應用於上游服務的每個主機,我們可以用它們來控制連線量。
下面是一個片段,顯示了我們如何設定對服務的並行請求的限制。
spec:
host: myredissrv.prod.svc.cluster.local
trafficPolicy:
connectionPool:
http:
http2MaxRequests: 50
異常點檢測是一個斷路器的實現,它跟蹤上游服務中每個主機(Pod)的狀態。如果一個主機開始返回 5xx HTTP 錯誤,它就會在預定的時間內被從負載均衡池中彈出。對於 TCP 服務,Envoy 將連線超時或失敗計算為錯誤。
下面是一個例子,它設定了 500 個並行的 HTTP2 請求(http2MaxRequests
)的限制,每個連線不超過 10 個請求(maxRequestsPerConnection
)到該服務。每 5 分鐘掃描一次上游主機(Pod)(interval
),如果其中任何一個主機連續失敗 10 次(contracticalErrors
),Envoy 會將其彈出 10 分鐘(baseEjectionTime
)。
trafficPolicy:
connectionPool:
http:
http2MaxRequests: 500
maxRequestsPerConnection: 10
outlierDetection:
consecutiveErrors: 10
interval: 5m
baseEjectionTime: 10m
包含任何與上游服務連線的 TLS 相關設定。下面是一個使用提供的證書設定 mTLS 的例子。
trafficPolicy:
tls:
mode: MUTUAL
clientCertificate: /etc/certs/cert.pem
privateKey: /etc/certs/key.pem
caCertificates: /etc/certs/ca.pem
其他支援的 TLS 模式有 DISABLE
(沒有 TLS 連線),SIMPLE
(在上游端點發起 TLS 連線),以及 ISTIO_MUTUAL
(與 MUTUAL
類似,使用 Istio 的 mTLS 證書)。
註釋:LEAST_CONN表示最少連線,ROUND_ROBIN表示輪詢,輪詢演演算法是把請求平均的轉發給各個後端,使它們的負載大致相同。這有個前提,就是每個請求所佔用的後端時間要差不多,如果有些請求佔用的時間很長,會導致其所在的後端負載較高。在這種場景下,把請求轉發給連線數較少的後端,能夠達到更好的負載均衡效果,這就是least_conn演演算法。least_conn演演算法很簡單,首選遍歷後端叢集,比較每個後端的conns/weight,選取該值最小的後端。如果有多個後端的conns/weight值同為最小的,那麼對它們採用加權輪詢演演算法。
使用 portLevelSettings
欄位,我們可以將流量策略應用於單個埠。比如說:
trafficPolicy:
portLevelSettings:
- port:
number: 80
loadBalancer:
simple: LEAST_CONN
- port:
number: 8000
loadBalancer:
simple: ROUND_ROBIN
在前面,我們瞭解瞭如何利用流量的比例(weight
欄位)在多個子集之間進行流量路由。在某些情況下,純粹的基於權重的流量路由或分割已經足夠了。然而,在有些場景和情況下,我們可能需要對流量如何被分割和轉發到目標服務進行更細化的控制。
Istio 允許我們使用傳入請求的一部分,並將其與定義的值相匹配。例如,我們可以匹配傳入請求的 URI 字首,並基於此路由流量。
屬性 | 描述 |
---|---|
uri | 將請求 URI 與指定值相匹配 |
schema | 匹配請求的 schema(HTTP、HTTPS...) |
method | 匹配請求的 method(GET、POST...) |
authority | 匹配請求 authority 頭 |
headers | 匹配請求頭。頭資訊必須是小寫的,並以連字元分隔(例如:x-my-request-id )。注意,如果我們使用頭資訊進行匹配,其他屬性將被忽略(uri 、schema 、method 、authority )。 |
上述每個屬性都可以用這些方法中的一種進行匹配:
exact: "value"
匹配精確的字串prefix: "value"
只匹配字首regex:"value"
根據 ECMAscript 風格的正則進行匹配例如,假設請求的 URI 看起來像這樣:https://dev.example.com/v1/api
。為了匹配該請求的 URI,我們會這樣寫:
http:
- match:
- uri:
prefix: /v1
上述片段將匹配傳入的請求,並且請求將被路由到該路由中定義的目的地。
另一個例子是使用正則並在頭上進行匹配。
http:
- match:
- headers:
user-agent:
regex: '.*Firefox.*'
上述匹配將匹配任何使用者代理頭與 Regex 匹配的請求。
在頭資訊和其他請求屬性上進行匹配是有用的,但有時我們可能需要通過請求 URI 中的值來匹配請求。
例如,讓我們考慮這樣一種情況:傳入的請求使用 /v1/api
路徑,而我們想把請求路由到 /v2/api
端點。
這樣做的方法是重寫所有傳入的請求和與 /v1/api
匹配的 authority/host headers 到 /v2/api
。
例如:
...
http:
- match:
- uri:
prefix: /v1/api
rewrite:
uri: /v2/api
route:
- destination:
host: customers.default.svc.cluster.local
...
即使目標服務不在 /v1/api
端點上監聽,Envoy 也會將請求重寫到 /v2/api
。
我們還可以選擇將請求重定向或轉發到一個完全不同的服務。下面是我們如何在頭資訊上進行匹配,然後將請求重定向到另一個服務:
...
http:
- match:
- headers:
my-header:
exact: hello
redirect:
uri: /hello
authority: my-service.default.svc.cluster.local:8000
...
redirect
和 destination
欄位是相互排斥的。如果我們使用 redirect
,就不需要設定 destination
。
在進行匹配時,我們可以使用 AND 和 OR 兩種語意。讓我們看一下下面的片段:
...
http:
- match:
- uri:
prefix: /v1
headers:
my-header:
exact: hello
...
上面的片段使用的是 AND 語意。這意味著 URI 字首需要與 /v1
相匹配,並且頭資訊 my-header
有一個確切的值 hello
。
要使用 OR 語意,我們可以新增另一個 match
項,像這樣:
...
http:
- match:
- uri:
prefix: /v1
...
- match:
- headers:
my-header:
exact: hello
...
在上面的例子中,將首先對 URI 字首進行匹配,如果匹配,請求將被路由到目的地。如果第一個不匹配,演演算法會轉移到第二個,並嘗試匹配頭。如果我們省略路由上的匹配欄位,它將總是評估為 true
。
我們將學習如何使用權重在不同的服務版本之間路由流量。然後,我們將部署 Customers 服務版本 v2,並使用子集在這兩個版本之間分配流量。
讓我們從部署 Gateway 開始:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- '*'
將上述 YAML 儲存為 gateway.yaml
,並使用 kubectl apply -f gateway.yaml
部署 Gateway。
接下來,我們將建立 Web Frontend 和 Customers 服務的部署以及相應的 Kubernetes 服務。讓我們首先從 web-frontend
開始:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-frontend
labels:
app: web-frontend
spec:
replicas: 1
selector:
matchLabels:
app: web-frontend
template:
metadata:
labels:
app: web-frontend
version: v1
spec:
containers:
- image: gcr.io/tetratelabs/web-frontend:1.0.0
imagePullPolicy: Always
name: web
ports:
- containerPort: 8080
env:
- name: CUSTOMER_SERVICE_URL
value: 'http://customers.default.svc.cluster.local'
---
kind: Service
apiVersion: v1
metadata:
name: web-frontend
labels:
app: web-frontend
spec:
selector:
app: web-frontend
ports:
- port: 80
name: http
targetPort: 8080
注意,我們正在設定一個名為 CUSTOMER_SERVICE_URL
的環境變數,它指向我們接下來要部署的 customer
服務。Web Frontend 使用這個 URL 來呼叫 Customers 服務。
將上述 YAML
儲存為 web-frontend.yaml
,並使用 kubectl apply -f web-frontend.yaml
建立部署和服務。
現在我們可以部署 Customers 服務的 v1版本了。注意我們是如何在 Pod 模板中設定 version: v1
標籤的。然而,該服務在其選擇器中只使用app: customers
。這是因為我們將在 DestinationRule 中建立子集,這些子集將在選擇器中應用額外的版本標籤,使我們能夠到達執行特定版本的 Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
name: customers-v1
labels:
app: customers
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: customers
version: v1
template:
metadata:
labels:
app: customers
version: v1
spec:
containers:
- image: gcr.io/tetratelabs/customers:1.0.0
imagePullPolicy: Always
name: svc
ports:
- containerPort: 3000
---
kind: Service
apiVersion: v1
metadata:
name: customers
labels:
app: customers
spec:
selector:
app: customers
ports:
- port: 80
name: http
targetPort: 3000
將上述內容儲存為 customers-v1.yaml
,並使用 kubectl apply -f customers-v1.yaml
建立部署和服務。
我們應該有兩個應用程式的部署在執行:
$ kubectl get po
NAME READY STATUS RESTARTS AGE
customers-v1-7857944975-5lxc8 2/2 Running 0 36s
web-frontend-659f65f49-jz58r 2/2 Running 0 3m38s
現在我們可以為 web-frontend
建立一個 VirtualService,並將其繫結到 Gateway 資源上:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: web-frontend
spec:
hosts:
- '*'
gateways:
- gateway
http:
- route:
- destination:
host: web-frontend.default.svc.cluster.local
port:
number: 80
將上述 YAML 儲存為 web-frontend-vs.yaml
,並使用 kubectl apply -f web-frontend-vs.yaml
建立 VirtualService。
現在我們可以在瀏覽器中開啟 GATEWAY_URL
,並進入顯示 Customers 服務中客戶列表的 Web Frontend,如下圖所示。
如果我們部署了 Customers 服務 v2 版本,我們在呼叫 http://customers.default.svc.cluster.local
,得到的迴應將是隨機的。它們要麼來自 Customers 服務的 v2 版本,要麼來自 v1 版本。
我們需要為 Customers 服務建立 DestinationRule,並定義兩個子集,代表 v1 和 v2 版本。然後,我們可以建立一個 VirtualService,並將所有流量路由到 v1 版本的子集。之後,我們可以在不影響現有服務的情況下部署 v2 版本的 Customers 服務。
讓我們從 DestinationRule 和兩個子集開始:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: customers
spec:
host: customers.default.svc.cluster.local
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
將上述內容儲存到 customers-dr.yaml
,並使用 kubectl apply -f customers-dr.yaml
建立 DestinationRule。
我們可以建立 VirtualService 並在目標中指定 v1子集:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: customers
spec:
hosts:
- 'customers.default.svc.cluster.local'
http:
- route:
- destination:
host: customers.default.svc.cluster.local
port:
number: 80
subset: v1
每當有請求被傳送到 Kubernetes Customers 服務時,它將被路由到同一服務的 v1子集。
將上述 YAML 儲存為 customers-vs.yaml
,並使用 kubectl apply -f customers-vs.yaml
建立 VirtualService。
現在我們已經準備好部署 v2 版的 Customers 服務了。v2 版本返回與前一版本相同的客戶列表,但它也包括城市名稱。
讓我們建立 Customers v2 部署。我們不需要部署 Kubernetes 服務,因為我們已經部署了一個 v1 版本的服務。
apiVersion: apps/v1
kind: Deployment
metadata:
name: customers-v2
labels:
app: customers
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: customers
version: v2
template:
metadata:
labels:
app: customers
version: v2
spec:
containers:
- image: gcr.io/tetratelabs/customers:2.0.0
imagePullPolicy: Always
name: svc
ports:
- containerPort: 3000
該部署與 v1 部署幾乎相同。唯一的區別是所使用的 Docker 映象版本和設定在版本標籤上的 v2 值。
將上述 YAML 儲存為 customers-v2.yaml
,並使用 kubectl apply -f customers-v2.yaml
建立部署。
讓我們使用 weight
欄位並修改 VirtualService,使 50% 的流量被傳送到 v1 子集,另 50% 傳送到 v2 子集。
要做到這一點,我們將建立第二個 destination
,有相同的主機名,但有不同的子集。我們還將為 destination
新增 weight: 50
,以便在兩個版本之間平均分配流量。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: customers
spec:
hosts:
- 'customers.default.svc.cluster.local'
http:
- route:
- destination:
host: customers.default.svc.cluster.local
port:
number: 80
subset: v1
weight: 50
- destination:
host: customers.default.svc.cluster.local
port:
number: 80
subset: v2
weight: 50
將上述 YAML 儲存為 customers-50-50.yaml
並使用 kubectl apply -f customers-50-50.yaml
更新 VirtualService。
在瀏覽器中開啟 GATEWAY_URL
,重新整理幾次頁面,看看不同的響應。來自 Customers v2 的響應顯示在下圖中。
為了改變傳送到一個或另一個版本的流量比例,我們可以更新 VirtualService。同樣,我們也可以新增 v3 或 v4 版本,並在這些版本之間分割流量。
刪除 Deployments、Services、VirtualServices、DestinationRule 和 Gateway:
kubectl delete deploy web-frontend customers-{v1,v2}
kubectl delete svc customers web-frontend
kubectl delete vs customers web-frontend
kubectl delete dr customers
kubectl delete gateway gateway
在這個實驗中,我們將學習如何使用請求屬性在多個服務版本之間路由流量。
我們將從部署 Gateway 開始:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- '*'
將上述 YAML 儲存為 gateway.yaml
並使用 kubectl apply -f gateway.yaml
部署閘道器。
接下來,我們將部署Web前端、Customers v1、Customers v2,以及相應的 VirtualServices 和 DestinationRule。一旦一切部署完畢,所有流量將被路由到 Customers v1。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-frontend
labels:
app: web-frontend
spec:
replicas: 1
selector:
matchLabels:
app: web-frontend
template:
metadata:
labels:
app: web-frontend
version: v1
spec:
containers:
- image: gcr.io/tetratelabs/web-frontend:1.0.0
imagePullPolicy: Always
name: web
ports:
- containerPort: 8080
env:
- name: CUSTOMER_SERVICE_URL
value: 'http://customers.default.svc.cluster.local'
---
kind: Service
apiVersion: v1
metadata:
name: web-frontend
labels:
app: web-frontend
spec:
selector:
app: web-frontend
ports:
- port: 80
name: http
targetPort: 8080
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: web-frontend
spec:
hosts:
- '*'
gateways:
- gateway
http:
- route:
- destination:
host: web-frontend.default.svc.cluster.local
port:
number: 80
將上述 YAML 儲存為 web-frontend.yaml
並使用 kubectl apply -f web-frontend.yaml
建立部署和服務。
apiVersion: apps/v1
kind: Deployment
metadata:
name: customers-v1
labels:
app: customers
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: customers
version: v1
template:
metadata:
labels:
app: customers
version: v1
spec:
containers:
- image: gcr.io/tetratelabs/customers:1.0.0
imagePullPolicy: Always
name: svc
ports:
- containerPort: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: customers-v2
labels:
app: customers
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: customers
version: v2
template:
metadata:
labels:
app: customers
version: v2
spec:
containers:
- image: gcr.io/tetratelabs/customers:2.0.0
imagePullPolicy: Always
name: svc
ports:
- containerPort: 3000
---
kind: Service
apiVersion: v1
metadata:
name: customers
labels:
app: customers
spec:
selector:
app: customers
ports:
- port: 80
name: http
targetPort: 3000
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: customers
spec:
hosts:
- 'customers.default.svc.cluster.local'
http:
- route:
- destination:
host: customers.default.svc.cluster.local
port:
number: 80
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: customers
spec:
host: customers.default.svc.cluster.local
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
將上述 YAML 儲存為 customers.yaml
,用 kubectl apply -f customers.yaml
建立資源。
為了確保一切部署和工作正常,開啟 GATEWAY_URL
,並確保我們從 Customers v1 獲得響應。
我們將更新 Customers 的 VirtualService,並更新流量在兩個版本的 Customers 服務之間的路由。
讓我們看一下 YAML,如果請求中包含一個 header user: debug
,就把流量路由到 Customers v2。如果沒有設定這個 header,我們就被路由到 Customers v1。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: customers
spec:
hosts:
- 'customers.default.svc.cluster.local'
http:
- match:
- headers:
user:
exact: debug
route:
- destination:
host: customers.default.svc.cluster.local
port:
number: 80
subset: v2
- route:
- destination:
host: customers.default.svc.cluster.local
port:
number: 80
subset: v1
將上述 YAML 儲存為 customers-vs.yaml
,然後用 kubectl apply -f customers-vs.yaml
更新 VirtualService。
如果我們不提供埠號,VirtualService 中的目的地也會工作。這是因為該服務只定義了一個埠。
如果我們開啟 GATEWAY_URL
,我們仍然應該得到來自 Customers v1的響應。如果我們在請求中新增 header user: debug
,我們會注意到customers 的響應是來自 Customers v2。
我們可以使用 ModHeader 擴充套件來修改瀏覽器中的頭資訊。另外,我們也可以使用 cURL,像這樣把頭資訊新增到請求中。
$ curl -H "user: debug" http://GATEWAY_URL/
...
<th class="px-4 py-2">CITY</th>
<th class="px-4 py-2">NAME</th>
...
如果我們看一下回復,你會注意到有兩欄——CITY 和 NAME。
刪除 Deployment、Service、VirtualService、DestinationRule 和 Gateway:
kubectl delete deploy web-frontend customers-{v1,v2}
kubectl delete svc customers web-frontend
kubectl delete vs customers web-frontend
kubectl delete dr customers
kubectl delete gateway gateway