12.5.4 跨集群的版本路由

通过前面的章节,我们已经了解了Istio的很多功能,例如基本版本的路由等,可以在单个Kubernetes集群上很容易地实现。而很多真实的业务场景中,基于微服务的应用程序并非那么简单,而是需要在多个位置跨集群去分配和运行服务。那么问题就来了,是否Istio的这些功能同样可以很简单地运行在这些真实的复杂环境中呢?

下面我们将会通过一个示例来了解Istio的流量管理功能如何在具有多个控制平面拓扑的多集群网格中正常运行。

1)首先,部署版本v1的helloworld服务到第一个集群cluster1中,执行如下命令:


kubectl create namespace hello
kubectl label namespace hello istio-injection=enabled
kubectl apply -n hello -f samples/sleep/sleep.yaml
kubectl apply -n hello -f samples/helloworld/service.yaml
kubectl apply -n hello -f samples/helloworld/helloworld.yaml -l version=v1

2)部署版本v2与v3的helloworld服务到第二个集群cluster2中,执行如下命令:


kubectl create namespace hello
kubectl label namespace hello istio-injection=enabled
kubectl apply -n hello -f samples/helloworld/service.yaml
kubectl apply -n hello -f samples/helloworld/helloworld.yaml -l version=v2
kubectl apply -n hello -f samples/helloworld/helloworld.yaml -l version=v3

3)如前面章节中所述,多控制平面下,需要使用以.global为后缀的DNS名称访问远程服务。在我们的例子中,它是helloworld.hello.global,所以我们需要在集群cluster1中创建服务条目ServiceEntry和目标规则DestinationRule。服务条目ServiceEntry将使用集群cluster2的入口网关作为端点地址来访问服务。

通过使用以下命令在集群cluster1中创建helloworld服务对应的服务条目ServiceEntry和目标规则DestinationRule:


kubectl apply -n hello -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: helloworld
spec:
  hosts:
  - helloworld.hello.global
  location: MESH_INTERNAL
  ports:
  - name: http1
    number: 5000
    protocol: http
  resolution: DNS
  addresses:
  - 127.255.0.8
  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: helloworld-global
spec:
  host: helloworld.hello.global
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v2
    labels:
      cluster: cluster2
  - name: v3
    labels:
      cluster: cluster2
EOF

4)在两个集群上创建目标规则。在集群cluster1中创建子集v1对应的目标规则,执行如下命令:


kubectl apply -n hello -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: helloworld
spec:
  host: helloworld.hello.svc.cluster.local
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v1
    labels:
      version: v1
EOF

而在集群cluster2中创建子集v2和v3对应的目标规则,执行如下命令:


kubectl apply -n hello -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: helloworld
spec:
  host: helloworld.hello.svc.cluster.local
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3
EOF

5)创建虚拟服务以路由流量。应用下面的虚拟服务将会使得来自用户jason对helloworld的流量请求指向位于集群cluster2中的版本v2和v3,其中v2比例为70%,v3比例为30%;来自任何其他用户对helloworld的流量请求都将转到位于集群cluster1中的版本v1:


kubectl apply -n hello -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
    - helloworld.hello.svc.cluster.local
    - helloworld.hello.global
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: helloworld.hello.global
        subset: v2
      weight: 70
    - destination:
        host: helloworld.hello.global
        subset: v3
      weight: 30
  - route:
    - destination:
        host: helloworld.hello.svc.cluster.local
        subset: v1
EOF

执行多次调用,可以从下面的执行结果中看出,上述流量路由的规则生效,这也说明了在多控制平面拓扑下,用于路由的规则定义与在本地集群的使用方式是一样的:

设置多集群网格的最简单方法是使用多控制平面拓扑,因为它没有特殊的网络要求。通过上述示例可以看出,在单个Kubernetes集群上运行的路由功能同样很容易地在多个集群中使用运行。