在多叢集服務網格中進行版本路由
在多叢集服務網格中設定 Istio 路由規則。
如果您花了一些時間研究 Istio,您可能會注意到它包含許多可以使用在單個 Kubernetes 叢集上執行的簡單任務和範例來演示的功能。由於大多數(如果不是全部)真實世界的雲端和微服務應用程式並非如此簡單,並且需要將服務分散並在多個位置運行,您可能想知道所有這些功能在您的實際生產環境中是否也會如此簡單。
幸運的是,Istio 提供了幾種配置服務網格的方法,使應用程式可以或多或少地透明地成為服務在多個叢集中運行的網格的一部分,也就是在多叢集部署中。設定多叢集網格最簡單的方法,因為它沒有特殊的網路要求,是使用複製的控制平面模型。在此配置中,每個為網格做出貢獻的 Kubernetes 叢集都有自己的控制平面,但每個控制平面都在單一管理控制下同步運行。
在本文中,我們將探討 Istio 的其中一項功能,流量管理,如何在具有專用控制平面拓撲的多叢集網格中運作。我們將展示如何設定 Istio 路由規則,通過部署 Bookinfo 範例,其中 reviews
服務的 v1
版本在一個叢集中運行,而 v2
和 v3
版本在第二個叢集中運行,來呼叫多叢集服務網格中的遠端服務。
設定叢集
首先,您需要兩個 Kubernetes 叢集,它們都運行稍微自訂的 Istio 設定。
按照複製的控制平面說明設定具有兩個 Istio 叢集的多叢集環境。
kubectl
命令用於透過--context
標誌存取兩個叢集。使用以下命令列出您的 context$ kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * cluster1 cluster1 user@foo.com default cluster2 cluster2 user@foo.com default
匯出以下包含您設定的 context 名稱的環境變數
$ export CTX_CLUSTER1=<cluster1 context name> $ export CTX_CLUSTER2=<cluster2 context name>
在 cluster1
中部署 bookinfo
應用程式的 v1 版本
在 cluster1
中運行 productpage
和 details
服務以及 reviews
服務的 v1
版本
$ kubectl label --context=$CTX_CLUSTER1 namespace default istio-injection=enabled
$ kubectl apply --context=$CTX_CLUSTER1 -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: productpage
labels:
app: productpage
spec:
ports:
- port: 9080
name: http
selector:
app: productpage
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: productpage-v1
spec:
replicas: 1
template:
metadata:
labels:
app: productpage
version: v1
spec:
containers:
- name: productpage
image: istio/examples-bookinfo-productpage-v1:1.10.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
apiVersion: v1
kind: Service
metadata:
name: details
labels:
app: details
spec:
ports:
- port: 9080
name: http
selector:
app: details
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: details-v1
spec:
replicas: 1
template:
metadata:
labels:
app: details
version: v1
spec:
containers:
- name: details
image: istio/examples-bookinfo-details-v1:1.10.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
apiVersion: v1
kind: Service
metadata:
name: reviews
labels:
app: reviews
spec:
ports:
- port: 9080
name: http
selector:
app: reviews
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: reviews-v1
spec:
replicas: 1
template:
metadata:
labels:
app: reviews
version: v1
spec:
containers:
- name: reviews
image: istio/examples-bookinfo-reviews-v1:1.10.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
EOF
在 cluster2
中部署 bookinfo
v2 和 v3 服務
在 cluster2
中運行 ratings
服務以及 reviews
服務的 v2
和 v3
版本
$ kubectl label --context=$CTX_CLUSTER2 namespace default istio-injection=enabled
$ kubectl apply --context=$CTX_CLUSTER2 -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: ratings
labels:
app: ratings
spec:
ports:
- port: 9080
name: http
selector:
app: ratings
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: ratings-v1
spec:
replicas: 1
template:
metadata:
labels:
app: ratings
version: v1
spec:
containers:
- name: ratings
image: istio/examples-bookinfo-ratings-v1:1.10.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
apiVersion: v1
kind: Service
metadata:
name: reviews
labels:
app: reviews
spec:
ports:
- port: 9080
name: http
selector:
app: reviews
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: reviews-v2
spec:
replicas: 1
template:
metadata:
labels:
app: reviews
version: v2
spec:
containers:
- name: reviews
image: istio/examples-bookinfo-reviews-v2:1.10.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: reviews-v3
spec:
replicas: 1
template:
metadata:
labels:
app: reviews
version: v3
spec:
containers:
- name: reviews
image: istio/examples-bookinfo-reviews-v3:1.10.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
EOF
存取 bookinfo
應用程式
就像任何應用程式一樣,我們將使用 Istio 閘道來存取 bookinfo
應用程式。
在
cluster1
中建立bookinfo
閘道$ kubectl apply --context=$CTX_CLUSTER1 -f @samples/bookinfo/networking/bookinfo-gateway.yaml@
按照 Bookinfo 範例說明確定入口 IP 和埠,然後將您的瀏覽器指向
http://$GATEWAY_URL/productpage
。
您應該看到帶有評論的 productpage
,但沒有評分,因為 reviews
服務的只有 v1
版本在 cluster1
上運行,而且我們尚未設定存取 cluster2
的權限。
在 cluster1
上為遠端 reviews 服務建立服務條目和目標規則
如設定說明中所述,遠端服務是使用 .global
DNS 名稱存取的。在我們的例子中,它是 reviews.default.global
,因此我們需要為該主機建立服務條目和目標規則。服務條目將使用 cluster2
閘道作為端點位址來存取服務。您可以使用閘道的 DNS 名稱(如果有的話)或其公共 IP,如下所示
$ export CLUSTER2_GW_ADDR=$(kubectl get --context=$CTX_CLUSTER2 svc --selector=app=istio-ingressgateway \
-n istio-system -o jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}")
現在,使用以下命令建立服務條目和目標規則
$ kubectl apply --context=$CTX_CLUSTER1 -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: reviews-default
spec:
hosts:
- reviews.default.global
location: MESH_INTERNAL
ports:
- name: http1
number: 9080
protocol: http
resolution: DNS
addresses:
- 240.0.0.3
endpoints:
- address: ${CLUSTER2_GW_ADDR}
labels:
cluster: cluster2
ports:
http1: 15443 # Do not change this port value
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews-global
spec:
host: reviews.default.global
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
subsets:
- name: v2
labels:
cluster: cluster2
- name: v3
labels:
cluster: cluster2
EOF
服務條目的位址 240.0.0.3
可以是任何未分配的任意 IP。使用來自 E 類位址範圍 240.0.0.0/4 的 IP 是一個不錯的選擇。查看閘道連線的多叢集範例以獲取更多詳細資訊。
請注意,目標規則中子集的標籤會對應到與 cluster2
閘道對應的服務條目端點標籤 (cluster: cluster2
)。一旦請求到達目標叢集,將會使用本機目標規則來識別與請求的子集對應的實際 Pod 標籤(version: v1
或 version: v2
)。
在兩個叢集上為本機 reviews 服務建立目標規則
嚴格來說,我們只需要定義每個叢集中正在使用的本機服務的子集(即,cluster1
中的 v1
、cluster2
中的 v2
和 v3
),但為了簡單起見,我們將在兩個叢集中定義所有三個子集,因為定義未實際部署的版本子集沒有任何問題。
$ kubectl apply --context=$CTX_CLUSTER1 -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews.default.svc.cluster.local
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
EOF
$ kubectl apply --context=$CTX_CLUSTER2 -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews.default.svc.cluster.local
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
EOF
建立虛擬服務來路由 reviews 服務流量
此時,對 reviews
服務的所有呼叫都將轉到本機 reviews
Pod (v1
),因為如果您查看原始程式碼,您會發現 productpage
實作只是向 http://reviews:9080
(會展開為主機 reviews.default.svc.cluster.local
) 發出請求,這是該服務的本機版本。對應的遠端服務名為 reviews.default.global
,因此需要路由規則將請求重新導向至全域主機。
套用以下虛擬服務,將使用者 jason
的流量導向在 cluster2
上運行的 reviews
版本 v2
和 v3
(50/50)。任何其他使用者的流量都將轉到 reviews
版本 v1
。
$ kubectl apply --context=$CTX_CLUSTER1 -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews.default.svc.cluster.local
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews.default.global
subset: v2
weight: 50
- destination:
host: reviews.default.global
subset: v3
weight: 50
- route:
- destination:
host: reviews.default.svc.cluster.local
subset: v1
EOF
返回您的瀏覽器並以使用者 jason
的身分登入。如果您多次重新整理頁面,您應該會看到顯示在黑色和紅色評分星星之間交替 (v2
和 v3
)。如果您登出,您將只會看到沒有評分的評論 (v1
)。
總結
在本文中,我們已經了解如何使用 Istio 路由規則將服務的版本分散在具有複製控制平面模型的多叢集服務網格中的叢集之間。在本範例中,我們手動設定了提供與一個遠端服務 reviews
連線所需的 .global
服務條目和目標規則。但是,一般來說,如果我們希望任何服務都能夠在本機或遠端運行,我們需要為每個服務建立 .global
資源。幸運的是,這個過程可以自動化,並且很可能會在未來版本的 Istio 中實現。