在多个 GKE 集群上配置 Traffic Director(使用共享 VPC)

本教程介绍如何配置 Traffic Director,以在共享 VPC 网络的多个项目中运行的服务间实现服务到服务的通信。本教程适用于网络管理员和 Google Kubernetes Engine (GKE) 平台管理员。

企业通常将其资源分成多个 Google Cloud 项目,这些项目按团队、应用或环境(例如开发、预演和生产环境)分隔资源。每个 Google Cloud 项目都带有自己的默认 Virtual Private Cloud (VPC),供 Google Cloud 资源(例如 Compute Engine 实例和 GKE 集群)使用。

通过共享 VPC,您无需在每个项目中管理多个 VPC,而是将所有 VPC 资源(子网、防火墙规则、负载平衡器)集中在一个宿主项目中,然后在其他名为“服务项目”的项目中共享网络资源。这种方法使网络管理员可以集中管理所有网络资源,同时为团队、应用和环境提供项目级分区。要授予项目所需的访问网络资源的权限,您可以使用服务帐号来配置服务项目的身份和访问权限管理 (IAM) 权限。

下图显示了一个共享 VPC 宿主项目,该项目将四个子网共享到两个服务项目(每个项目两个子网),包括每个项目的 IP 地址。

共享 VPC 宿主项目将四个子网共享到两个服务项目。

在某些情况下,在多个服务项目中运行的服务之间需要进行服务到服务的通信。只要跨服务项目的实例连接到同一 VPC,就可以通过配置 VPC 防火墙规则来建立可达性。对于在 GKE 集群中运行的服务,您可以使用 Traffic Director 在多个 GKE 集群、多个项目和多个地区中运行的服务之间创建服务网格。Traffic Director 充当服务网格控制平面,它将配置在 GKE 集群中运行的每个 pod 中作为 Sidecar 容器运行的 Envoy 代理。Envoy 代理 Sidecar 拦截在每个 pod 中运行的应用容器发出的所有请求,并在 GKE 集群之间连接服务。您还可以针对 Compute Engine 实例中运行的服务使用 Traffic Director。

在本教程中,您将创建并设置包含两个服务项目的共享 VPC。通过使用共享 VPC,您将创建两个 GKE 集群,每个服务项目中一个,且位于不同地区中。您可以配置示例服务,其中 Envoy 代理作为 Sidecar 运行。您还可以通过配置 Traffic Director 来配置 Envoy 代理,以在 GKE 集群之间进行服务到服务的通信。

下图显示了一个共享 VPC 宿主项目,该项目将四个子网共享给两个服务项目,每个服务项目两个子网。

一个共享 VPC 宿主项目将四个子网共享给两个服务项目,每个服务项目两个子网。

每个服务项目都包含一个 GKE 集群,其中包括一个示例应用 pod 和一个 BusyBox pod。在每个应用 pod 中运行的 Envoy Sidecar 代理跨地区和集群通过网络进行连接。

目标

  • 创建一个宿主项目和两个服务项目。
  • 在具有两个子网的宿主项目中创建一个共享 VPC。GKE 集群使用的两个服务项目各有一个子网。
  • 使用共享 VPC 中的子网创建两个 GKE 集群,每个服务项目一个。
  • 通过在具有 Envoy Sidecar 代理的两个集群中使用 httpbin 来部署示例应用。在两个集群中部署 BusyBox pod 以测试连接性。
  • 配置 Traffic Director 以允许所有服务之间的网络连接。
  • 确认服务可以跨 GKE 集群和服务项目进行通信。

费用

本教程使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用量来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

准备工作

如需在 Google Cloud 中配置共享 VPC,请确保您在 Google Cloud 上具有以下资源和角色:

  • 组织资源,它是 Google Cloud 资源层次结构中的根节点,也是项目的分层超级节点。如需创建组织资源,请按照获取组织资源中的说明进行操作。只能在组织资源中的项目之间创建共享 VPC。
  • 您的用户在组织级层具有以下 IAM 角色
    • Project Creator (roles/resourcemanager.projectCreator)。创建宿主和服务项目。
    • Editor (roles/editor)。在组织中的 Cloud 项目中创建和删除资源。
    • Project Billing Manager (roles/billing.projectManager)。将结算帐号分配给组织中的项目。此角色不允许您创建结算帐号,但您可以将现有结算帐号分配给项目。如果您需要创建新的结算帐号,请使用 Billing Account Administrator (roles/billing.admin) 角色。
    • Compute Admin (roles/compute.admin)。为组织内的所有项目创建网络资源(VPC、子网、防火墙规则)。
    • Project IAM Admin (roles/resourcemanager.projectIamAdmin)。管理组织中所有项目的 IAM 政策。
    • Project Deleter (roles/resourcemanager.projectDeleter)。(可选)删除组织中的项目。

如需设置上述资源和角色,请按以下步骤操作:

  1. 转到管理资源页面。

    转到“管理资源”页面

  2. 选择您的 Google Cloud 组织,然后将组织 ID 编号从 ID 列复制到记事本或文件中。您稍后将在本教程中使用此 ID 编号。

  3. 在与您的组织相同的行上,点击 ,然后点击设置

  4. IAM 和管理页面上,点击 IAM。确保在组织级层为您的用户提供适当的 IAM 角色。

    列出了特定用户的角色列表。

  5. 在 Cloud Console 中,激活 Cloud Shell。

    激活 Cloud Shell

  6. 确认您已使用具有您在步骤 4 中配置的角色的同一用户名进行登录:

    gcloud info --format=json | jq '.config.account'
    
  7. 获取用于 Cloud 项目的结算帐号:

    gcloud beta billing accounts list
    

    输出类似于以下内容:

    ACCOUNT_ID            NAME                    OPEN  MASTER_ACCOUNT_ID
    1337A-1337A-1337A     My Billing Account      True
    

    将该结算帐号 ID 复制到记事本或文件中。下一步中会用到此编号。

  8. 为组织 ID 和结算帐号 ID 设置环境变量:

    export ORG_ID=ORG_ID_NUMBER
    export BILLING_ID=BILLING_ACCOUNT_ID
    

    替换以下内容:

    • ORG_ID_NUMBER:步骤 2 中的组织 ID
    • BILLING_ACCOUNT_ID:步骤 7 中的结算帐号 ID

在下一部分中,您将在组织中创建资源。

设置环境

在本部分中,您将在 Google Cloud 组织中创建三个项目:在其中配置共享 VPC 的宿主项目和两个使用共享 VPC 资源的服务项目。

创建项目和结算

  1. 在 Cloud Shell 中,在您的 Google Cloud 组织中创建三个项目:

    export RANDOM_PERSIST=$RANDOM
    export HOST_PROJECT="td-${ORG_ID}-${RANDOM_PERSIST}-host-prj"
    export SVC_PROJECT_1="td-${ORG_ID}-${RANDOM_PERSIST}-svc-prj1"
    export SVC_PROJECT_2="td-${ORG_ID}-${RANDOM_PERSIST}-svc-prj2"
    gcloud projects create ${HOST_PROJECT} --organization=${ORG_ID}
    gcloud projects create ${SVC_PROJECT_1} --organization=${ORG_ID}
    gcloud projects create ${SVC_PROJECT_2} --organization=${ORG_ID}
    

    在前述命令中定义的项目变量必须表示这三个项目的项目 ID。

  2. 为所有三个项目启用结算:

    gcloud beta billing projects link ${HOST_PROJECT} \
        --billing-account ${BILLING_ID}
    gcloud beta billing projects link ${SVC_PROJECT_1} \
        --billing-account ${BILLING_ID}
    gcloud beta billing projects link ${SVC_PROJECT_2} \
        --billing-account ${BILLING_ID}
    
  3. 为所有项目启用 GKE 和 Traffic Director API:

    gcloud services enable container.googleapis.com trafficdirector.googleapis.com --project $HOST_PROJECT
    gcloud services enable container.googleapis.com trafficdirector.googleapis.com --project $SVC_PROJECT_1
    gcloud services enable container.googleapis.com trafficdirector.googleapis.com --project $SVC_PROJECT_2
    

获取 Google Cloud 服务帐号

每个 Cloud 项目都带有几个默认服务帐号,这些帐号包含对各种资源的默认权限。以下是本教程中您所需的三个 Google 管理的默认服务帐号

您需要来自两个服务项目的服务帐号电子邮件,以便在宿主项目中创建 IAM 权限。这些权限使服务项目可以使用宿主项目中的资源(在本例中为共享 VPC)。这些服务帐号具有使用项目编号的标准命名约定。

  • 在 Cloud Shell 中,获取来自两个服务项目的两个服务帐号电子邮件:

    export SVC_PROJECT_1_NUM=$(gcloud projects list --format=json --filter="${SVC_PROJECT_1}" | jq -r '.[].projectNumber')
    export SVC_PROJECT_2_NUM=$(gcloud projects list --format=json --filter="${SVC_PROJECT_2}" | jq -r '.[].projectNumber')
    
    export SVC_PROJECT_1_COMPUTE_SA="${SVC_PROJECT_1_NUM}-compute@developer.gserviceaccount.com"
    export SVC_PROJECT_2_COMPUTE_SA="${SVC_PROJECT_2_NUM}-compute@developer.gserviceaccount.com"
    
    export SVC_PROJECT_1_GKE_SA="service-${SVC_PROJECT_1_NUM}@container-engine-robot.iam.gserviceaccount.com"
    export SVC_PROJECT_2_GKE_SA="service-${SVC_PROJECT_2_NUM}@container-engine-robot.iam.gserviceaccount.com"
    
    export SVC_PROJECT_1_API_SA="${SVC_PROJECT_1_NUM}@cloudservices.gserviceaccount.com"
    export SVC_PROJECT_2_API_SA="${SVC_PROJECT_2_NUM}@cloudservices.gserviceaccount.com"
    

创建 VPC 网络和子网

  1. 在 Cloud Shell 中,在名为 shared-vpc 的宿主项目中创建 VPC 网络。创建一个自定义模式 VPC,以便您可以手动创建子网。

    gcloud compute networks create shared-vpc \
        --subnet-mode custom \
        --project $HOST_PROJECT
    
  2. shared-vpc 资源中创建两个子网。两个服务项目中的 GKE 集群将各使用一个子网。为 GKE 节点创建一个主要范围,并创建两个次要范围:一个用于 GKE pod,另一个用于 GKE 服务。

    export REGION_1=us-west1
    export ZONE_1=us-west1-a
    export REGION_2=us-central1
    export ZONE_2=us-central1-a
    
    gcloud compute networks subnets create subnet-1 \
        --project $HOST_PROJECT \
        --network shared-vpc \
        --range 10.0.4.0/22 \
        --region ${REGION_1} \
        --secondary-range subnet-1-services=10.0.32.0/20,subnet-1-pods=10.4.0.0/14
    
    gcloud compute networks subnets create subnet-2 \
        --project $HOST_PROJECT \
        --network shared-vpc \
        --range 172.16.4.0/22 \
        --region ${REGION_2} \
        --secondary-range subnet-2-services=172.16.16.0/20,subnet-2-pods=172.20.0.0/14
    
  3. 针对 VPC 网络中的所有 IP 地址范围创建防火墙规则,以便 GKE pod 可以在所有端口和协议上相互通信。您可以将此规则限制为仅允许所需端口。

    gcloud compute firewall-rules create allow-gke-svc-1-all \
        --project ${HOST_PROJECT} \
        --network shared-vpc \
        --allow tcp,udp \
        --direction INGRESS \
        --source-ranges 10.0.4.0/22,10.4.0.0/14,10.0.32.0/20
    
    gcloud compute firewall-rules create allow-gke-svc-2-all \
        --project ${HOST_PROJECT} \
        --network shared-vpc \
        --allow tcp,udp \
        --direction INGRESS \
        --source-ranges 172.16.4.0/22,172.20.0.0/14,172.16.16.0/20
    
    gcloud compute firewall-rules create allow-healthchecks \
        --project ${HOST_PROJECT} \
        --network shared-vpc \
        --allow tcp,udp \
        --direction INGRESS \
        --source-ranges 130.211.0.0/22,35.191.0.0/16
    

    上述防火墙规则的前两个规则允许共享 VPC 网络中的 subnet-1subnet-2 网络连接。这种连接支持跨集群的 pod 到 pod IP 通信。第三个防火墙规则 allow-healthchecks 使 Cloud Load Balancing 能够先检查后端服务的运行状况,然后再向它们发送流量。Cloud Load Balancing 使用已知 IP 地址范围进行运行状况检查,这些 IP 地址范围配置为防火墙规则中 IP 地址的 source-ranges

创建共享 VPC

在本部分中,您将在宿主项目中启用和配置共享 VPC。您还将配置 IAM 权限,使服务项目能够使用共享 VPC 中的资源。

启用共享 VPC

  1. 在 Cloud Shell 中,在宿主项目中启用共享 VPC:

    gcloud compute shared-vpc enable ${HOST_PROJECT}
    
  2. 将两个服务项目添加到共享 VPC:

    gcloud compute shared-vpc associated-projects add \
        ${SVC_PROJECT_1} \
        --host-project ${HOST_PROJECT}
    
    gcloud compute shared-vpc associated-projects add \
        ${SVC_PROJECT_2} \
        --host-project ${HOST_PROJECT}
    

配置 IAM 角色

  1. 在 Cloud Shell 中,创建一个工作文件夹 (WORKDIR)),您可以在其中创建与本部分关联的文件:

    mkdir -p ~/td-shared-vpc
    cd ~/td-shared-vpc
    port WORKDIR=$(pwd)
    
  2. 在宿主项目中配置 IAM 权限,以便服务项目可以使用共享 VPC 中的资源。

    在此步骤中,您将配置 IAM 权限,使服务项目 1 可以访问 subnet-1,服务项目 2 可以访问 subnet-2。您将 Compute Network User IAM 角色 (roles/compute.networkUser) 分配给每个子网的各服务项目中的 Compute Engine 计算默认服务帐号和 Google Cloud API 服务帐号。

    1. 对于服务项目 1,为 subnet-1 配置 IAM 权限:

      export SUBNET_1_ETAG=$(gcloud beta compute networks subnets get-iam-policy subnet-1 --project ${HOST_PROJECT} --region ${REGION_1} --format=json | jq -r '.etag')
      
      cat > subnet-1-policy.yaml <<EOF
      bindings:
      - members:
        - serviceAccount:${SVC_PROJECT_1_API_SA}
        - serviceAccount:${SVC_PROJECT_1_GKE_SA}
        role: roles/compute.networkUser
      etag: ${SUBNET_1_ETAG}
      EOF
      
      gcloud beta compute networks subnets set-iam-policy subnet-1 \
      subnet-1-policy.yaml \
          --project ${HOST_PROJECT} \
          --region ${REGION_1}
      
    2. 对于服务项目 2,为 subnet-2 配置 IAM 权限:

      export SUBNET_2_ETAG=$(gcloud beta compute networks subnets get-iam-policy subnet-2 --project ${HOST_PROJECT} --region ${REGION_2} --format=json | jq -r '.etag')
      
      cat > subnet-2-policy.yaml <<EOF
      bindings:
      - members:
        - serviceAccount:${SVC_PROJECT_2_API_SA}
        - serviceAccount:${SVC_PROJECT_2_GKE_SA}
        role: roles/compute.networkUser
      etag: ${SUBNET_2_ETAG}
      EOF
      
      gcloud beta compute networks subnets set-iam-policy subnet-2 \
      subnet-2-policy.yaml \
          --project ${HOST_PROJECT} \
          --region ${REGION_2}
      
  3. 对于每个服务项目,您必须将 Kubernetes Engine Host Service Agent User IAM 角色 (roles/container.hostServiceAgentUser) 授予宿主项目中的 GKE 服务帐号:

    gcloud projects add-iam-policy-binding ${HOST_PROJECT} \
        --member serviceAccount:${SVC_PROJECT_1_GKE_SA} \
        --role roles/container.hostServiceAgentUser
    
    gcloud projects add-iam-policy-binding ${HOST_PROJECT} \
        --member serviceAccount:${SVC_PROJECT_2_GKE_SA} \
        --role roles/container.hostServiceAgentUser
    

    此角色允许服务项目的 GKE 服务帐号使用宿主项目的 GKE 服务帐号来配置共享网络资源。

  4. 对于每个服务项目,向 Compute Engine 默认服务帐号授予宿主项目中的 Compute Network Viewer IAM 角色 (roles/compute.networkViewer)。

    gcloud projects add-iam-policy-binding ${SVC_PROJECT_1} \
        --member serviceAccount:${SVC_PROJECT_1_COMPUTE_SA} \
        --role roles/compute.networkViewer
    
    gcloud projects add-iam-policy-binding ${SVC_PROJECT_2} \
        --member serviceAccount:${SVC_PROJECT_2_COMPUTE_SA} \
        --role roles/compute.networkViewer
    

    Envoy Sidecar 代理连接到 xDS 服务 (Traffic Director API) 后,该代理将使用 Compute Engine 虚拟机主机或 GKE 节点实例的服务帐号。该服务帐号必须具有 compute.globalForwardingRules.get 项目级层 IAM 权限。使用 Compute Network Viewer 角色足以完成此步骤。

验证共享 VPC 配置

  1. 在 Cloud Shell 中,验证两个服务项目中的可用子网:

    gcloud container subnets list-usable \
        --project ${SVC_PROJECT_1} \
        --network-project ${HOST_PROJECT}
    

    输出类似于以下内容:

    PROJECT                       REGION    NETWORK     SUBNET    RANGE
    td-012345678-host-project  us-west1  shared-vpc  subnet-1  10.0.4.0/22
        ┌──────────────────────┬───────────────┬─────────────────────────────┐
        │ SECONDARY_RANGE_NAME │ IP_CIDR_RANGE │            STATUS           │
        ├──────────────────────┼───────────────┼─────────────────────────────┤
        │ subnet-1-pods        │ 10.4.0.0/14   │ usable for pods or services │
        │ subnet-1-services    │ 10.0.32.0/20  │ usable for pods or services │
        └──────────────────────┴───────────────┴─────────────────────────────┘
    

    如果未列出任何项,请稍等片刻,然后再次运行前面的命令:

    gcloud container subnets list-usable \
        --project ${SVC_PROJECT_2} \
        --network-project ${HOST_PROJECT}
    

    输出类似于以下内容:

    PROJECT                       REGION       NETWORK     SUBNET    RANGE
    td-012345678-host-project  us-central1  shared-vpc  subnet-2  172.16.4.0/22
        ┌──────────────────────┬────────────────┬─────────────────────────────┐
        │ SECONDARY_RANGE_NAME │ IP_CIDR_RANGE  │            STATUS           │
        ├──────────────────────┼────────────────┼─────────────────────────────┤
        │ subnet-2-pods        │ 172.20.0.0/14  │ usable for pods or services │
        │ subnet-2-services    │ 172.16.16.0/20 │ usable for pods or services │
        └──────────────────────┴────────────────┴─────────────────────────────┘
    

在前面的输出中,您可以看到服务项目 1 可以使用 subnet-1 及其辅助地址。同样,服务项目 2 可以使用 subnet-2 及其辅助地址。

现在,您可以在使用这些子网的服务项目中创建资源,例如 GKE 集群。

创建 GKE 集群

在本部分中,您将创建两个 GKE 集群,每个服务项目中创建一个。每个集群使用共享 VPC 中的一个子网。用于共享网络资源的宿主项目中没有集群。

  1. 在 Cloud Shell 中,创建两个 GKE 集群,每个服务项目中创建一个:

    export GKE_1="gke-svc-1"
    export GKE_2="gke-svc-2"
    
    gcloud container clusters create ${GKE_1} \
        --project ${SVC_PROJECT_1} \
        --zone=${ZONE_1} \
        --enable-ip-alias \
        --scopes "https://www.googleapis.com/auth/cloud-platform" \
        --network projects/${HOST_PROJECT}/global/networks/shared-vpc \
        --subnetwork projects/${HOST_PROJECT}/regions/${REGION_1}/subnetworks/subnet-1 \
        --cluster-secondary-range-name subnet-1-pods \
        --services-secondary-range-name subnet-1-services --async
    
    gcloud container clusters create ${GKE_2} \
        --project ${SVC_PROJECT_2} \
        --zone=${ZONE_2} \
        --enable-ip-alias \
        --scopes "https://www.googleapis.com/auth/cloud-platform" \
        --network projects/${HOST_PROJECT}/global/networks/shared-vpc \
        --subnetwork projects/${HOST_PROJECT}/regions/${REGION_2}/subnetworks/subnet-2 \
        --cluster-secondary-range-name subnet-2-pods \
        --services-secondary-range-name subnet-2-services
    
  2. 确认两个集群都在运行:

    gcloud container clusters list --project ${SVC_PROJECT_1}
    gcloud container clusters list --project ${SVC_PROJECT_2}
    

    对于 gke_svc_1,输出类似于以下内容:

    NAME       LOCATION    MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION   NUM_NODES  STATUS
    gke-svc-1  us-west1-a  1.13.10-gke.0   35.233.232.169  n1-standard-1  1.13.10-gke.0  3          RUNNING
    

    对于 gke-svc-2,输出类似于以下内容:

    NAME       LOCATION       MASTER_VERSION  MASTER_IP      MACHINE_TYPE   NODE_VERSION   NUM_NODES  STATUS
    gke-svc-2  us-central1-a  1.13.10-gke.0   35.232.172.85  n1-standard-1  1.13.10-gke.0  3          RUNNING
    
  3. 为本教程创建一个新的 kubeconfig 文件:

    touch td-kubeconfig
    
    export KUBECONFIG=td-kubeconfig
    

    运行此命令后,kubeconfig 文件将不会干扰您的默认 kubeconfig 文件。在本教程结束时,您可以删除 KUBECONFIG 环境变量并将其重置为默认值。

  4. kubeconfig 文件中为两个集群创建凭据,并将两个上下文存储在变量中以备日后使用:

    gcloud container clusters get-credentials ${GKE_1} \
        --project ${SVC_PROJECT_1} --zone ${ZONE_1}
    export GKE_SVC_1_CONTEXT=`kubectl config current-context`
    
    gcloud container clusters get-credentials ${GKE_2} \
        --project ${SVC_PROJECT_2} --zone ${ZONE_2}
    export GKE_SVC_2_CONTEXT=`kubectl config current-context`
    

部署应用

您可以将示例应用部署在两个 GKE 集群中。通过使用 curl 命令行工具,您还可以在两个集群中创建 busybox 部署,以测试应用间的连接性。

  1. 下载示例应用和 BusyBox Kubernetes 清单:

    wget https://storage.googleapis.com/solutions-public-assets/td-shared-vpc-gke/app1.yaml
    wget https://storage.googleapis.com/solutions-public-assets/td-shared-vpc-gke/busybox.yaml
    

    示例应用侦听 HTTP 端口 80 并使用其主机名(本例中为 pod 名称)进行响应。

  2. 在两个 GKE 集群上部署示例应用和 BusyBox 应用:

    kubectl apply -f app1.yaml --cluster $GKE_SVC_1_CONTEXT
    kubectl apply -f app1.yaml --cluster $GKE_SVC_2_CONTEXT
    kubectl apply -f busybox.yaml --cluster $GKE_SVC_1_CONTEXT
    kubectl apply -f busybox.yaml --cluster $GKE_SVC_2_CONTEXT
    

检查部署

  1. 确认这两个应用在两个 GKE 集群中运行:

    kubectl get pods --cluster $GKE_SVC_1_CONTEXT
    kubectl get pods --cluster $GKE_SVC_2_CONTEXT
    

    对于 GKE_1,输出类似于以下内容:

    NAME                      READY   STATUS    RESTARTS   AGE
    app1-f565f7c75-l867n      2/2     Running   0          93s
    app1-f565f7c75-tc652      2/2     Running   0          93s
    busybox-6dcf7d84f-2hntb   2/2     Running   0          90s
    

    对于 GKE_2,输出类似于以下内容:

    NAME                      READY   STATUS    RESTARTS   AGE
    app1-f565f7c75-sp5vf      2/2     Running   0          99s
    app1-f565f7c75-v578c      2/2     Running   0          99s
    busybox-6dcf7d84f-vccjl   2/2     Running   0          97s
    

    在两个 GKE 集群中,示例主机名应用 app1 的两个 pod 和 busybox 的一个 pod 正在运行。每个 pod 都有两个正在运行的容器。

  2. 检查在其中一个 GKE 集群的某个 app1 pod 中运行的容器:

    export APP1_POD_1=$(kubectl --cluster ${GKE_SVC_1_CONTEXT} get pods -l run=app1 | awk 'NR==2 {print $1}')
    kubectl get pods ${APP1_POD_1} --cluster ${GKE_SVC_1_CONTEXT} -o json | jq '.spec.containers[].image'
    

    输出类似于以下内容:

    "gcr.io/kubernetes-e2e-test-images/serve-hostname-amd64:1.1"
    "docker.io/istio/proxyv2:1.1.2"
    

    您可以看到两个运行 app1 pod 的容器。第一个容器是示例主机名应用容器。第二个容器是 Envoy Sidecar 代理,该代理将请求路由到 pod 中和从 pod 路由出请求。

  3. 检查 Envoy 代理容器的参数部分:

    kubectl get pods ${APP1_POD_1} --cluster ${GKE_SVC_1_CONTEXT} -o json | jq '.spec.containers[1].args'
    

    输出类似于以下内容:

    [
      "proxy",
      "sidecar",
      "--domain",
      "$(POD_NAMESPACE).svc.cluster.local",
      "--configPath",
      "/etc/istio/proxy",
      "--binaryPath",
      "/usr/local/bin/envoy",
      "--serviceCluster",
      "$(POD_NAMESPACE)",
      "--drainDuration",
      "45s",
      "--parentShutdownDuration",
      "1m0s",
      "--discoveryAddress",
      "trafficdirector.googleapis.com:443",
      "--proxyLogLevel",
      "info",
      "--connectTimeout",
      "10s",
      "--proxyAdminPort",
      "15000",
      "--concurrency",
      "2",
      "--statusPort",
      "15020"
    ]
    +
    

    discoveryAddress 代理设置指向 Traffic Director API。这是 Envoy 代理的配置方式。您可以在以下部分中配置 Envoy 代理。

配置 Traffic Director

Traffic Director 配置在每个应用 pod 中运行的 Envoy Sidecar 代理,使它们可以通过网络进行通信。此外,Traffic Director 还使用一种配置来允许服务之间的东西流量。此配置类似于您用于 Google Cloud 外部 HTTP(S) 负载平衡的配置(允许从外部客户端到服务的南北流量)。

您可以为 Traffic Director 配置以下组件:

  • 运行状况检查,确保仅将流量发送到运行状况良好的 pod。
  • 指向后端后端服务,在本例中为您的服务的网络端点组 (NEG)。NEG 表示在 GKE 集群中运行的服务的 pod IP 地址。
  • 路由规则,其中包括创建转发规则,该规则表示要转发到后端服务的 IP,以及指向特定服务的特定网址路径的网址映射

下图展示了控制平面的逻辑流以及流向 Kubernetes pod 或 Compute Engine 虚拟机实例的流量。

控制平面的逻辑流以及流向 Kubernetes pod 或 Compute Engine 虚拟机实例的流量。

Kubernetes pod 由 NEG 控制器在 NEG 中表示为端点,而 Compute Engine 虚拟机实例由托管实例组 (MIG) 管理。后端服务可以具有一个或多个后端,这些后端可以是 NEG(在此示例中为 Kubernetes pod)或 MIG(在此示例中为 Compute Engine 虚拟机实例)。Traffic Director 基于 NEG 或 MIG 容量执行全球负载平衡,并将经过运行状况检查的 NEG 或 MIG 端点提供给数据平面。

使用全局转发规则目标代理和网址映射中的信息来管理流量,以将流量路由到后端服务

通过执行以下步骤,配置 Traffic Director 和 Cloud Load Balancing 组件:

  1. 获取在两个集群中运行的示例应用的 NEG 名称。

    export GKE_SVC_1_APP1_NEG=$(gcloud beta compute network-endpoint-groups list --project ${SVC_PROJECT_1} | grep west | awk '{print     $1}')
    export GKE_SVC_2_APP1_NEG=$(gcloud beta compute network-endpoint-groups list --project ${SVC_PROJECT_2} | grep central | awk'{print $1}')
    

    NEG 支持在 GKE 集群上进行容器原生负载平衡。您可以将 NEG 用作 Google Cloud 负载平衡器的后端。

  2. 为两个服务项目中的后端服务创建运行状况检查:

    gcloud compute health-checks create http td-gke-health-check-svc-proj-1 \
        --project ${SVC_PROJECT_1} --use-serving-port
    
    gcloud compute health-checks create http td-gke-health-check-svc-proj-2 \
        --project ${SVC_PROJECT_2} --use-serving-port
    
  3. 在两个服务项目中创建后端服务,并将您在上一步中创建的运行状况检查与该后端服务相关联:

    gcloud compute backend-services create td-gke-service-svc-proj-1 \
        --project ${SVC_PROJECT_1} --global \
        --health-checks td-gke-health-check-svc-proj-1 \
        --load-balancing-scheme INTERNAL_SELF_MANAGED
    
    gcloud compute backend-services create td-gke-service-svc-proj-2 \
        --project ${SVC_PROJECT_2} --global \
        --health-checks td-gke-health-check-svc-proj-2 \
        --load-balancing-scheme INTERNAL_SELF_MANAGED
    
  4. 将两个服务项目中的示例应用的 NEG 作为后端添加到后端服务:

    gcloud compute backend-services add-backend td-gke-service-svc-proj-1 \
        --project ${SVC_PROJECT_1} --global \
        --network-endpoint-group ${GKE_SVC_1_APP1_NEG} \
        --network-endpoint-group-zone ${ZONE_1} \
        --balancing-mode RATE \
        --max-rate-per-endpoint 5
    
    gcloud compute backend-services add-backend td-gke-service-svc-proj-2 \
        --project ${SVC_PROJECT_2} --global \
        --network-endpoint-group ${GKE_SVC_2_APP1_NEG} \
        --network-endpoint-group-zone ${ZONE_2} \
        --balancing-mode RATE \
        --max-rate-per-endpoint 5
    
  5. 在每个服务项目中创建一个网址映射:

    gcloud compute url-maps create td-gke-url-map-svc-proj-1 \
        --project ${SVC_PROJECT_1} --default-service td-gke-service-svc-proj-1
    
    gcloud compute url-maps create td-gke-url-map-svc-proj-2 \
        --project ${SVC_PROJECT_2} --default-service td-gke-service-svc-proj-2
    
  6. 在每个服务项目中创建一个目标代理:

    gcloud compute target-http-proxies create td-gke-proxy-svc-proj-1 \
        --project ${SVC_PROJECT_1} --url-map td-gke-url-map-svc-proj-1
    
    gcloud compute target-http-proxies create td-gke-proxy-svc-proj-2 \
        --project ${SVC_PROJECT_2} --url-map td-gke-url-map-svc-proj-2
    
  7. 预留两个内部静态 IP 地址,以在两个服务的转发规则中使用:

    gcloud compute addresses create static-ip-svc-proj-1 \
        --project ${SVC_PROJECT_1} \
        --subnet projects/${HOST_PROJECT}/regions/${REGION_1}/subnetworks/subnet-1 \
        --region=${REGION_1} --addresses 10.0.7.250
    
    gcloud compute addresses create static-ip-svc-proj-2 \
        --project ${SVC_PROJECT_2} \
        --subnet projects/${HOST_PROJECT}/regions/${REGION_2}/subnetworks/subnet-2 \
        --region=${REGION_2} --addresses 172.16.7.250
    
  8. 在每个服务项目中创建一个转发规则:

    gcloud compute forwarding-rules create td-gke-forwarding-rule-svc-proj-1 \
        --project ${SVC_PROJECT_1} --global \
        --target-http-proxy td-gke-proxy-svc-proj-1 --ports 80 \
        --address https://www.googleapis.com/compute/v1/projects/"${SVC_PROJECT_1}"/regions/"${REGION_1}"/addresses/static-ip-svc-proj-1 \
        --network https://www.googleapis.com/compute/v1/projects/"${HOST_PROJECT}"/global/networks/shared-vpc \
        --load-balancing-scheme INTERNAL_SELF_MANAGED
    
    gcloud compute forwarding-rules create td-gke-forwarding-rule-svc-proj-2 \
        --project ${SVC_PROJECT_2} --global \
        --target-http-proxy td-gke-proxy-svc-proj-2 --ports 80 \
        --address https://www.googleapis.com/compute/v1/projects/"${SVC_PROJECT_2}"/regions/"${REGION_2}"/addresses/static-ip-svc-proj-2 \
        --network https://www.googleapis.com/compute/v1/projects/"${HOST_PROJECT}"/global/networks/shared-vpc \
        --load-balancing-scheme INTERNAL_SELF_MANAGED
    

测试服务之间的连接

现在,您已经配置了 Traffic Director。每个应用 pod 中运行的 Envoy Sidecar 代理现在可以跨地区和集群通过网络进行连接。接下来,测试两个 GKE 集群中部署的服务之间的网络连接。

  1. 获取在两个 GKE 集群中运行的 busybox pod 的 pod 名称。您可以使用该 pod 名称进行网络连接测试:

    export BUSYBOX_SVC_PROJECT_1_POD=$(kubectl get pods -l run=client -o=jsonpath='{.items[0].metadata.name}' --cluster=${GKE_SVC_1_CONTEXT})
    export BUSYBOX_SVC_PROJECT_2_POD=$(kubectl get pods -l run=client -o=jsonpath='{.items[0].metadata.name}' --cluster=${GKE_SVC_2_CONTEXT})
    
  2. 验证其中一个 busybox pod 中的 istio-proxy 配置:

    kubectl --context ${GKE_SVC_1_CONTEXT} exec ${BUSYBOX_SVC_PROJECT_1_POD} -c istio-proxy -- curl localhost:15000/clusters | grep neg
    

    输出类似于以下内容:

    cloud-internal-istio:cloud_mp_748236137853_5025068062950697453::172.20.0.16:8000::sub_zone::jf:us-central1-a_3769163129600485500_neg
    cloud-internal-istio:cloud_mp_748236137853_5025068062950697453::172.20.1.10:8000::sub_zone::jf:us-central1-a_3769163129600485500_neg
    cloud-internal-istio:cloud_mp_397592564267_7855627510184552468::10.4.2.7:8000::sub_zone::pv:us-west1-a_4416141197590276889_neg
    cloud-internal-istio:cloud_mp_397592564267_7855627510184552468::10.4.0.11:8000::sub_zone::pv:us-west1-a_4416141197590276889_neg
    

    在此输出中,第一个字段是 Traffic Director 分配的内部服务名称。第二个字段(IP 地址)是服务的 pod IP 地址。最后一个字段表示 pod 的区域和 NEG ID。您可以在 gke-svc-2 集群中的 app1 pod 的 us-central1-a 区域中看到两个 pod IP 地址。您还可以在 gke-svc-1 集群中的 app1 pod 的 us-west1-a 区域中看到两个 pod IP 地址。

  3. 获取两个服务项目中 GKE 集群中主机名应用的 pod 名称:

    kubectl get pods -l run=app1 --cluster=${GKE_SVC_1_CONTEXT}
    kubectl get pods -l run=app1 --cluster=${GKE_SVC_2_CONTEXT}
    

    记下下一部分中用于连接测试的 pod 名称。

测试连接性

  1. 测试从服务项目 1 中的 BusyBox pod 发送到服务项目 1 中的主机名应用的 HTTP 请求:

    for i in {1..10}
    do
    kubectl exec -it ${BUSYBOX_SVC_PROJECT_1_POD}
    --cluster=${GKE_SVC_1_CONTEXT} -c busybox -- /bin/sh -c
    'wget -q -O - 10.0.7.250'; echo
    done
    

    结果是在服务项目 1 的 GKE 集群中运行的部署中的 pod 的主机名。

  2. 测试从服务项目 1 中的 BusyBox 发送到服务项目 2 中的主机名应用的 HTTP 请求:

    for i in {1..10}
    do
    kubectl exec -it ${BUSYBOX_SVC_PROJECT_1_POD}
    --cluster=${GKE_SVC_1_CONTEXT} -c busybox -- /bin/sh -c
    'wget -q -O - 172.16.7.250'; echo
    done
    

    结果是在服务项目 2 的 GKE 集群中运行的部署中的 pod 的主机名。

  3. 测试从服务项目 2 中的 BusyBox 发送到服务项目 2 中的主机名应用的 HTTP 请求:

    for i in {1..10}
    do
    kubectl exec -it ${BUSYBOX_SVC_PROJECT_2_POD}
    --cluster=${GKE_SVC_2_CONTEXT} -c busybox -- /bin/sh -c
    'wget -q -O - 172.16.7.250'; echo
    done`
    

    结果是在服务项目 2 的 GKE 集群中运行的部署中的 pod 的主机名。

  4. 测试从服务项目 2 中的 Busybox 发送到服务项目 1 中的主机名应用的 HTTP 请求:

    for i in {1..10}
    do
    kubectl exec -it ${BUSYBOX_SVC_PROJECT_2_POD}
    --cluster=${GKE_SVC_2_CONTEXT} -c busybox -- /bin/sh -c
    'wget -q -O - 10.0.7.250'; echo
    done
    

    结果是在服务项目 1 的 GKE 集群中运行的部署中的 pod 的主机名。

现在,您已经在共享 VPC 上配置了 Traffic Director,可以在多个服务项目中的 GKE 集群上运行的服务之间路由流量。

清理

为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

重置 kubeconfig

  • 重置 KUBECONFIG 变量以指向默认的 kubeconfig 文件:

    unset KUBECONFIG
    

删除所有项目

若要避免产生费用,最简单的方法是删除您为本教程创建的项目。在删除项目之前,您必须先停用共享 VPC。为此,请按以下顺序执行以下步骤:

  1. 从两个服务项目中移除转发规则:

    gcloud compute forwarding-rules delete td-gke-forwarding-rule \
        --project ${SVC_PROJECT_1} --global
    
    gcloud compute forwarding-rules delete td-gke-forwarding-rule \
        --project ${SVC_PROJECT_2} --global
    
  2. 从两个服务项目的后端服务中移除 NEG:

    gcloud compute backend-services remove-backend td-gke-service \
        --project ${SVC_PROJECT_1} --global \
        --network-endpoint-group ${GKE_SVC_1_APP1_NEG} \
        --network-endpoint-group-zone ${ZONE_1}
    
    gcloud compute backend-services remove-backend td-gke-service \
        --project ${SVC_PROJECT_2} --global \
        --network-endpoint-group ${GKE_SVC_2_APP1_NEG} \
        --network-endpoint-group-zone ${ZONE_2}
    
  3. 从两个服务项目中移除 NEG:

    gcloud compute network-endpoint-groups delete ${GKE_SVC_1_APP1_NEG} --project=${SVC_PROJECT_1} --zone=${ZONE_1} --quiet
    
    gcloud compute network-endpoint-groups delete ${GKE_SVC_2_APP1_NEG} --project=${SVC_PROJECT_2} --zone=${ZONE_2} --quiet
    
  4. 从两个服务项目中删除 GKE 集群:

    gcloud container clusters delete ${GKE_1} --project=${SVC_PROJECT_1} --zone=${ZONE_1} --quiet
    
    gcloud container clusters delete ${GKE_2} --project=${SVC_PROJECT_2} --zone=${ZONE_2} --quiet
    
  5. 从共享 VPC 分离服务项目:

    gcloud compute shared-vpc associated-projects remove ${SVC_PROJECT_1} --host-project ${HOST_PROJECT}
    
    gcloud compute shared-vpc associated-projects remove ${SVC_PROJECT_2} --host-project ${HOST_PROJECT}
    
  6. 在宿主项目中停用共享 VPC:

    gcloud compute shared-vpc disable ${HOST_PROJECT}
    
  7. 删除您为本教程创建的三个项目:

    gcloud projects delete ${HOST_PROJECT}
    gcloud projects delete ${SVC_PROJECT_1}
    gcloud projects delete ${SVC_PROJECT_2}
    

后续步骤