设置网关 TLS 路由

本指南演示了如何使用 GatewayTLSRoute 资源设置基于 Envoy 代理的入站流量网关。TLSRoute 资源还可以挂接到 Mesh 资源,以使用边车代理设置 TLS 直通路由。

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

入站流量网关的 TLS 直通
入站流量网关的 TLS 直通(点击可放大)

准备工作

确保您的部署满足以下指南中描述的前提条件:

配置防火墙规则

在本部分中,您将创建防火墙规则以允许将传入健康检查连接到网络中的虚拟机实例。

  1. 创建防火墙规则:

    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
    
  2. 配置防火墙规则,以允许来自任何来源的流量。修改用于端口和来源 IP 地址范围的命令:

    gcloud compute firewall-rules create allow-gateway-ingress-traffic \
      --network=NETWORK_NAME \
      --direction=INGRESS \
      --action=ALLOW \
      --rules=tcp:443 \
      --source-ranges="0.0.0.0/0" \
      --target-tags=gateway-proxy
    

配置 Identity and Access Management 权限

在本部分中,您将为网关代理指定服务账号,并将正确的 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"
    

配置 Gateway 资源

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

    name: gateway443
    scope: gateway-proxy
    ports:
    - 443
    type: OPEN_MESH
    
  2. 使用 gateway443.yaml 规范创建 Gateway 资源:

    gcloud network-services gateways import gateway443 \
        --source=gateway443.yaml \
        --location=global
    

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

在本部分中,您将创建与入站流量网关关联的 Envoy 代理。

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

    gcloud beta compute instance-templates create gateway-proxy \
      --machine-type=n1-standard-1 \
      --boot-disk-size=10GB \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=gateway-proxy \
      --network-interface=network=NETWORK_NAME,no-address \
      --service-account="gateway-proxy@PROJECT_ID.iam.gserviceaccount.com" \
      --service-proxy=enabled,scope=gateway-proxy
    
  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:443 \
      --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)'
    

    此 IP 地址会在此设置指南后面的部分中用作 IP_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=443 \
      --backend-service=xnlb-REGION \
      --backend-service-region=REGION
    

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

出于演示目的,您可以在代管式实例组中创建包含自动扩缩虚拟机的后端服务。虚拟机回显有关使用端口 443 上的 HTTPS 协议的 Web 请求的详细信息。

  1. 使用在端口 443 上公开的 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-10 \
      --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 443: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:443 \
      --zone=ZONE
    
  4. 创建健康检查:

    gcloud compute health-checks create https https-helloworld-health-check \
      --port=443
    
  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:443
    
  6. 使用负载均衡方案 INTERNAL_SELF_MANAGED 创建全局后端服务并添加健康检查:

    gcloud compute backend-services create https-helloworld-service \
      --global \
      --load-balancing-scheme=INTERNAL_SELF_MANAGED \
      --port-name=https \
      --health-checks 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 \
      --global
    

使用 TLSRoute 资源设置路由

在前面的部分中,您配置了 Gateway 资源和 HTTPS 服务器。接下来,使用将 SNI 主机名与后端服务关联的 TLSRoute 资源将它们连接起来。

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

    name: helloworld-tls-route
    gateways:
    - projects/PROJECT_NUMBER/locations/global/gateways/gateway443
    rules:
    - matches:
      - sniHost:
        - example.com
        alpn:
        - h2
      action:
       destinations:
       - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/https-helloworld-service
    

    在上一个指令中,TLSRouteexample.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=global
    

Traffic Director 现已配置为在代管式实例组中的后端之间对 TLSRoute 资源中指定的服务进行流量负载均衡。

验证部署

在本部分中,您将验证是否可以通过外部直通网络负载均衡器和 Traffic Director Gateway 资源从外部客户端访问服务。

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

    curl https://example.com --resolve example.com:443:IP_ADDRESS -k
    

该命令会返回代管式实例组中某个虚拟机的响应。输出如下所示:

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

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

您还可以运行否定验证方法。如果您运行本部分中的命令,则请求会被丢弃,因为它与 TLSRoute 匹配条件不匹配。

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

curl https://invalid-server.com --resolve invalid-server.com:443:IP_ADDRESS -k

在以下命令中,ALPN 与 h2(HTTP2 协议)不匹配,因此 Gateway 会拒绝连接:

curl https://example.com --resolve example.com:443:IP_ADDRESS -k --http1.1

在以下命令中,客户端将创建一个纯文本(未加密)连接,因此 Gateway 会拒绝连接:

curl example.com:443 --resolve example.com:443:IP_ADDRESS -k

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

curl: (35) OpenSSL SSL_connect: Connection reset by peer in connection.