区域 Cloud Service Mesh

借助区域隔离,连接到 Cloud Service Mesh 控制平面特定区域的客户端只能访问该区域内的资源。同样,特定区域内的 API 资源只能引用该区域内的其他资源。

区域 Cloud Service Mesh 存在以下限制:

  • 不支持 Istio API。您无法使用 Kubernetes 和 Istio API 通过区域 Traffic Director。此预览版仅支持 Google Cloud API。
  • 全球服务路由 API 的现有注意事项和限制适用。
  • 支持 xdSTP 命名方案的最低 Envoy 版本为 v1.31.1。
  • 不支持 Gateway for Mesh API
  • 最低 gRPC 版本为 v1.65。
  • 仅支持以下区域:

    africa-south1
    asia-east1
    asia-east2
    asia-northeast1
    asia-northeast2
    asia-northeast3
    asia-south1
    asia-south2
    asia-southeast1
    asia-southeast2
    australia-southeast1
    australia-southeast2
    europe-central2
    europe-north1
    europe-north2
    europe-southwest1
    europe-west10
    europe-west12
    europe-west1
    europe-west2
    europe-west3
    europe-west4
    europe-west6
    europe-west8
    europe-west9
    me-central1
    me-central2
    me-west1
    northamerica-northeast1
    northamerica-northeast2
    northamerica-south1
    southamerica-east1
    southamerica-west1
    us-central1
    us-east1
    us-east4
    us-east5
    us-south1
    us-west1
    us-west2
    us-west3
    us-west4
    

价格

当此功能正式版发布后,支持区域性 Cloud Service Mesh 的每个区域都将具有区域性 SKU。目前,价格与全球价格相同。

为 Cloud Service Mesh 准备 xDS 客户端

Compute 虚拟机 Envoy xDS

手动

手动步骤以使用手动 Envoy 部署设置虚拟机为基础。 主要区别在于,ENVOY_CONTROL_PLANE_REGION 会被设置并注入到引导加载程序中。

  1. 创建实例模板:

    gcloud compute instance-templates create td-vm-templategcloud compute instance-templates create td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=http-td-tag,http-server,https-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script='#! /usr/bin/env bash
    
    # Set variables
    export ENVOY_CONTROL_PLANE_REGION="us-central1"
    export ENVOY_USER="envoy"
    export ENVOY_USER_UID="1337"
    export ENVOY_USER_GID="1337"
    export ENVOY_USER_HOME="/opt/envoy"
    export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
    export ENVOY_PORT="15001"
    export ENVOY_ADMIN_PORT="15000"
    export ENVOY_TRACING_ENABLED="false"
    export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
    export ENVOY_ACCESS_LOG="/dev/stdout"
    export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
    export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
    export GCE_METADATA_SERVER="169.254.169.254/32"
    export INTERCEPTED_CIDRS="*"
    export GCP_PROJECT_NUMBER=PROJECT_NUMBER
    export VPC_NETWORK_NAME=mesh:sidecar-mesh
    export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)
    
    # Create system user account for Envoy binary
    sudo groupadd ${ENVOY_USER} \
      --gid=${ENVOY_USER_GID} \
      --system
    sudo adduser ${ENVOY_USER} \
      --uid=${ENVOY_USER_UID} \
      --gid=${ENVOY_USER_GID} \
      --home=${ENVOY_USER_HOME} \
      --disabled-login \
      --system
    # Download and extract the Cloud Service Mesh tar.gz file
    cd ${ENVOY_USER_HOME}
    sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
      -C bootstrap_template.yaml \
      --strip-components 1
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
      -C iptables.sh \
      --strip-components 1
    sudo rm traffic-director-xdsv3.tar.gz
    
    # Generate Envoy bootstrap configuration
    cat "${BOOTSTRAP_TEMPLATE}" \
      | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
      | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
      | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
      | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
      | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
      | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
      | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
      | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
      | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
      | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
      | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
      | sudo tee "${ENVOY_CONFIG}"
    
    # Install Envoy binary
    wget -O envoy_key https://apt.envoyproxy.io/signing.key
    cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
    sudo apt-get update
    sudo apt-get install envoy
    
    # Run Envoy as systemd service
    sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
      --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
      bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"
    
    # Configure iptables for traffic interception and redirection
    sudo ${ENVOY_USER_HOME}/iptables.sh \
      -p "${ENVOY_PORT}" \
      -u "${ENVOY_USER_UID}" \
      -g "${ENVOY_USER_GID}" \
      -m "REDIRECT" \
      -i "${INTERCEPTED_CIDRS}" \
      -x "${GCE_METADATA_SERVER}"
    

Compute 虚拟机 gRPC xDS

与全局 Cloud Service Mesh 类似,gRPC 客户端需要配置一个引导加载程序,以告知它如何连接到区域 Cloud Service Mesh。

您可以使用 gRPC 引导生成器来生成此引导。如需将其设置为使用区域 Cloud Service Mesh,请指定一个新标志:--xds-server-region

在此示例中,将 xds-server-region 设置为 us-central1 会自动确定区域性 Cloud Service Mesh 端点:trafficdirector.us-central1.rep.googleapis.com:443.

K8s 手动 Envoy 注入

以下手动步骤以使用手动 Envoy 注入功能设置 Google Kubernetes Engine Pod 为基础。 不过,您只需要修改有关手动注入 Pod 的部分

  1. 将控制平面从全球级更改为区域级:

    wget -q -O - https://storage.googleapis.com/traffic-director/demo/trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s/PROJECT_NUMBER/PROJECT_NUMBER/g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s/MESH_NAME/MESH_NAME/g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s|trafficdirector.googleapis.com|trafficdirector.${REGION}.rep.googleapis.com|g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s|gcr.io/google-containers/busybox|busybox:stable|g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    1. 应用更改:

      kubectl apply -f trafficdirector_client_new_api_sample_xdsv3.yaml
        ```
      

设置指南

本部分介绍了五种独立的配置和部署模型。这些都是现有全局服务路由 API 设置指南的区域化版本。

使用区域 GRPCRoute 和区域 Cloud Service Mesh 配置无代理 gRPC 服务

本部分介绍了如何使用区域级 Cloud Service Mesh 和区域级 GRPCRoute 资源配置无代理 gRPC 服务网格。

为方便起见,请存储您执行配置的 Google Cloud 项目编号,以便将本指南中的所有示例复制并粘贴到命令行中:

export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"

PROJECT_NUMBER 替换为您的项目编号。

您可以选择性地替换以下内容:

  • us-central1 替换为您要使用的其他区域。
  • us-central1-a 替换为您要使用的其他可用区。
  • default 替换为其他 VPC_NAME。

网格配置

当无代理 gRPC 应用连接到 xds://hostname 时,gRPC 客户端库会建立与 Cloud Service Mesh 的连接,以获取路由主机名请求所需的路由配置。

  1. 创建网格规范并将其存储在 mesh.yaml 文件中:

    cat <<EOF > mesh.yaml
    name: grpc-mesh
    EOF
    
  2. 使用 mesh.yaml 规范创建网格:

    gcloud network-services meshes import grpc-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

    创建区域网格后,Cloud Service Mesh 即可提供配置。不过,由于尚未定义任何服务,因此配置为空。

gRPC 服务配置

出于演示目的,您将创建一个区域级后端服务,其中包含自动扩缩虚拟机(使用代管式实例组 [MIG]),该服务将使用 gRPC 协议在端口 50051 上提供 hello world

  1. 使用端口 50051 上公开的 helloworld gRPC 服务创建 Compute Engine 虚拟机实例模板:

    gcloud compute instance-templates create grpc-td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=allow-health-checks \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata-from-file=startup-script=<(echo '#! /bin/bash
    set -e
    cd /root
    sudo apt-get update -y
    sudo apt-get install -y openjdk-11-jdk-headless
    curl -L https://github.com/grpc/grpc-java/archive/v1.38.0.tar.gz | tar -xz
    cd grpc-java-1.38.0/examples/example-hostname
    ../gradlew --no-daemon installDist
    # Server listens on 50051
    sudo systemd-run ./build/install/hostname-server/bin/hostname-server')
    
  2. 基于模板创建 MIG:

    gcloud compute instance-groups managed create grpc-td-mig-us-central1 \
      --zone=${ZONE} \
      --size=2 \
      --template=grpc-td-vm-template
    
  3. 为 gRPC 服务配置已命名端口。这是 gRPC 服务配置为侦听请求的端口。

    gcloud compute instance-groups set-named-ports grpc-td-mig-us-central1 \
      --named-ports=grpc-helloworld-port:50051 \
      --zone=${ZONE}
    

    在本示例中,端口为 50051。

  4. 创建 gRPC 健康检查。

    gcloud compute health-checks create grpc grpc-helloworld-health-check \
      --use-serving-port --region=${REGION}
    

    这些服务必须实现 gRPC 健康检查协议,以确保 gRPC 健康检查正常运行。如需了解详情,请参阅创建健康检查

  5. 创建防火墙规则以允许传入的健康检查关联到您网络中的实例:

    gcloud compute firewall-rules create grpc-vm-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:50051
    
  6. 使用负载均衡方案 INTERNAL_SELF_MANAGED 创建区域后端服务,并将之前创建的健康检查和代管式实例组添加到后端服务。端口名称中指定的端口用于连接到代管式实例组内的虚拟机。

    gcloud compute backend-services create grpc-helloworld-service \
        --load-balancing-scheme=INTERNAL_SELF_MANAGED \
        --protocol=GRPC \
        --port-name=grpc-helloworld-port \
      --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/grpc-helloworld-health-check" \
        --region=${REGION}
    
  7. 将代管式实例组添加到 BackendService

    gcloud compute backend-services add-backend grpc-helloworld-service \
      --instance-group=grpc-td-mig-us-central1 \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

使用区域 GRPCRoute 设置路由

此时,区域级网格和 gRPC 服务器服务已配置完毕。现在,您可以设置所需的路由。

  1. 创建区域性 GRPCRoute 规范并将其存储在 grpc_route.yaml 文件中:

    cat <<EOF > grpc_route.yaml
    name: helloworld-grpc-route
    hostnames:
    - helloworld-gce
    meshes:
    - projects/${PROJECT_NUMBER}/locations/${REGION}/meshes/grpc-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/grpc-helloworld-service
    EOF
    
  2. 使用 grpc_route.yaml 规范创建区域性 GRPCRoute:

    gcloud network-services grpc-routes import helloworld-grpc-route \
        --source=grpc_route.yaml \
        --location=${REGION}
    

    Cloud Service Mesh 现已配置为在托管式实例组中的后端之间对 gRPC 路由中指定的服务进行流量负载均衡。

创建 gRPC 客户端服务

如需验证配置,请实例化一个具有无代理 gRPC 数据平面的客户端应用。此应用必须在其引导文件中指定网格的名称。

配置完成后,此应用可以使用 xds:///helloworld-gce 服务 URI 向与 helloworld-gce 关联的实例或端点发送请求。

在以下示例中,您将使用 grpcurl 工具测试 gRPC 服务。

  1. 创建客户端虚拟机:

    gcloud compute instances create grpc-client \
      --zone=${ZONE}\
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata-from-file=startup-script=<(echo '#! /bin/bash
    set -ex
    export PROJECT=PROJECT_NUMBER
    export REGION=us-central1
    export GRPC_XDS_BOOTSTRAP=/run/td-grpc-bootstrap.json
    echo export GRPC_XDS_BOOTSTRAP=$GRPC_XDS_BOOTSTRAP | sudo tee /etc/profile.d/grpc-xds-bootstrap.sh
    curl -L https://storage.googleapis.com/traffic-director/td-grpc-bootstrap-0.18.0.tar.gz | tar -xz
    ./td-grpc-bootstrap-0.18.0/td-grpc-bootstrap --config-mesh=grpc-mesh --xds-server-uri=trafficdirector.${REGION}.rep.googleapis.com:443 --gcp-project-number=${PROJECT} | sudo tee $GRPC_XDS_BOOTSTRAP
    sudo sed -i "s|\"authorities\": {|\"authorities\": {\n    \"traffic-director.${REGION}.xds.googleapis.com\": {\"xds_servers\":[{\"server_uri\": \"trafficdirector.${REGION}.rep.googleapis.com:443\", \"channel_creds\": [ { \"type\": \"google_default\" } ], \"server_features\": [ \"xds_v3\", \"ignore_resource_deletion\" ]}], \"client_listener_resource_name_template\": \"xdstp://traffic-director.${REGION}.xds.googleapis.com/envoy.config.listener.v3.Listener/${PROJECT}/mesh:grpc-mesh/%s\"},|g" $GRPC_XDS_BOOTSTRAP
    sudo sed -i "s|\"client_default_listener_resource_name_template\": \"xdstp://traffic-director-global.xds.googleapis.com|\"client_default_listener_resource_name_template\": \"xdstp://traffic-director.${REGION}.xds.googleapis.com|g" $GRPC_XDS_BOOTSTRAP')
    

设置环境变量和引导文件

客户端应用需要引导配置文件。上一部分中的启动脚本会设置 GRPC_XDS_BOOTSTRAP 环境变量,并使用帮助程序脚本生成引导文件。所生成引导文件中 TRAFFICDIRECTOR_GCP_PROJECT_NUMBER 和 zone 的值将从知道 Compute Engine 虚拟机实例这些详细信息的元数据服务器获取。

您可以使用 -gcp-project-number 选项手动将这些值提供给帮助程序脚本。您必须使用 -config-mesh-experimental 选项提供与网格资源匹配的网格名称。

  1. 如需验证配置,请登录客户端:

    gcloud compute ssh grpc-client --zone=${ZONE}
    
  2. 下载并安装 grpcurl 工具:

    curl -L https://github.com/fullstorydev/grpcurl/releases/download/v1.9.3/grpcurl_1.9.3_linux_x86_64.tar.gz | tar -xz
    
  3. 运行 grpcurl 工具,将 xds:///helloworld-gce 作为服务 URI,将 helloworld.Greeter/SayHello 作为服务名称和要调用的方法。

    ./grpcurl --plaintext \
      -d '{"name": "world"}' \
      xds:///helloworld-gce helloworld.Greeter/SayHello
    

    使用 -d 选项传递 SayHello 方法的参数。

    您应该会看到如下所示的输出,其中 INSTANCE_NAME 是虚拟机实例的名称:

    Greeting: Hello world, from INSTANCE_HOSTNAME
    

这将验证无代理 gRPC 客户端是否已成功连接到 Cloud Service Mesh,并使用 xDS 名称解析器获取 helloworld-gce 服务的后端。客户端向服务的其中一个后端发送请求,无需了解 IP 地址或执行 DNS 解析。

使用 HTTP 服务配置 Envoy 边车代理配置,并使用区域级 HTTPRoute 和区域级 Mesh

本部分介绍了如何使用区域级网格和区域级 HTTPRoute 资源配置基于 Envoy 代理的服务网格。

为方便起见,请存储您执行配置的 Google Cloud 项目编号,以便将本指南中的所有示例复制并粘贴到命令行中:

export PROJECT_ID="PROJECT_ID"
export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"

替换以下内容

  • PROJECT_ID 替换为您的项目 ID。
  • PROJECT_NUMBER 替换为您的项目编号。

您可以选择性地替换以下内容:

  • us-central1 替换为您要使用的其他区域。
  • us-central1-a 替换为您要使用的其他可用区。

网格配置

边车 Envoy 代理从 Cloud Service Mesh 接收服务路由配置。边车会显示区域网格资源的名称,以标识已配置的特定服务网格。从 Cloud Service Mesh 收到的路由配置用于根据在 Route 资源中配置的请求参数(例如主机名或标头),将通过边车代理的流量定向到各种区域性后端服务。

请注意,网格名称是边车代理用于请求与此网格关联的配置的键。

  1. 创建区域级网格规范并将其存储在 mesh.yaml 文件中:

    cat <<EOF > mesh.yaml
    name: sidecar-mesh
    EOF
    

    如果未指定,则拦截端口默认为 15001。

  2. 使用 mesh.yaml 规范创建区域网格:

    gcloud network-services meshes import sidecar-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

    创建区域网格后,Cloud Service Mesh 即可提供配置。不过,由于尚未定义任何服务,因此配置将为空。

HTTP 服务器配置

出于演示目的,您将创建一个区域后端服务,其中包含自动扩缩的虚拟机(使用代管式实例组 - MIG),这些虚拟机将在端口 80 上使用 gRPC 协议提供“hello world”。

  1. 使用端口 80 上公开的 helloworld HTTP 服务创建 Compute Engine 虚拟机实例模板:

    gcloud compute instance-templates create td-httpd-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=http-td-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script="#! /bin/bash
    
    sudo apt-get update -y
    sudo apt-get install apache2 -y
    sudo service apache2 restart
    echo '<!doctype html><html><body><h1>'\`/bin/hostname\`'</h1></body></html>' | sudo tee /var/www/html/index.html"
    
  2. 基于模板创建 MIG:

    gcloud compute instance-groups managed create http-td-mig-us-central1 \
      --zone=${ZONE} \
      --size=2 \
      --template=td-httpd-vm-template
    
  3. 创建健康检查:

    gcloud compute health-checks create http http-helloworld-health-check --region=${REGION}
    
  4. 创建防火墙规则以允许传入的健康检查关联到您网络中的实例:

    gcloud compute firewall-rules create http-vm-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \
      --target-tags http-td-server \
      --rules tcp:80
    
  5. 使用负载均衡方案 INTERNAL_SELF_MANAGED 创建区域性后端服务

    gcloud compute backend-services create http-helloworld-service \
        --load-balancing-scheme=INTERNAL_SELF_MANAGED \
        --protocol=HTTP \
    --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/http-helloworld-health-check" \
        --region=${REGION}
    
  6. 将健康检查以及托管或非托管实例组添加到后端服务:

    gcloud compute backend-services add-backend http-helloworld-service \
      --instance-group=http-td-mig-us-central1 \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

    此示例使用代管式实例组和 Compute Engine 虚拟机模板,该模板运行我们之前创建的示例 HTTP 服务。

使用区域级 HTTPRoute 设置路由

已配置网格资源和 HTTP 服务器。现在,您可以使用 HTTPRoute 资源将它们连接起来,而此资源将主机名与后端服务相关联。

  1. 创建 HTTPRoute 规范并将其存储为 http_route.yaml:

    cat <<EOF > http_route.yaml
    name: helloworld-http-route
    hostnames:
    - helloworld-gce
    meshes:
    - projects/${PROJECT_NUMBER}/locations/${REGION}/meshes/sidecar-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/http-helloworld-service
    EOF
    
  2. 使用 http_route.yaml 规范创建 HTTPRoute:

    gcloud network-services http-routes import helloworld-http-route \
        --source=http_route.yaml \
        --location=${REGION}
    

    Cloud Service Mesh 现已配置为在代管式实例组中的后端之间对 HTTPRoute 中指定的服务进行流量负载均衡。

使用 Envoy 边车创建 HTTP 客户端

在本部分中,您将实例化一个带有 Envoy 边车代理的客户端虚拟机,以请求之前创建的 Cloud Service Mesh 配置。请注意,Google Cloud CLI 命令中的 mesh 参数引用了之前创建的网格资源。

gcloud compute instance-templates create td-vm-template \
  --scopes=https://www.googleapis.com/auth/cloud-platform \
  --tags=http-td-tag,http-server,https-server \
  --image-family=debian-11 \
  --image-project=debian-cloud \
  --metadata=startup-script='#! /usr/bin/env bash

# Set variables
export ENVOY_CONTROL_PLANE_REGION="us-central1"
export ENVOY_USER="envoy"
export ENVOY_USER_UID="1337"
export ENVOY_USER_GID="1337"
export ENVOY_USER_HOME="/opt/envoy"
export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
export ENVOY_PORT="15001"
export ENVOY_ADMIN_PORT="15000"
export ENVOY_TRACING_ENABLED="false"
export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
export ENVOY_ACCESS_LOG="/dev/stdout"
export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
export GCE_METADATA_SERVER="169.254.169.254/32"
export INTERCEPTED_CIDRS="*"
export GCP_PROJECT_NUMBER=PROJECT_NUMBER
export VPC_NETWORK_NAME=mesh:sidecar-mesh
export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)

# Create system user account for Envoy binary
sudo groupadd ${ENVOY_USER} \
  --gid=${ENVOY_USER_GID} \
  --system
sudo adduser ${ENVOY_USER} \
  --uid=${ENVOY_USER_UID} \
  --gid=${ENVOY_USER_GID} \
  --home=${ENVOY_USER_HOME} \
  --disabled-login \
  --system
# Download and extract the Cloud Service Mesh tar.gz file
cd ${ENVOY_USER_HOME}
sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
  -C bootstrap_template.yaml \
  --strip-components 1
sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
  -C iptables.sh \
  --strip-components 1
sudo rm traffic-director-xdsv3.tar.gz

# Generate Envoy bootstrap configuration
cat "${BOOTSTRAP_TEMPLATE}" \
  | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
  | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
  | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
  | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
  | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
  | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
  | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
  | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
  | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
  | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
  | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
  | sudo tee "${ENVOY_CONFIG}"

# Install Envoy binary
wget -O envoy_key https://apt.envoyproxy.io/signing.key
cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
sudo apt-get update
sudo apt-get install envoy

# Run Envoy as systemd service
sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
  --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
  bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"

# Configure iptables for traffic interception and redirection
sudo ${ENVOY_USER_HOME}/iptables.sh \
  -p "${ENVOY_PORT}" \
 -u "${ENVOY_USER_UID}" \
  -g "${ENVOY_USER_GID}" \
  -m "REDIRECT" \
  -i "${INTERCEPTED_CIDRS}" \
  -x "${GCE_METADATA_SERVER}"
'

gcloud compute instances create td-vm-client \
  --zone=${ZONE} \
  --source-instance-template td-vm-template
  1. 登录已创建的虚拟机:

    gcloud compute ssh td-vm-client --zone=${ZONE}
    
  2. 验证与所创建的测试服务的 HTTP 连接:

    curl -H "Host: helloworld-gce" http://10.0.0.1/
    

    该命令会返回托管式实例组中某个虚拟机的响应,并将主机名输出到控制台。

使用区域性 TCPRoute 配置 TCP 服务

此配置流程与使用 HTTP 服务设置 Envoy 代理非常相似,但后端服务提供 TCP 服务,并且路由基于 TCP/IP 参数而不是 HTTP 协议。

为方便起见,请存储您执行配置的 Google Cloud 项目编号,以便将本指南中的所有示例复制并粘贴到命令行中:

export PROJECT_ID="PROJECT_ID"
export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"

替换以下内容

  • PROJECT_ID 替换为您的项目 ID。
  • PROJECT_NUMBER 替换为您的项目编号。

您可以选择性地替换以下内容:

  • us-central1 替换为您要使用的其他区域。
  • us-central1-a 替换为您要使用的其他可用区。

网格配置

  1. 创建区域级网格规范并将其存储在 mesh.yaml 文件中:

    cat <<EOF > mesh.yaml
    name: sidecar-mesh
    EOF
    
  2. 使用 mesh.yaml 规范创建区域网格:

    gcloud network-services meshes import sidecar-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

TCP 服务器配置

出于演示目的,您将创建一个区域后端服务,其中包含自动扩缩的虚拟机(使用代管式实例组 - MIG),这些虚拟机将使用端口 10000 上的 gRPC 协议提供“hello world”。

  1. 使用 netcat 实用程序创建 Compute Engine 虚拟机实例模板,该模板在端口 10000 上运行测试服务:

    gcloud compute instance-templates create tcp-td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=allow-health-checks \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script="#! /bin/bash
    sudo apt-get update -y
    sudo apt-get install netcat -y
    while true;
      do echo 'Hello from TCP service' | nc -l -s 0.0.0.0 -p 10000;
    done &"
    
  2. 基于模板创建 MIG:

    gcloud compute instance-groups managed create tcp-td-mig-us-central1 \
      --zone=${ZONE} \
      --size=1 \
      --template=tcp-td-vm-template
    
  3. 将创建的代管式实例组上的已命名端口设置为 port 10000

    gcloud compute instance-groups set-named-ports tcp-td-mig-us-central1 \
      --zone=${ZONE} --named-ports=tcp:10000
    
  4. 创建区域级健康检查:

    gcloud compute health-checks create tcp tcp-helloworld-health-check --port 10000 --region=${REGION}
    
  5. 创建防火墙规则以允许传入的健康检查关联到您网络中的实例:

    gcloud compute firewall-rules create tcp-vm-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:10000
    
  6. 创建负载均衡方案为 INTERNAL_SELF_MANAGED 的区域后端服务,并将健康检查以及托管或非托管实例组添加到后端服务。

    gcloud compute backend-services create tcp-helloworld-service \
        --region=${REGION} \
        --load-balancing-scheme=INTERNAL_SELF_MANAGED \
        --protocol=TCP \
        --port-name=tcp \
        --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/tcp-helloworld-health-check"
    
  7. 将 MIG 添加到 BackendService:

    gcloud compute backend-services add-backend tcp-helloworld-service \
      --instance-group tcp-td-mig-us-central1 \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

使用区域 TCPRoute 设置路由

  1. 创建 TCPRoute 规范并将其存储在 tcp_route.yaml 文件中:

    cat <<EOF > tcp_route.yaml
    name: helloworld-tcp-route
    meshes:
    - projects/$PROJECT_NUMBER/locations/$REGION/meshes/sidecar-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/$PROJECT_NUMBER/locations/$REGION/backendServices/tcp-helloworld-service
      matches:
      - address: '10.0.0.1/32'
        port: '10000'
    EOF
    
  2. 使用 tcp_route.yaml 规范创建 TCPRoute:

    gcloud network-services tcp-routes import helloworld-tcp-route \
        --source=tcp_route.yaml \
        --location=${REGION}
    

使用 Envoy 边车创建 TCP 客户端

  1. 创建连接到 Cloud Service Mesh 的 Envoy 虚拟机:

    gcloud compute instance-templates create td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=http-td-tag,http-server,https-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script='#! /usr/bin/env bash
    
    # Set variables
    export ENVOY_CONTROL_PLANE_REGION="us-central1"
    export ENVOY_USER="envoy"
    export ENVOY_USER_UID="1337"
    export ENVOY_USER_GID="1337"
    export ENVOY_USER_HOME="/opt/envoy"
    export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
    export ENVOY_PORT="15001"
    export ENVOY_ADMIN_PORT="15000"
    export ENVOY_TRACING_ENABLED="false"
    export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
    export ENVOY_ACCESS_LOG="/dev/stdout"
    export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
    export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
    export GCE_METADATA_SERVER="169.254.169.254/32"
    export INTERCEPTED_CIDRS="*"
    export GCP_PROJECT_NUMBER=PROJECT_NUMBER
    export VPC_NETWORK_NAME=mesh:sidecar-mesh
    
    export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)
    
    # Create system user account for Envoy binary
    sudo groupadd ${ENVOY_USER} \
      --gid=${ENVOY_USER_GID} \
      --system
    sudo adduser ${ENVOY_USER} \
      --uid=${ENVOY_USER_UID} \
      --gid=${ENVOY_USER_GID} \
      --home=${ENVOY_USER_HOME} \
      --disabled-login \
      --system
    # Download and extract the Cloud Service Mesh tar.gz file
    cd ${ENVOY_USER_HOME}
    sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
      -C bootstrap_template.yaml \
      --strip-components 1
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
      -C iptables.sh \
      --strip-components 1
    sudo rm traffic-director-xdsv3.tar.gz
    
    # Generate Envoy bootstrap configuration
    cat "${BOOTSTRAP_TEMPLATE}" \
      | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
      | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
      | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
      | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
      | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
      | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
      | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
      | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
      | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
      | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
      | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
      | sudo tee "${ENVOY_CONFIG}"
    
    # Install Envoy binary
    wget -O envoy_key https://apt.envoyproxy.io/signing.key
    cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
    sudo apt-get update
    sudo apt-get install envoy
    
    # Run Envoy as systemd service
    sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
      --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
      bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"
    
    # Configure iptables for traffic interception and redirection
    sudo ${ENVOY_USER_HOME}/iptables.sh \
      -p "${ENVOY_PORT}" \
    -u "${ENVOY_USER_UID}" \
      -g "${ENVOY_USER_GID}" \
      -m "REDIRECT" \
      -i "${INTERCEPTED_CIDRS}" \
      -x "${GCE_METADATA_SERVER}"
    '
    
    gcloud compute instances create td-vm-client \
      --zone=${ZONE} \
      --source-instance-template td-vm-template
    
  2. 登录已创建的虚拟机:

    gcloud compute ssh td-vm-client --zone=${ZONE}
    
  3. 验证与所创建的测试服务的连接:

    curl 10.0.0.1:10000 --http0.9 -v
    

    您应该会看到返回的文本 Hello from TCP service,并且能够看到在远程虚拟机上运行的 netcat 服务返回的任何文本。

宿主项目中的区域网格配置

将项目指定为宿主项目。任何有权在此项目中创建/更新/删除网格的服务账号都可以控制附加到此项目中区域性网格的路由配置。

  1. 定义一个将在整个示例中使用的变量:

    export REGION="us-central1"
    

    您可以选择将 us-central1 替换为您要使用的其他区域。

  2. 创建网格规范并将其存储在 mesh.yaml 文件中:

    cat <<EOF > mesh.yaml
    name: shared-mesh
    EOF
    
  3. 在此项目中定义一个具有所需配置的网格资源:

    gcloud network-services meshes import shared-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

    记下此网格资源的完整 URI。服务所有者将来需要使用此 URI 将其路由关联到此网格。

  4. networkservices.meshes.use IAM 权限授予此网格以及能够将其服务信息关联到此网格的跨项目服务账号:

    gcloud projects add-iam-policy-binding HOST_PROJECT_NUMBER --member='HTTP_ROUTE_SERVICE_OWNER_ACCOUNT' --role='roles/compute.networkAdmin'
    

    现在,被授予 networkservices.meshes.use 权限的所有服务所有者都可以将其路由规则添加到此网格。

服务项目中的路由配置

每个服务所有者都需要在其项目中创建区域后端服务和区域路由资源,类似于使用 HTTP 服务设置 Envoy 代理。唯一的区别是,每个 HTTPRoute/GRPCRoute/TCPRoute 都将在 meshes 字段中包含宿主项目的网格资源的 URI。

  1. 创建 sharedvpc-http-route:

    echo "name: sharedvpc-http-route
    hostnames:
    - helloworld-gce
    meshes:
    - /projects/HOST_PROJECT_NUMBER/locations/${REGION}/meshes/shared-mesh
    rules:
    - action:
        destinations:
        - serviceName: \"SERVICE_URL\"" | \
    gcloud network-services http-routes import sharedvpc-http-route \
        --source=- \
        --location=${REGION}
    

在服务项目中配置客户端服务

配置位于服务项目中的 Cloud Service Mesh 客户端(Envoy 代理或无代理客户端)时,需要在其引导配置中指定网格资源所在的项目编号和网格名称:

TRAFFICDIRECTOR_GCP_PROJECT_NUMBER=HOST_PROJECT_NUMBER
TRAFFICDIRECTOR_MESH_NAME=MESH_NAME

网关 TLS 路由

本部分演示了如何使用区域级网关和区域级 TLSRoute 资源设置基于 Envoy 代理的入站流量网关。

区域级外部直通式网络负载平衡器会将流量定向到充当入站流量网关的 Envoy 代理。Envoy 代理使用 TLS 直通路由并将流量定向到后端虚拟机实例上运行的 HTTPS 服务器。

定义一些将在整个示例中使用的变量。

export PROJECT_ID="PROJECT_ID"
export PROJECT_NUMBER="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-b"
export NETWORK_NAME = "default"

替换以下内容:default

  • PROJECT_ID 替换为您的项目 ID。
  • PROJECT_NUMBER 替换为您的项目编号。

您可以选择性地替换以下内容:

  • us-central1 替换为您要使用的其他区域。
  • us-central1-b 替换为您要使用的其他可用区。
  • default 替换为您要使用的其他网络名称。

在多项目共享 VPC 环境中交叉引用区域网格和区域路由资源

在某些场景下,服务网格配置包含由不同项目拥有的服务。例如,在共享 VPC 或对等互连 VPC 部署中,每个项目所有者都可以定义自己的一组服务,以使这些服务可用于所有其他项目。

此配置称为“跨项目”配置,因为将不同项目中定义的多个资源相结合,形成可提供给代理或无代理客户端的单个配置。

配置防火墙规则

  1. 配置防火墙规则,以允许来自任何来源的流量。修改端口和来源 IP 地址范围的命令。

    gcloud compute firewall-rules create allow-gateway-health-checks \
    --network=${NETWORK_NAME} \
    --direction=INGRESS \
    --action=ALLOW \
    --rules=tcp \
    --source-ranges="35.191.0.0/16,209.85.152.0/22,209.85.204.0/22" \
    --target-tags=gateway-proxy
    

配置 IAM 权限

  1. 为网关代理创建服务账号身份:

    gcloud iam service-accounts create gateway-proxy
    
  2. 将所需的 IAM 角色分配给服务账号身份:

    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="serviceAccount:gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \
      --role="roles/trafficdirector.client"
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="serviceAccount:gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \
      --role="roles/logging.logWriter"
    

配置区域级网关:

  1. 在名为 gateway8443.yaml 的文件中,创建用于 HTTP 流量的 Gateway 规范:

    cat <<EOF > gateway8443.yaml
    name: gateway8443
    scope: gateway-proxy-8443
    ports:
    - 8443
    type: OPEN_MESH
    EOF
    
  2. 使用 gateway8443.yaml 规范创建区域级 Gateway 资源:

    gcloud network-services gateways import gateway8443 \
        --source=gateway8443.yaml \
        --location=${REGION}
    

使用 Envoy 代理创建代管式实例组

在本部分中,您将为运行自动部署的 Envoy 服务代理的虚拟机创建实例模板。Envoy 的范围设置为 gateway-proxy。请勿将服务端口作为 --service-proxy 标志的参数传递。

  1. 使用 Envoy 代理创建代管式实例组:

    gcloud beta compute instance-templates create gateway-proxy \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=gateway-proxy,http-td-tag,http-server,https-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --network-interface=network=${NETWORK_NAME} \
      --service-account="gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \
      --metadata=startup-script='#! /usr/bin/env bash
    
    # Set variables
    export ENVOY_CONTROL_PLANE_REGION="us-central1"
    export GCP_PROJECT_NUMBER=PROJECT_NUMBER
    export VPC_NETWORK_NAME=scope:gateway-proxy-8443
    export ENVOY_USER="envoy"
    export ENVOY_USER_UID="1337"
    export ENVOY_USER_GID="1337"
    export ENVOY_USER_HOME="/opt/envoy"
    export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
    export ENVOY_PORT="15001"
    export ENVOY_ADMIN_PORT="15000"
    export ENVOY_TRACING_ENABLED="false"
    export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
    export ENVOY_ACCESS_LOG="/dev/stdout"
    export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
    export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
    export GCE_METADATA_SERVER="169.254.169.254/32"
    export INTERCEPTED_CIDRS="*"
    
    export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)
    
    # Create system user account for Envoy binary
    sudo groupadd ${ENVOY_USER} \
      --gid=${ENVOY_USER_GID} \
      --system
    sudo adduser ${ENVOY_USER} \
      --uid=${ENVOY_USER_UID} \
      --gid=${ENVOY_USER_GID} \
      --home=${ENVOY_USER_HOME} \
      --disabled-login \
      --system
    # Download and extract the Cloud Service Mesh tar.gz file
    cd ${ENVOY_USER_HOME}
    sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
      -C bootstrap_template.yaml \
      --strip-components 1
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
      -C iptables.sh \
      --strip-components 1
    sudo rm traffic-director-xdsv3.tar.gz
    
    # Generate Envoy bootstrap configuration
    cat "${BOOTSTRAP_TEMPLATE}" \
      | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
      | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
      | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
      | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
      | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
      | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
      | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
      | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
      | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
      | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
      | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
      | sudo tee "${ENVOY_CONFIG}"
    
    # Install Envoy binary
    wget -O envoy_key https://apt.envoyproxy.io/signing.key
    cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
    sudo apt-get update
    sudo apt-get install envoy
    
    # Run Envoy as systemd service
    sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
      --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
      bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"
    
    # Configure iptables for traffic interception and redirection
    sudo ${ENVOY_USER_HOME}/iptables.sh \
      -p "${ENVOY_PORT}" \
    -u "${ENVOY_USER_UID}" \
      -g "${ENVOY_USER_GID}" \
      -m "REDIRECT" \
      -i "${INTERCEPTED_CIDRS}" \
      -x "${GCE_METADATA_SERVER}"
    '
    
  2. 通过实例模板创建区域级代管式实例组:

    gcloud compute instance-groups managed create gateway-proxy \
      --region=${REGION} \
      --size=1 \
      --template=gateway-proxy
    
  3. 设置托管式实例组的服务端口名称:

    gcloud compute instance-groups managed set-named-ports gateway-proxy \
      --named-ports=https:8443 \
      --region=${REGION}
    

设置区域级外部直通网络负载均衡器

  1. 创建静态外部区域级 IP 地址:

    gcloud compute addresses create xnlb-${REGION} \
      --region=${REGION}
    
  2. 获取为外部负载均衡器预留的 IP 地址:

    gcloud compute addresses describe xnlb-${REGION} \
      --region=${REGION} --format='value(address)'
    
  3. 为网关代理创建健康检查:

    gcloud compute health-checks create tcp xnlb-${REGION} \
      --region=${REGION} \
      --use-serving-port
    
  4. 为网关代理创建后端服务:

    gcloud compute backend-services create xnlb-${REGION} \
      --health-checks=xnlb-${REGION} \
      --health-checks-region=${REGION} \
      --load-balancing-scheme=EXTERNAL \
      --protocol=TCP \
      --region=${REGION} \
      --port-name=https
    
  5. 将托管式实例组添加为后端:

    gcloud compute backend-services add-backend xnlb-${REGION} \
      --instance-group=gateway-proxy \
      --instance-group-region=${REGION} \
      --region=${REGION}
    
  6. 创建转发规则以将流量路由到网关代理:

    gcloud compute forwarding-rules create xnlb-${REGION} \
      --region=${REGION} \
      --load-balancing-scheme=EXTERNAL \
      --address=${IP_ADDRESS} \
      --ip-protocol=TCP \
      --ports=8443 \
      --backend-service=xnlb-${REGION} \
      --backend-service-region=${REGION}
    

配置运行 HTTPS 服务的代管式实例组

  1. 使用在端口 8443 上公开的 HTTPS 服务创建实例模板:

    gcloud compute instance-templates create td-https-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=https-td-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script='#! /bin/bash
    
    sudo rm -rf /var/lib/apt/lists/*
    sudo apt-get -y clean
    sudo apt-get -y update
    sudo apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common
    sudo curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
    sudo add-apt-repository -y "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
    sudo apt-get -y update
    sudo apt-get -y install docker-ce
    sudo which docker
    echo "{ \"registry-mirrors\": [\"https://mirror.gcr.io\"] }" | sudo tee -a /etc/docker/daemon.json
    sudo service docker restart
    sudo docker run -e HTTPS_PORT=9999 -p 8443:9999 --rm -dt mendhak/http-https-echo:22'
    
  2. 基于实例模板创建托管式实例组:

    gcloud compute instance-groups managed create https-td-mig-us-${REGION} \
      --zone=${ZONE} \
      --size=2 \
      --template=td-https-vm-template
    
  3. 设置托管式实例组的服务端口的名称:

    gcloud compute instance-groups managed set-named-ports https-td-mig-us-${REGION} \
      --named-ports=https:8443 \
      --zone=${ZONE}
    
  4. 创建运行状况检查:

    gcloud compute health-checks create https https-helloworld-health-check \
      --port=8443 --region=${REGION}
    
  5. 创建防火墙规则以允许传入的健康检查关联到您网络中的实例:

    gcloud compute firewall-rules create https-vm-allow-health-checks \
      --network ${NETWORK_NAME} --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --target-tags https-td-server \
      --rules tcp:8443
    
  6. 创建负载均衡方案为 INTERNAL_SELF_MANAGED 的区域性后端服务,并添加健康检查:

    gcloud compute backend-services create https-helloworld-service \
      --region=${REGION} \
      --load-balancing-scheme=INTERNAL_SELF_MANAGED \
      --port-name=https \
      --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/https-helloworld-health-check"
    
  7. 将托管式实例组作为后端添加到后端服务:

    gcloud compute backend-services add-backend https-helloworld-service \
      --instance-group=https-td-mig-us-${REGION} \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

使用 TLSRoute 资源设置路由

  1. 在名为 tls_route.yaml 的文件中,创建 TLSRoute 规范:

    cat <<EOF > tls_route.yaml
    name: helloworld-tls-route
    gateways:
    - projects/${PROJECT_NUMBER}/locations/${REGION}/gateways/gateway8443
    rules:
    - matches:
      - sniHost:
        - example.com
        alpn:
        - h2
      action:
        destinations:
        - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/https-helloworld-service
    EOF
    

    在上一个指令中,TLSRoute 将 example.com 作为 SNI 匹配,并将 h2 作为 ALPN 匹配。如果匹配项按如下方式更改,则 TLSRoute 会匹配 SNI 或 ALPN:

    - matches:
      - sniHost:
        - example.com
      - alpn:
        - h2
    
  2. 使用 tls_route.yaml 规范创建 TLSRoute 资源:

    gcloud network-services tls-routes import helloworld-tls-route \
        --source=tls_route.yaml \
        --location=${REGION}
    

验证部署

  1. 运行以下 curl 命令以验证与您创建的测试服务之间的 HTTP 连接:

    curl https://example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k
    
  2. 该命令会返回托管式实例组中某个虚拟机的响应。输出类似于以下内容:

    {
      "path": "/",
      "headers": {
        "host": "example.com:8443",
        "user-agent": "curl/8.16.0",
        "accept": "*/*"
      },
      "method": "GET",
      "body": "",
      "fresh": false,
      "hostname": "example.com",
      "ip": "::ffff:10.128.0.59",
      "ips": [],
      "protocol": "https",
      "query": {},
      "subdomains": [],
      "xhr": false,
      "os": {
        "hostname": "19cd7812e792"
      },
      "connection": {
        "servername": "example.com"
      }
    

使用否定验证方法进行验证

  1. 在以下命令中,SNI 与 example.com 不匹配,因此网关会拒绝连接:

    curl https://invalid-server.com:8443 --resolve invalid-server.com:8443:${IP_ADDRESS} -k
    
  2. 在以下命令中,ALPN 与 h2(HTTP2 协议)不匹配,因此网关会拒绝连接:

    curl https://example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k --http1.1
    

    上述命令均会返回以下错误:

    curl: (35) OpenSSL SSL_connect: Connection reset by peer in connection.
    
  3. 在以下命令中,客户端将创建一个纯文本(未加密)连接,因此网关会拒绝该连接,并显示“404 Not Found”错误:

    curl example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k