本文是从零学习envoy笔记第四章 - 后端路由
  • 从零学习envoy笔记 - Gateway总览
  • 从零学习envoy笔记 - 学习EG API和Gateway API
  • 从零学习envoy笔记 - 快速部署实验环境
  • 从零学习envoy笔记 - 官方Task Backend Routing
  • 从零学习envoy笔记 - 官方Task Backend Utilization Load Balancing
  • 从零学习envoy笔记 - 官方Task Bandwidth Limit
  • 从零学习envoy笔记 - 官方Task Client Traffic Policy

BackendTrafficPolicy

Backend 是 Envoy Gateway 扩展 CRD,用于直接配置后端 endpoint,比如外部域名、外部 IP、Unix Socket 等。

Backend 更方便的理解是,用于指向一个后端服务

示例 1:后端是外部域名

text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
kind: Backend
metadata:
  name: external-httpbin
  namespace: default
spec:
  type: Endpoints
  endpoints:
    - fqdn:
        hostname: www.baidu.com
        port: 80

需要注意的是,backend 本身只是顶一个 endpoint (相对于其他proxy的概念来理解),所以真实可以访问还需要定义 HTTPRoute 等后端

yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: baidu-route
  namespace: default
spec:
  parentRefs:
    - name: eg
  hostnames:
    - baidu.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      filters:
        - type: URLRewrite
          urlRewrite:
            hostname: www.baidu.com
      backendRefs:
        - group: gateway.envoyproxy.io
          kind: Backend
          name: external-httpbin
          port: 80

上面示例是一个外部的 Backend, 通过 envoy 吧 baidu.example.com 代理到 baidu.com

示例2 - Dynamic Forward Proxy

Dynamic Forward Proxy 是指 EG 不提前写死后端地址,而是根据请求里的 Host 动态解析目标域名,然后转发出去。

在配置上理解就是,Envoy Gateway 通过 Backend API,把 Backend.spec.type 设置成 DynamicResolver,底层用的是 Envoy 的 Dynamic Forward Proxy。

首先映射 envoy 端口 (使用 kind 的方式)

text
1
2
3
4
5
6
# Envoy Service
export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system \
  --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg \
  -o jsonpath='{.items[0].metadata.name}')
# 映射端口
kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80

准备 yaml,效果为:Envoy 会根据请求 Host 或重写后的 Host 做 DNS 解析并转发

text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
cat <<YAML | k apply -n default -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: eg
  namespace: default
spec:
  gatewayClassName: envoy-gateway-class
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      hostname: proxy.example.com
      allowedRoutes:
        namespaces:
          from: Same
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: HTTPRouteFilter
metadata:
  name: host-rewrite-from-header
  namespace: default
spec:
  urlRewrite:
    hostname:
      type: Header
      header: x-dynamic-host-header
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: dynamic-gray-red-route
  namespace: default
spec:
  parentRefs:
    - name: eg
  hostnames:
    - proxy.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - group: gateway.envoyproxy.io
          kind: Backend
          name: backend-dynamic-resolver
      filters:
        - type: ExtensionRef
          extensionRef:
            group: gateway.envoyproxy.io
            kind: HTTPRouteFilter
            name: host-rewrite-from-header
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: Backend
metadata:
  name: backend-dynamic-resolver
  namespace: default
spec:
  type: DynamicResolver
YAML

访问 gray 服务

text
1
2
3
4
curl -i \
  -H "Host: proxy.example.com" \
  -H "x-dynamic-host-header: envoy-end-gray.default.svc.cluster.local" \
  http://127.0.0.1:8888/colorful

验证结果

text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ curl -i   -H "Host: proxy.example.com"   -H "x-dynamic-host-header: envoy-end-gray.default.svc.cluster.local"   http://127.0.0.1:8888/colorful
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
date: Thu, 18 Jun 2026 13:09:34 GMT
content-length: 30

{"message":"hello with gray."}

$ curl -i   -H "Host: proxy.example.com"   -H "x-dynamic-host-header: envoy-end-red.default.svc.cluster.local"   http://127.0.0.1:8888/colorful
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
date: Thu, 18 Jun 2026 13:09:48 GMT
content-length: 29

{"message":"hello with red."}

实际上的流程为

text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Client
  |
  | 传入 Header Host: proxy.example.com
  | 传入 Header x-dynamic-host-header: envoy-end-gray.default.svc.cluster.local
  v
Gateway / HTTPRoute
  |
  | HTTPRouteFilter 把后端 Host 改成 gray 的 Service
  v
Backend type: DynamicResolver
  |
  | 动态解析 envoy-end-gray.default.svc.cluster.local
  v
gray service

遇到一个小问题,kind 在主机重启后,存在数据丢失

这里 False 这说明 没有成功生成数据面 Envoy Proxy

text
1
2
3
$ kubectl get gateway -n default
NAME   CLASS                 ADDRESS   PROGRAMMED   AGE
eg     envoy-gateway-class             False        27h

通常通过 describe 或者查看 controller 日志来查看

text
1
2
3
kubectl describe gateway eg -n default
# 或者
kubectl logs -n envoy-gateway-system deploy/envoy-gateway --tail=200

找到日志发现,Gateway 还在引用 “envoy-gateway-class”,GatewayClass 因为重启已经不存在了。需要重建

text
1
2
failed to get GatewayClass
GatewayClass.gateway.networking.k8s.io "envoy-gateway-class" not found

重建 GatewayClass

text
1
2
3
4
5
6
7
8
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: envoy-gateway-class
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
EOF

然后就可以看到数据面的恢复了

text
1
2
3
4
5
6
7
8
9
$ kubectl get gatewayclass
NAME                  CONTROLLER                                      ACCEPTED   AGE
eg                    gateway.envoyproxy.io/gatewayclass-controller   True       27h
envoy-gateway-class   gateway.envoyproxy.io/gatewayclass-controller   True       4m22s

$ kp -n envoy-gateway-system
NAME                                         READY   STATUS    RESTARTS        AGE
envoy-default-eg-e41e7b31-7f9554b6c5-2jg9d   2/2     Running   0               4m53s
envoy-gateway-867494677b-qlnwl               1/1     Running   2 (6h14m ago)   25h

官方示例 [1]

text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cat <<EOF | kubectl apply -f -
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: dynamic-forward-proxy
spec:
  parentRefs:
    - name: eg
  rules:
    - backendRefs:
      - group: gateway.envoyproxy.io
        kind: Backend
        name: backend-dynamic-resolver
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: Backend
metadata:
  name: backend-dynamic-resolver
spec:
  type: DynamicResolver
  tls:
    wellKnownCACertificates: System
EOF

这里就是通过请求,当请求 envoy 的地址时,直接请求到 Header HOST 配置地址 gateway.envoyproxy.io

text
1
curl -HHost:gateway.envoyproxy.io http://${GATEWAY_HOST}

Reference

[1] Forwarding Based on the Original Host