在 Google Cloud 外部设置多集群网格

本指南介绍如何为以下平台设置多集群网格:

  • GKE on VMware
  • Google Distributed Cloud Virtual for Bare Metal
  • GKE on AWS
  • Amazon EKS

本指南介绍如何设置两个集群,但您可以扩展此过程,将任意数量的集群加入网格中。

准备工作

本指南假设您使用 asmcli install 安装了 Anthos Service Mesh。您需要 asmcliasmcli 下载到您运行 asmcli install 时在 --output_dir 中指定的目录的配置软件包。如果需要进行设置,请按照安装依赖工具并验证集群中的步骤操作:

您需要访问要在网格中设置的所有集群的 kubeconfig 文件。

设置环境变量和占位符

安装东-西网关时,您需要以下环境变量。

  1. 为项目编号创建环境变量。在以下命令中,将 FLEET_PROJECT_ID 替换为舰队宿主项目的项目 ID。

    export PROJECT_NUMBER=$(gcloud projects describe FLEET_PROJECT_ID --format="value(projectNumber)")
    
  2. 为网格标识符创建环境变量。

    export MESH_ID="proj-${PROJECT_NUMBER}"
    
  3. 按照 asmcli 要求的格式,为集群名称创建环境变量。

    export CLUSTER_1="cn-FLEET_PROJECT_ID-global-CLUSTER_NAME_1"
    export CLUSTER_2="cn-FLEET_PROJECT_ID-global-CLUSTER_NAME_2"
    
  4. 使用此命令输出中 NAME 列下的值获取集群的上下文名称:

    kubectl config get-contexts
  5. 将环境变量设置为集群上下文名称,本指南后面将在许多步骤中用到这些环境变量:

    export CTX_1=CLUSTER1_CONTEXT_NAME
    export CTX_2=CLUSTER2_CONTEXT_NAME
    

安装东-西网关

在以下命令中:

  • CLUSTER_NAME_1CLUSTER_NAME_2 替换为您集群的名称。

  • PATH_TO_KUBECONFIG_1PATH_TO_KUBECONFIG_2 替换为您集群的 kubeconfig 文件。

Mesh CA 或 CA Service

  1. 在 cluster1 中安装专用于到 $CLUSTER_2东西流量的网关。默认情况下,此网关在互联网上为公开。生产系统可能需要额外的访问限制(例如防火墙规则),以防止外部攻击。

    asm/istio/expansion/gen-eastwest-gateway.sh \
        --mesh ${MESH_ID} \
        --cluster ${CLUSTER_1} \
        --network default \
        --revision asm-1139-10 | \
        ./istioctl --kubeconfig=PATH_TO_KUBECONFIG_1 install -y --set spec.values.global.pilotCertProvider=kubernetes -f -
    
  2. $CLUSTER_2 中安装专用于 $CLUSTER_1 的东-西流量的网关。

    asm/istio/expansion/gen-eastwest-gateway.sh \
        --mesh ${MESH_ID} \
        --cluster ${CLUSTER_2} \
        --network default \
        --revision asm-1139-10 | \
        ./istioctl install --kubeconfig=PATH_TO_KUBECONFIG_2 -y --set spec.values.global.pilotCertProvider=kubernetes -f -
    

Istio CA

  1. 在 cluster1 中安装专用于到 $CLUSTER_2东西流量的网关。默认情况下,此网关在互联网上为公开。生产系统可能需要额外的访问限制(例如防火墙规则),以防止外部攻击。

    asm/istio/expansion/gen-eastwest-gateway.sh \
        --mesh ${MESH_ID} \
        --cluster ${CLUSTER_1} \
        --network default \
        --revision asm-1139-10 | \
        ./istioctl --kubeconfig=PATH_TO_KUBECONFIG_1 install -y -f -
    
  2. $CLUSTER_2 中安装专用于 $CLUSTER_1 的东-西流量的网关。

    asm/istio/expansion/gen-eastwest-gateway.sh \
        --mesh ${MESH_ID} \
        --cluster ${CLUSTER_2} \
        --network default \
        --revision asm-1139-10 | \
        ./istioctl --kubeconfig=PATH_TO_KUBECONFIG_2 install -y -f -
    

公开服务

由于集群位于不同的网络中,因此您需要在这两个集群中的东-西网关上公开所有服务 (*.local)。虽然此网关在互联网上为公开,但只有具有可信 mTLS 证书和工作负载 ID 的服务才能访问其背后的服务,就像它们位于同一网络上一样。

  1. 通过 CLUSTER_NAME_1 的东-西网关公开服务。

    kubectl --kubeconfig=PATH_TO_KUBECONFIG_1 apply -n istio-system -f \
        asm/istio/expansion/expose-services.yaml
    
  2. 通过 CLUSTER_NAME_2 的东-西网关公开服务。

    kubectl --kubeconfig=PATH_TO_KUBECONFIG_2 apply -n istio-system -f \
        asm/istio/expansion/expose-services.yaml
    

启用端点发现

运行 asmcli create-mesh 命令以启用端点发现。此示例仅显示两个集群,但您可以运行此命令在更多集群上启用端点发现,但需遵循 GKE Hub 服务限制

  ./asmcli create-mesh \
      FLEET_PROJECT_ID \
      PATH_TO_KUBECONFIG_1 \
      PATH_TO_KUBECONFIG_2

验证多集群连接

本部分介绍如何将示例 HelloWorldSleep 服务部署到多集群环境,以验证跨集群负载均衡可正常工作。

启用边车代理注入

  1. 找到修订版本标签值,您将在后面的步骤中用到该值。该步骤取决于您的 Anthos Service Mesh 类型(代管式或集群内)。

    代管式

    使用以下命令找到修订版本标签,您将在后面的步骤中用到该标签。

    kubectl get controlplanerevision -n istio-system

    输出类似于以下内容:

     NAME                RECONCILED   STALLED   AGE
     asm-managed-rapid   True         False     89d
     

    在输出中的 NAME 列下,记下修订版本标签的值。在此示例中,该值为 asm-managed-rapid。在下一部分的步骤中使用该修订版本值。

    集群内

    使用以下命令找到修订版本标签,您将在后面的步骤中用到该标签。

    kubectl -n istio-system get pods -l app=istiod --show-labels

    输出类似于以下内容:

     NAME                                READY   STATUS    RESTARTS   AGE   LABELS
     istiod-asm-173-3-5788d57586-bljj4   1/1     Running   0          23h   app=istiod,istio.io/rev=asm-173-3,istio=istiod,pod-template-hash=5788d57586
     istiod-asm-173-3-5788d57586-vsklm   1/1     Running   1          23h   app=istiod,istio.io/rev=asm-173-3,istio=istiod,pod-template-hash=5788d57586
     

    在输出中的 LABELS 列下,记下 istiod 修订版本标签的值,该值位于前缀 istio.io/rev= 之后。在此示例中,该值为 asm-173-3。在下一部分的步骤中使用该修订版本值。

安装 HelloWorld 服务

  1. 在每个集群中创建示例命名空间和服务定义。 在以下命令中,将 REVISION 替换为您在上一步中记下的 istiod 修订版本标签。

    for CTX in ${CTX_1} ${CTX_2}
    do
        kubectl create --context=${CTX} namespace sample
        kubectl label --context=${CTX} namespace sample \
            istio-injection- istio.io/rev=REVISION --overwrite
    done
    

    其中,REVISION 是您之前记下的 istiod 修订版本标签。

    输出如下:

    label "istio-injection" not found.
    namespace/sample labeled
    

    您可以安全地忽略 label "istio-injection" not found.

  2. 在这两个集群中创建 HelloWorld 服务:

    kubectl create --context=${CTX_1} \
        -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \
        -l service=helloworld -n sample
    
    kubectl create --context=${CTX_2} \
        -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \
        -l service=helloworld -n sample
    

将 HelloWorld v1 和 v2 部署到每个集群

  1. HelloWorld v1 部署到 CLUSTER_1,并将 v2 部署到 CLUSTER_2,这可帮助以后验证跨集群负载均衡:

    kubectl create --context=${CTX_1} \
      -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \
      -l version=v1 -n sample
    kubectl create --context=${CTX_2} \
      -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \
      -l version=v2 -n sample
  2. 使用以下命令确认 HelloWorld v1v2 正在运行。验证输出是否如下所示:

    kubectl get pod --context=${CTX_1} -n sample
    NAME                            READY     STATUS    RESTARTS   AGE
    helloworld-v1-86f77cd7bd-cpxhv  2/2       Running   0          40s
    kubectl get pod --context=${CTX_2} -n sample
    NAME                            READY     STATUS    RESTARTS   AGE
    helloworld-v2-758dd55874-6x4t8  2/2       Running   0          40s

部署 Sleep 服务

  1. Sleep 服务部署到这两个集群。此 pod 将出于演示目的生成虚假网络流量:

    for CTX in ${CTX_1} ${CTX_2}
    do
        kubectl apply --context=${CTX} \
            -f ${SAMPLES_DIR}/samples/sleep/sleep.yaml -n sample
    done
    
  2. 等待在每个集群中启动 Sleep 服务。验证输出是否如下所示:

    kubectl get pod --context=${CTX_1} -n sample -l app=sleep
    NAME                             READY   STATUS    RESTARTS   AGE
    sleep-754684654f-n6bzf           2/2     Running   0          5s
    kubectl get pod --context=${CTX_2} -n sample -l app=sleep
    NAME                             READY   STATUS    RESTARTS   AGE
    sleep-754684654f-dzl9j           2/2     Running   0          5s

验证跨集群负载均衡

多次调用 HelloWorld 服务,并检查输出以验证来自 v1 和 v2 的交替回复:

  1. 调用 HelloWorld 服务:

    kubectl exec --context="${CTX_1}" -n sample -c sleep \
        "$(kubectl get pod --context="${CTX_1}" -n sample -l \
        app=sleep -o jsonpath='{.items[0].metadata.name}')" \
        -- /bin/sh -c 'for i in $(seq 1 20); do curl -sS helloworld.sample:5000/hello; done'
    

    输出类似于如下所示内容:

    Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8
    Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv
    ...
  2. 再次调用 HelloWorld 服务:

    kubectl exec --context="${CTX_2}" -n sample -c sleep \
        "$(kubectl get pod --context="${CTX_2}" -n sample -l \
        app=sleep -o jsonpath='{.items[0].metadata.name}')" \
        -- /bin/sh -c 'for i in $(seq 1 20); do curl -sS helloworld.sample:5000/hello; done'
    

    输出类似于如下所示内容:

    Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8
    Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv
    ...

恭喜,您已成功验证负载均衡的多集群 Anthos Service Mesh!

清理

完成负载均衡验证后,请从集群中移除 HelloWorldSleep 服务。

kubectl delete ns sample --context ${CTX_1}
kubectl delete ns sample --context ${CTX_2}