目录
概述
准备工作
创建 Service A
创建 Service B
创建 Envoy 代理和负载均衡
创建 Traffic Director 对象
测试请求分流
总结
概述
Traffic Director 是 Google Cloud 的全代管式应用网络平台和服务网格。使用 Traffic Director,您可以在多个区域跨多个集群和虚拟机 (VM) 实例部署全球负载均衡机制、将原来由服务代理执行的健康检查工作分流,以及配置复杂的流量控制政策。Traffic Director 也可帮助您在全局服务网格中运行微服务。网格负责处理微服务的网络,因此您可以编写不需要了解底层网络复杂性的应用代码。应用逻辑与网络逻辑之间的这种分离可让您提高开发速度,提高服务可用性,并为贵组织引入现代 DevOps 做法。
服务网格由应用、与 xDS 兼容的数据平面(通常是开源 Envoy 代理)和作为网格控制层面的 Traffic Director 组成。Traffic Director 是在 Google Cloud 中运行的代管式、高可用性控制平面服务。您无需安装或更新控制层面,因此可以在服务网格基础架构中管理一个较少的组件。
本文用一个实例说明Traffic Director的基本使用方法和功能。本实例架构如下图所示,使用Traffic Director控制的envoy代理服务器集群接收谷歌云HTTP(S) Load Balance转发的请求,并对请求进行分流,再分发到两个不同的后端服务。其中一个后端服务Service A由虚机实例组搭建,另一个后端服务Service B则用GKE集群上的service搭建。在不同的环境中搭建两个不同的服务只是为了演示说明,实际使用中也可以在同一个环境中搭建多个服务。

准备工作
在配置 Traffic Director 相关组件和服务之前,要先开通服务。
gcloud services enable trafficdirector.googleapis.com
gcloud services enable \\ osconfig.googleapis.com \\ trafficdirector.googleapis.com \\ compute.googleapis.com \\ networkservices.googleapis.com |
创建 Service A
首先用非托管虚机实例组创建一个 HTTP 服务 Service A。创建基本步骤为
创建一个虚机实例,其上安装运行 Nginx
创建一个非托管实例组,并将上述虚机加入此实例组
创建健康检查和后端服务,并将后端服务指向上述实例组
注意,后端服务的类型为 INTERNAL_SELF_MANAGED。这是 Traffic Director 专用的后端服务类型。
gcloud compute instances create vm-service-a-nginx-1 \\ --image-family=ubuntu-1804-lts \\ --image-project=ubuntu-os-cloud \\ --machine-type=n2-standard-2 \\ --zone=asia-southeast1-b \\ --tags=http-server \\ --metadata=startup-script='#! /bin/bash apt update apt -y install nginx service nginx start'
gcloud compute instance-groups unmanaged create uig-svc-a-nginx-1 \\ --project=youzhi-lab \\ --zone=asia-southeast1-b \\ --named-ports=http:80
gcloud compute instance-groups unmanaged add-instances uig-svc-a-nginx-1 \\ --project=youzhi-lab \\ --zone=asia-southeast1-b \\ --instances=vm-service-a-nginx-1
gcloud compute health-checks create http health-check-svc
gcloud compute backend-services create bs-svc-a \\ --global \\ --load-balancing-scheme=INTERNAL_SELF_MANAGED \\ --protocol=HTTP \\ --health-checks health-check-svc-a
gcloud compute backend-services add-backend bs-svc-a \\ --instance-group uig-svc-a-nginx-1 \\ --instance-group-zone asia-southeast1-b \\ --global |
创建Service B
现在,在 GKE 集群上创建另一个 HTTP 服务 Service B。如果项目中还没有 GKE 集群,需要先创建一个集群。
在集群详情页中选中一个节点,查看其网络标签,如下所示。

针对上述网络标签创建一个防火墙规则,放行所有谷歌云负载均衡发起的健康检查请求。
gcloud compute --project=youzhi-lab firewall-rules create gke-allow-health-checks \\ --direction=INGRESS \\ --priority=1000 \\ --network=default \\ --action=ALLOW \\ --rules=tcp \\ --source-ranges=35.191.0.0/16,209.85.152.0/22,209.85.204.0/22, 130.211.0.0/22 \\ --target-tags=gke-demo-cluster-sin-de6153dd-node |
创建一个名为 td-gke-svc-b.yaml 的文件,并输入以下内容。这些代码定义了一个基于 serve-hostname-amd64 容器镜像的 deployment,并基于此 deployment 创建了一个 NEG 类型的 service。
apiVersion: v1 kind: Service metadata: name: td-gke-service-b annotations: cloud.google.com/neg: '{"exposed_ports":{"80":{"name": "td-gke-service-b"}}}' spec: ports: - port: 80 name: service-entry protocol: TCP targetPort: 8000 selector: run: app1 type: ClusterIP
---
apiVersion: apps/v1 kind: Deployment metadata: labels: run: app1 name: deployment-service-b spec: replicas: 2 selector: matchLabels: run: app1 template: metadata: labels: run: app1 spec: containers: - image: gcr.io/kubernetes-e2e-test-images/serve-hostname-amd64:1.1 name: app1 command: - /bin/sh - -c - /serve_hostname -http=true -udp=false -port=8000 ports: - protocol: TCP containerPort: 8000 |
部署上述 deployment 和 service。
kubectl apply -f ./td-gke-svc-b.yaml |
现在,运行以下命令查看上述 service 所生成的网络端点组信息,以用于后面步骤创建端点组类型的后端服务。
gcloud compute network-endpoint-groups list |grep td-gke-service-b td-gke-service-b asia-southeast1-a GCE_VM_IP_PORT 1 td-gke-service-b asia-southeast1-b GCE_VM_IP_PORT 0 td-gke-service-b asia-southeast1-c GCE_VM_IP_PORT 1 |
可以看到,已经创建了3个同名的网络端点组,每个端点组在一个单独的 zone。
现在,创建一个用于网络端点组的健康检查,以及 INTERNAL_SELF_MANAGED 类型的后端服务,并将上述网络端点组作为后端添加到此后端服务。注意添加网络端点组后端时,可以根据服务用到的不同协议,比如 HTTP 或者 TCP,使用 RATE 或者 CONNECTION 均衡模式。
gcloud compute health-checks create http health-check-svc-neg \\ --use-serving-port
gcloud compute backend-services create bs-td-gke-service-b \\ --global \\ --health-checks health-check-svc-neg \\ --load-balancing-scheme INTERNAL_SELF_MANAGED
gcloud compute backend-services add-backend bs-td-gke-service-b \\ --global \\ --network-endpoint-group td-gke-service-b \\ --network-endpoint-group-zone asia-southeast1-a \\ --balancing-mode RATE \\ --max-rate-per-endpoint 50
gcloud compute backend-services add-backend bs-td-gke-service-b \\ --global \\ --network-endpoint-group td-gke-service-b \\ --network-endpoint-group-zone asia-southeast1-b \\ --balancing-mode RATE \\ --max-rate-per-endpoint 50
gcloud compute backend-services add-backend bs-td-gke-service-b \\ --global \\ --network-endpoint-group td-gke-service-b \\ --network-endpoint-group-zone asia-southeast1-c \\ --balancing-mode RATE \\ --max-rate-per-endpoint 50 |
创建 Envoy 代理和负载均衡
现在,需要创建一个 Envoy 代理虚机实例组,以及 HTTP 全球负载均衡,以接收外部请求。
首先创建 Envoy 客户端读取 Traffic Director 指令要用到的服务账号,以及放行负载均衡健康检查要用到的防火墙规则。
gcloud iam service-accounts create gateway-proxy
gcloud projects add-iam-policy-binding youzhi-lab \\ --member="serviceAccount:gateway-proxy@youzhi-lab.iam.gserviceaccount.com" \\ --role="roles/trafficdirector.client"
gcloud projects add-iam-policy-binding youzhi-lab \\ --member="serviceAccount:gateway-proxy@youzhi-lab.iam.gserviceaccount.com" \\ --role="roles/logging.logWriter"
gcloud compute firewall-rules create allow-gateway-health-checks \\ --network=default \\ --direction=INGRESS \\ --action=ALLOW \\ --rules=tcp \\ --source-ranges="35.191.0.0/16,209.85.152.0/22,209.85.204.0/22,130.211.0.0/22" \\ --target-tags=gateway-proxy
gcloud compute firewall-rules create allow-gateway-ingress-traffic \\ --network=default \\ --direction=INGRESS \\ --action=ALLOW \\ --rules=tcp:80,tcp:443 \\ --source-ranges="0.0.0.0/0" \\ --target-tags=gateway-proxy |
创建一个自动安装 Envoy 客户端的虚机模板。注意--service-proxy=enabled 参数会使实例自动安装 Envoy 代理,以及 service proxy agent。后者会初始化 Envoy、配置请求拦截并监控 Envoy 代理的状态。
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=default,no-address \\ --service-account="gateway-proxy@youzhi-lab.iam.gserviceaccount.com" \\ --service-proxy=enabled,scope=gateway-proxy |
基于上面的虚机模板,创建一个托管实例组,并配置伸缩规则。
gcloud compute instance-groups managed create mig-gateway-proxies-sin \\ --region=asia-southeast1 \\ --size=2 \\ --template=gateway-proxy \\ --target-distribution-shape=EVEN
gcloud compute instance-groups managed set-named-ports \\ mig-gateway-proxies-sin \\ --region=asia-southeast1 \\ --named-ports=healthz:80
gcloud compute instance-groups managed set-autoscaling \\ mig-gateway-proxies-sin \\ --region=asia-southeast1 \\ --cool-down-period=60 \\ --min-num-replicas=3 \\ --max-num-replicas=10 \\ --mode=on \\ --target-cpu-utilization=0.6 |
该实例组可以接收不同类型的负载均衡,以从内网或者外网接收 HTTP、gRPC 或者 TCP 协议请求。本实例下面配置一个 HTTP 类型的全球负载均衡。
gcloud compute backend-services create bs-td-service-test \\ --protocol HTTP \\ --health-checks health-check-svc \\ --global \\ --enable-cdn \\ --enable-logging \\ --port-name=healthz \\ --timeout=60
gcloud compute backend-services add-backend bs-td-service-test \\ --instance-group=mig-gateway-proxies-sin \\ --instance-group-region=asia-southeast1 \\ --global
gcloud compute url-maps create urlmap-td-service-test \\ --default-service bs-td-service-test
gcloud compute target-http-proxies create target-proxy-td-service-test \\ --url-map urlmap-td-service-test
gcloud compute forwarding-rules create fwrl-td-service-test \\ --global \\ --target-http-proxy=target-proxy-td-service-test \\ --ports=80 |
配置生效后,可以运行以下命令获取负载均衡的对外 IP 地址。
gcloud compute forwarding-rules describe fwrl-td-service-test --global IPAddress: 34.111.121.78 IPProtocol: TCP |
可以看到地址为34.111.121.78。此地址将在后面测试时使用。
创建 Traffic Director 对象
现在需要创建 Traffic Director 资源,以将 Envoy 代理和两个后端服务连接起来。下面创建了一个 Gateway 资源和一个 HTTPRoute 资源。其中 Gateway 用于配置 Envoy 代理处理南北流量的流量管理和安全配置。而 HTTPRoute 资源用于针对 HTTP 请求的路由配置。
从 HTTPRoute 的配置中可以看到,我们将入向请求分发到两个不同的后端服务,分别与前述章节创建的 Service A 和 Service B 的 URI 对应。
cat <<EOF | tee gateway_service_test.yaml name: gateway-service-test scope: gateway-proxy ports: - 80 type: OPEN_MESH EOF
cat <<EOF | tee service_test_http_route.yaml name: http-route-service-test hostnames: - '*' gateways: - projects/youzhi-lab/locations/global/gateways/gateway-service-test rules: - action: destinations: - serviceName: "projects/youzhi-lab/locations/global/backendServices/bs-svc-a" weight: 50 - serviceName: "projects/youzhi-lab/locations/global/backendServices/bs-td-gke-service-b" weight: 50 EOF
gcloud alpha network-services gateways import gateway-service-test \\ --source=gateway_service_test.yaml \\ --location=global
gcloud alpha network-services http-routes import http-route-service-test \\ --source=service_test_http_route.yaml \\ --location=global |
至此所有配置完成。
测试请求分流
为了测试流量分布,我们从本地笔记本发起并发的HTTP请求,使用以下命令。其中测试地址为HTTP全球负载均衡的访问地址。
ab -n 15000 -c 5 -m GET -v 3 http://34.111.121.78/ |
Traffic Director 的流量监控已经集成在谷歌云的统一监控服务。为了查看流量请求在两个不同后端服务的分流,需要先获取两个不同后端服务的数字 ID。使用如下命令。
gcloud compute backend-services describe bs-svc-a --global |grep id id: '7581516333227411972'
gcloud compute backend-services describe bs-td-gke-service-b --global |grep id id: '5065631019304195090' |
在谷歌云控制台 Monitoring 监控服务中选择 Metrics Explorer,并在 MQL 脚本窗口中输入以下脚本。然后可以在实时监控图表中看到流量的数量和分布。
fetch gce_backend_service
| metric 'trafficdirector.googleapis.com/xds/server/request_count'
| align rate(1m)
| every 1m
| group_by [resource.backend_service_id],
[value_request_count_aggregate: aggregate(value.request_count)]
当两个服务在 HTTPRoute 中配置的权重分布为50/50时,可以看到流量分布如下图。

当两个服务在 HTTPRoute 中配置的权重分布为90/10时,可以看到流量分布如下图。

当 HTTPRoute 中只配置了一个服务,即100%导流向该服务时,可以看到流量分布如下图。

总结
本文演示了使用 Traffic Director 和 Envoy 实现一个基本的南北流量分流。此功能也可以使用搭建 Nginx 集群的方式实现,但是相比而言,Traffic Director 和 Envoy 的方式利用了谷歌云的托管高可用控制平面,而且所有的 Envoy 配置创建和变更可以自动同步下发到所有的 Envoy 节点,其可用性、一致性和自动性更高。
除了流量分流,该架构也可以用于流量监控、重定向、请求改写、请求镜像和错误注入等目的。