您正在查看 Anthos Service Mesh 1.8 的文档。查看最新文档或选择其他可用版本:

Anthos Service Mesh 上的多集群 GKE 配置

本指南介绍如何使用 Mesh CACitadel 以及启用跨集群负载平衡将两个集群联接到单个 Anthos Service Mesh。您可以轻松扩展此流程,将任意数量的集群整合到网格中。

多集群 Anthos Service Mesh 配置可以满足一些重要企业场景,例如扩缩、位置和隔离。如需了解详情,请参阅多集群用例。此外,您还应优化您的应用,以充分利用服务网格。如需了解详情,请参阅准备适用于 Anthos Service Mesh 的应用

前提条件

本指南假定您有两个或多个满足以下要求的 Google Cloud GKE 集群:

  • 集群上安装有 Anthos Service Mesh 1.6.8 或更高版本。
    • 如果您的集群位于同一项目中,请参阅安装概览以安装集群或将其升级到所需的版本。
    • 如果您的集群位于不同的项目中,请参阅多项目安装和迁移以安装集群或将其升级到所需的版本。
  • 如果您要联接的集群不在同一个项目中,则必须使用 asm-gcp-multiproject 配置文件进行安装,并且这些集群必须位于同一网络的共享 VPC 配置中。此外,我们建议您用一个项目托管共享 VPC,以及两个服务项目用于创建集群的。如需了解详情,请参阅通过共享 VPC 设置集群
  • 如果您使用 Citadel CA,请对这两个集群使用同一自定义根 CA。
  • 如果您的 Anthos Service Mesh 基于专用集群构建,我们建议您在同一 VPC 中创建单个子网否则您必须确保:
    1. 控制层面可以通过集群专用 IP 访问远程专用集群控制层面。
    2. 您可以将调用控制层面的 IP 范围添加到远程专用集群的已获授权的网络。如需了解详情,请参阅在专用集群之间配置端点发现

设置项目和集群变量

  1. 为方便起见,请设置工作文件夹。这是您在之前的步骤准备安装 Anthos Service Mesh 中下载并解压缩 Anthos Service Mesh 文件的文件夹。

    export PROJECT_DIR=YOUR_WORKING_FOLDER
  2. 为每个集群创建上下文变量。上下文是由集群项目 ID、集群名称和位置构成的字符串。对于位置值,请使用集群的位置,例如 us-west2-a。在此示例中,网格包含一个集群,您需要向网格添加另一个集群:

    export CTX_1=gke_CLUSTER_1_PROJECT_ID_CLUSTER_1_LOCATION_CLUSTER_1_NAME
    export CTX_2=gke_CLUSTER_2_PROJECT_ID_CLUSTER_2_LOCATION_CLUSTER_2_NAME

在集群之间配置端点发现

使用以下命令为跨集群负载平衡配置端点发现。此步骤执行以下任务:

  • istioctl 命令会创建密钥,以授予对集群的 Kube API 服务器的访问权限。
  • kubectl 命令将密钥应用于另一个集群,以便第二个集群从第一个集群中读取服务端点。
istioctl x create-remote-secret --context=${CTX_1} --name=${CLUSTER_1_NAME} | \
  kubectl apply -f - --context=${CTX_2}
istioctl x create-remote-secret --context=${CTX_2} --name=${CLUSTER_2_NAME} | \
  kubectl apply -f - --context=${CTX_1}

在专用集群之间配置端点发现

使用专用集群时,您必须配置远程集群的专用 IP 而不是公共 IP,因为公共 IP 无法访问。

  1. 将包含公共 IP 的 Secret 写入临时文件:

    istioctl x create-remote-secret --context=${CTX_1} --name=${CLUSTER_1_NAME} > ${CTX_1}.secret
    
    istioctl x create-remote-secret --context=${CTX_2} --name=${CLUSTER_2_NAME} > ${CTX_2}.secret
    
  2. 检索专用集群的专用 IP,然后使用它们替换临时文件夹的 Secret 中的公共 IP:

    IFS="_" read -r -a VALS <<< ${CTX_1}
    PROJECT_1=${VALS[1]}
    LOCATION_1=${VALS[2]}
    CLUSTER_1=${VALS[3]}
    PRIV_IP=`gcloud container clusters describe "${CLUSTER_1}" --project "${PROJECT_1}" \
        --zone "${LOCATION_1}" --format "value(privateClusterConfig.privateEndpoint)"`
    sed -i 's/server\:.*/server\: https:\/\/'"${PRIV_IP}"'/' ${CTX_1}.secret
    
    IFS="_" read -r -a VALS <<< ${CTX_2}
    PROJECT_2=${VALS[1]}
    LOCATION_2=${VALS[2]}
    CLUSTER_2=${VALS[3]}
    PRIV_IP=`gcloud container clusters describe "${CLUSTER_2}" --project "${PROJECT_2}" \
        --zone "${LOCATION_2}" --format "value(privateClusterConfig.privateEndpoint)"`
    sed -i 's/server\:.*/server\: https:\/\/'"${PRIV_IP}"'/' ${CTX_2}.secret
    
  3. 将新 Secret 应用到集群中:

    kubectl apply -f ${CTX_1}.secret --context=${CTX_2}
    
    kubectl apply -f ${CTX_2}.secret --context=${CTX_1}
    

为专用集群配置授权网络

仅当您的网格符合以下所有条件时,才应遵循此部分:

在 Anthos Service Mesh 中部署多个集群时,每个集群中的 Istiod 需要调用远程集群的 GKE 控制层面。要允许流量,您需要将调用集群中的 pod 地址范围添加到远程集群的授权网络。

  1. 获取每个集群的 pod IP CIDR 地址块:

    POD_IP_CIDR_1=`gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \
      --format "value(ipAllocationPolicy.clusterIpv4CidrBlock)"`
    
    POD_IP_CIDR_2=`gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \
      --format "value(ipAllocationPolicy.clusterIpv4CidrBlock)"`
    
  2. 将 Kubernetes 集群 pod IP CIDR 地址块添加到远程集群:

    EXISTING_CIDR_1=`gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \
     --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"`
    gcloud container clusters update ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \
    --enable-master-authorized-networks \
    --master-authorized-networks ${POD_IP_CIDR_2},${EXISTING_CIDR_1//;/,}
    
    EXISTING_CIDR_2=`gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \
     --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"`
    gcloud container clusters update ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \
    --enable-master-authorized-networks \
    --master-authorized-networks ${POD_IP_CIDR_1},${EXISTING_CIDR_2//;/,}
    

    如需了解详情,请参阅创建具有授权网络的集群

  3. 验证授权网络是否已更新:

    gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \
     --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"
    
    gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \
     --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"
    

启用控制平面全球访问权限

仅当您的网格符合以下所有条件时,才应遵循此部分:

  • 您使用的是专用集群。
  • 网格中的集群使用不同的区域。

您必须启用控制平面全球访问权限,以允许每个集群中的 istiod 调用远程集群的 GKE 控制平面。

  1. 启用控制平面全球访问权限:

    gcloud container clusters update ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \
     --enable-master-global-access
    
    gcloud container clusters update ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \
     --enable-master-global-access
    
  2. 验证控制平面是否已启用访问权限:

    gcloud container clusters describe ${CLUSTER_1} --zone ${LOCATION_1}
    
    gcloud container clusters describe ${CLUSTER_2} --zone ${LOCATION_2}
    

    输出中的 privateClusterConfig 部分显示 masterGlobalAccessConfig 的状态。

打开跨子网流量的端口

仅当您的网格符合以下所有条件时,才应遵循此部分:

  • 网格中的集群使用不同的子网。
  • pod 会打开除 443 和 15002 以外的端口。

GKE 会自动向每个节点添加防火墙规则,以允许同一子网内的流量。如果网格包含多个子网,您必须明确设置防火墙规则以允许跨子网流量。您必须为每个子网添加新的防火墙规则,以允许所有传入流量的来源 IP CIDR 地址块和目标端口。

创建防火墙规则:

TARGET_TAG_1=`gcloud compute firewall-rules list --filter="name~gke-${CLUSTER_1}-[0-9a-z]*-master" --format 'value(targetTags)'`
NEW_FIREWALL_NAME_1=new_firewall_name_1

gcloud compute firewall-rules create ${NEW_FIREWALL_NAME_1} \
    --action ALLOW \
    --direction INGRESS \
    --source-ranges ${POD_IP_CIDR_2} \
    --rules protocol:port[,protocol,port] \
    --target-tags ${TARGET_TAG_1}
TARGET_TAG_2=`gcloud compute firewall-rules list --filter="name~gke-${CLUSTER_2}-[0-9a-z]*-master" --format "value(targetTags)"`
NEW_FIREWALL_NAME_2=new_firewall_name_2
gcloud compute firewall-rules create ${NEW_FIREWALL_NAME_2} \
    --action ALLOW \
    --direction INGRESS \
    --source-ranges ${POD_IP_CIDR_1} \
    --rules protocol:port[,protocol,port] \
    --target-tags ${TARGET_TAG_2}

其中:

  • protocol:port 是所需的端口及其协议(tcpudp)。

验证您的部署

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

启用 Sidecar 注入

  1. 使用以下命令查找 istiod 服务中使用的修订版本标签值,您将在后续步骤中用到该值。

    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 服务

在每个集群中创建示例命名空间和服务定义。 在以下命令中,将 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.

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

    kubectl create --context=${CTX_1} \
        -f ${PROJECT_DIR}/samples/helloworld/helloworld.yaml \
        -l service=helloworld -n sample
    
    kubectl create --context=${CTX_2} \
        -f ${PROJECT_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 ${PROJECT_DIR}/samples/helloworld/helloworld.yaml \
      -l version=v1 -n sample
    kubectl create --context=${CTX_2} \
      -f ${PROJECT_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 ${PROJECT_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}')" \
        -- curl -sS helloworld.sample:5000/hello
    

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

    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}')" \
        -- curl -sS helloworld.sample:5000/hello
    

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

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

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

清理 HelloWorld 服务

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

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