8.5 KiB
title | description | weight | keywords | aliases | |||
---|---|---|---|---|---|---|---|
通过网关进行连接的多集群 | 在一个使用网关进行连接的多集群网格中配置远程服务。 | 20 |
|
|
这个示例展示了如何在多控制平面拓扑的多集群网格中 配置和调用远程服务。为了演示跨集群访问,会在一个集群中使用 Sleep 服务调用另一个集群中的 httpbin 服务。
开始之前
-
根据使用网关连接多控制平面的介绍,建立两个 Istio 网格组成的集群环境。
-
用
kubectl
的--context
参数来访问两个不同的集群。用下面的命令列出配置文件中的context
(上下文):{{< text bash >}} $ kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE
-
cluster1 cluster1 user@foo.com default cluster2 cluster2 user@foo.com default
{{< /text >}}
-
-
将配置文件中的上下文名称导出为环境变量:
{{< text bash >}} $ export CTX_CLUSTER1= $ export CTX_CLUSTER2= {{< /text >}}
配置示例服务
-
在
cluster1
中部署sleep
服务:{{< text bash >}} $ kubectl create --context=$CTX_CLUSTER1 namespace foo $ kubectl label --context=$CTX_CLUSTER1 namespace foo istio-injection=enabled $ kubectl apply --context=$CTX_CLUSTER1 -n foo -f @samples/sleep/sleep.yaml@ {{< /text >}}
-
在
cluster2
中部署httpbin
服务:{{< text bash >}} $ kubectl create --context=$CTX_CLUSTER2 namespace bar $ kubectl label --context=$CTX_CLUSTER2 namespace bar istio-injection=enabled $ kubectl apply --context=$CTX_CLUSTER2 -n bar -f @samples/httpbin/httpbin.yaml@ {{< /text >}}
-
导出
cluster2
的网关地址:{{< text bash >}}
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}") {{< /text >}}这个命令使用了网关的公网 IP,如果条件允许,这里使用 DNS 名称也是可以的
{{< tip >}} 如果
cluster2
正在一个不支持外部负载均衡的环境下运行,需要使用 nodePort 来完成对网关的访问。可以在控制 Ingress 流量一文中,找到获取网关地址和端口的说明。还需要把服务的入口端点用下面的步骤从 15443 更换为对应的 nodePort(也就是kubectl --context=$CTX_CLUSTER2 get svc -n istio-system istio-ingressgateway -o=jsonpath='{.spec.ports[?(@.port==15443)].nodePort}'
)。 {{< /tip >}} -
在
cluster1
中为httpbin
服务创建ServiceEntry
。为了让
cluster1
中的sleep
能够访问到cluster2
中的httpbin
,需要创建一个ServiceEntry
。ServiceEntry
的主机名称应该是<name>.<namespace>.global
的格式,其中的name
和namespace
代表的是远端服务的名称和命名空间。为了让 DNS 为
*.global
域的服务进行解析。必须给这些服务提供 IP 地址。{{< tip >}} (
.global
DNS 域)中的每个服务必须在集群内具有唯一的 IP 地址。 {{< /tip >}}如果这些全局服务具有真实的 VIP,可以直接使用;否则我们推荐使用 loopback 范围内的
127.0.0.0/8
。这些 IP 在 Pod 之外是不可路由的。在这个例子中我们会使用127.255.0.0/16
,这样就不会和一些知名地址例如127.0.0.1
重叠了。对这些 IP 的访问会被 Sidecar 截获,并路由到对应的远程服务之中。{{< text bash >}} $ kubectl apply --context=$CTX_CLUSTER1 -n foo -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: httpbin-bar spec: hosts:
必须是 name.namespace.global 的形式
- httpbin.bar.global
把远程集群服务作为网格的一部分。网格中的所有集群都有同样的信任关系。
location: MESH_INTERNAL ports:
- name: http1 number: 8000 protocol: http resolution: DNS addresses:
在一个集群内,httpbin.bar.global 应该对应唯一的远程服务 IP 地址。
这个地址不需要是可路由的。到这个 IP 的流量会被 Sidecar 截获和路由。
- 127.255.0.2 endpoints:
对于 sleep.bar 服务来说,这是一个 Cluster2 中的 Ingress gateway 的可路由地址。
从这个 Sidecar 中发出的流量会被路由到这个地址。
- address: ${CLUSTER2_GW_ADDR} ports: http1: 15443 # 不要修改端口值 EOF {{< /text >}}
上面的配置会把
cluster1
中所有到httpbin.bar.global
中所有端口的流量使用 mTLS 连接路由到<IPofCluster2IngressGateway>:15443
。端口 15443 的 Gateway 是一个定义了 SNI 感知的 Envoy,是开始之前一节中的多集群部署步骤中设置的。进入 15443 端口的流量在对应内部服务的 Pod 中做负载均衡(本例中就是
cluster
中的httpbin.bar
)。{{< warning >}} 不要为 15443 端口创建
Gateway
配置。 {{< /warning >}} -
从
sleep
服务中检查对httpbin
的访问:{{< text bash >}}
kubectl exec --context=$CTX_CLUSTER1
(kubectl get --context=$CTX_CLUSTER1 -n foo pod -l app=sleep -o jsonpath={.items..metadata.name})
-n foo -c sleep -- curl httpbin.bar.global:8000/ip {{< /text >}}
使用 Egress Gateway 向远程集群发送流量
如果要从 cluster1
中使用单独的 Egress Gateway 进行流量路由,而非直接通过 Sidecar 完成。可以用下面的 ServiceEntry
定义来替代前一节中的定义:
{{< tip >}} 这里定义的配置不能用于其它非跨集群的 Egress 流量。 {{< /tip >}}
{{< text bash >}} $ kubectl apply --context=$CTX_CLUSTER1 -n foo -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: httpbin-bar spec: hosts:
必须是 name.namespace.global 的形式
- httpbin.bar.global location: MESH_INTERNAL ports:
- name: http1 number: 8000 protocol: http resolution: DNS addresses:
- 127.255.0.2 endpoints:
- address: ${CLUSTER2_GW_ADDR} network: external ports: http1: 15443 # 不要修改端口值
- address: istio-egressgateway.istio-system.svc.cluster.local ports: http1: 15443 EOF {{< /text >}}
为远程服务提供分版本路由
如果远程服务具有多个版本,可以为 ServiceEntry
加入一个或多个标签,例如:
{{< text bash >}} $ kubectl apply --context=$CTX_CLUSTER1 -n foo -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: httpbin-bar spec: hosts:
必须是 name.namespace.global 这样的形式
- httpbin.bar.global location: MESH_INTERNAL ports:
- name: http1 number: 8000 protocol: http resolution: DNS addresses:
每个服务对 httpbin.bar.global 的解析地址必须是唯一的。
- 127.255.0.2 endpoints:
- address: ${CLUSTER2_GW_ADDR} labels: version: beta some: thing foo: bar ports: http1: 15443 # 不要修改这个端口号 EOF {{< /text >}}
接下来可以根据配置请求路由任务中的说明来创建对应的 VirtualService
和 DestinationRule
。DestinationRule
使用标签选择器来定义 httpbin.bar.global
服务的子集。具体步骤和本地服务是一致的。
清理
执行下列命令,清理示例服务。
-
清理
cluster1
:{{< text bash >}} $ kubectl delete --context=$CTX_CLUSTER1 -n foo -f @samples/httpbin/httpbin.yaml@ $ kubectl delete --context=$CTX_CLUSTER1 -n foo serviceentry httpbin-bar $ kubectl delete --context=$CTX_CLUSTER1 ns foo {{< /text >}}
-
清理
cluster2
:{{< text bash >}} $ kubectl delete --context=$CTX_CLUSTER2 -n bar -f @samples/httpbin/httpbin.yaml@ $ kubectl delete --context=$CTX_CLUSTER2 ns bar {{< /text >}}