目录

概述

准备工作

创建 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。创建基本步骤为

  1. 创建一个虚机实例,其上安装运行 Nginx

  2. 创建一个非托管实例组,并将上述虚机加入此实例组

  3. 创建健康检查和后端服务,并将后端服务指向上述实例组

注意,后端服务的类型为 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 节点,其可用性、一致性和自动性更高。

除了流量分流,该架构也可以用于流量监控、重定向、请求改写、请求镜像和错误注入等目的。


相关推荐