在多叢集服務網格中進行版本路由

在多叢集服務網格中設定 Istio 路由規則。

2019 年 2 月 7 日 | 作者:Frank Budinsky - IBM

如果您花了一些時間研究 Istio,您可能會注意到它包含許多可以使用在單個 Kubernetes 叢集上執行的簡單任務範例來演示的功能。由於大多數(如果不是全部)真實世界的雲端和微服務應用程式並非如此簡單,並且需要將服務分散並在多個位置運行,您可能想知道所有這些功能在您的實際生產環境中是否也會如此簡單。

幸運的是,Istio 提供了幾種配置服務網格的方法,使應用程式可以或多或少地透明地成為服務在多個叢集中運行的網格的一部分,也就是在多叢集部署中。設定多叢集網格最簡單的方法,因為它沒有特殊的網路要求,是使用複製的控制平面模型。在此配置中,每個為網格做出貢獻的 Kubernetes 叢集都有自己的控制平面,但每個控制平面都在單一管理控制下同步運行。

在本文中,我們將探討 Istio 的其中一項功能,流量管理,如何在具有專用控制平面拓撲的多叢集網格中運作。我們將展示如何設定 Istio 路由規則,通過部署 Bookinfo 範例,其中 reviews 服務的 v1 版本在一個叢集中運行,而 v2v3 版本在第二個叢集中運行,來呼叫多叢集服務網格中的遠端服務。

設定叢集

首先,您需要兩個 Kubernetes 叢集,它們都運行稍微自訂的 Istio 設定。

cluster1 中部署 bookinfo 應用程式的 v1 版本

cluster1 中運行 productpagedetails 服務以及 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 服務的 v2v3 版本

$ 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 應用程式。

您應該看到帶有評論的 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: v1version: v2)。

在兩個叢集上為本機 reviews 服務建立目標規則

嚴格來說,我們只需要定義每個叢集中正在使用的本機服務的子集(即,cluster1 中的 v1cluster2 中的 v2v3),但為了簡單起見,我們將在兩個叢集中定義所有三個子集,因為定義未實際部署的版本子集沒有任何問題。

$ 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 版本 v2v3 (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 的身分登入。如果您多次重新整理頁面,您應該會看到顯示在黑色和紅色評分星星之間交替 (v2v3)。如果您登出,您將只會看到沒有評分的評論 (v1)。

總結

在本文中,我們已經了解如何使用 Istio 路由規則將服務的版本分散在具有複製控制平面模型的多叢集服務網格中的叢集之間。在本範例中,我們手動設定了提供與一個遠端服務 reviews 連線所需的 .global 服務條目和目標規則。但是,一般來說,如果我們希望任何服務都能夠在本機或遠端運行,我們需要為每個服務建立 .global 資源。幸運的是,這個過程可以自動化,並且很可能會在未來版本的 Istio 中實現。

分享這篇文章