多集群服务网格中的版本路由

在多集群服务网格中配置 Istio 路由规则。

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

如果您花时间研究 Istio,您可能已经注意到它包含许多功能,这些功能可以通过在单个 Kubernetes 集群上运行的简单任务示例进行演示。由于大多数(如果不是全部)现实世界的云和基于微服务的应用程序并不那么简单,并且需要将服务分布并在多个位置运行,因此您可能想知道在您的真实生产环境中所有这些事情是否同样简单。

幸运的是,Istio 提供了几种方法来配置服务网格,以便应用程序或多或少地透明地成为网格的一部分,其中服务运行在多个集群中,即在多集群部署中。由于没有特殊的网络要求,因此设置多集群网格最简单的方法是使用复制的控制平面模型。在此配置中,每个为网格做出贡献的 Kubernetes 集群都有自己的控制平面,但每个控制平面都同步并在单个管理控制下运行。

在本文中,我们将了解 Istio 的一项功能,即流量管理,如何在具有专用控制平面拓扑的多集群网格中工作。我们将展示如何配置 Istio 路由规则以调用多集群服务网格中的远程服务,方法是部署Bookinfo 示例,其中版本v1reviews服务运行在一个集群中,版本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上为远程评论服务创建服务条目和目标规则

设置说明中所述,远程服务使用.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)。

在两个集群上为本地评论服务创建目标规则

从技术上讲,我们只需要定义每个集群中正在使用的本地服务的子集(即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 Pod(v1),因为如果您查看源代码,您会发现productpage实现只是对http://reviews:9080(扩展为主机reviews.default.svc.cluster.local)发出请求,即服务的本地版本。相应的远程服务名为reviews.default.global,因此需要路由规则将请求重定向到全局主机。

应用以下虚拟服务,将用户jason的流量引导到reviews版本v2v3(50/50),它们运行在cluster2上。任何其他用户的流量都将转到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 版本中实现。

分享此文章