在 Kubernetes 的日常运维中,我们习惯了使用 Ingress 来处理 HTTP/HTTPS 七层流量。但当面临需要暴露数据库、游戏服务或 DNS 等四层协议时,传统的 Ingress 就有些力不从心了。Envoy Gateway 凭借其基于 Kubernetes Gateway API 的原生设计和强大的 Envoy 代理内核,为解决 TCP/UDP 流量路由提供了优雅的方案。本文将手把手带你完成 Envoy Gateway 中 TCP 和 UDP 路由的配置。

上图清晰地展示了 Envoy Gateway 的核心架构:外部请求流量经由网关(Gateway)管理的代理(Proxy)节点,最终被路由到后端用户应用(User App)。网关则通过静态或动态配置进行管理。
核心概念:TCPRoute 与 UDPRoute
在遵循 Gateway API 标准的 Envoy Gateway 架构中,不同类型的流量由不同的路由资源处理:
- HTTPRoute:用于处理 HTTP/HTTPS 流量。
- TCPRoute:用于处理面向连接的、基于流的 TCP 流量,常见于 MySQL、PostgreSQL、Redis、SSH 等服务。
- UDPRoute:用于处理无连接的、基于数据报的 UDP 流量,常见于 DNS、游戏服务器、QUIC 等场景。
无论是 TCPRoute 还是 UDPRoute,都需要绑定到一个监听了对应协议(TCP 或 UDP)的 Gateway 资源上,才能生效。
实战:配置 TCP 路由
假设我们已经有一个基础的 HTTP Gateway 环境,现在需要为其增加 TCP 路由能力,将 2084 端口的 TCP 流量路由到后端的 simple Service。
1. 为现有 Gateway 添加 TCP 监听器
首先,我们通过 kubectl patch 命令,在已有的 Gateway 资源 simple-gw 上新增一个 TCP 类型的监听器。
$ kubectl patch gateway simple-gw --type=json --patch '[
{
"op": "add",
"path": "/spec/listeners/-",
"value": {
"name": "tcp-2084",
"port": 2084,
"protocol": "TCP"
}
}
]'
gateway.gateway.networking.k8s.io/simple-gw patched
2. 验证 Gateway 与 Envoy 监听状态
应用补丁后,需要确认 Envoy 代理 Pod 是否已成功监听 2084 端口。
$ sudo crictl ps | grep simple-gw
a9aa1fb792260 a1ea73ec74e58 24 minutes ago Running shutdown-manager 0 e3c0b55bc1a1a envoy-default-simple-gw-d9e70e75-654d8db7d7-85ggn
52d6f9253a884 c36c3dd237ac4 24 minutes ago Running envoy 0 e3c0b55bc1a1a envoy-default-simple-gw-d9e70e75-654d8db7d7-85ggn
$ sudo crictl inspect 52d6f9253a884 | grep pid
"pid": 17169,
"pid": 1
"type": "pid"
$ sudo nsenter -t 17169 -n netstat -lntup | grep 2084
tcp 0 0 0.0.0.0:2084 0.0.0.0:* LISTEN 17169/envoy

输出显示 envoy 进程(PID 17169)已在 0.0.0.0:2084 端口上启动 TCP 监听,配置生效。
3. 创建 TCPRoute 资源
接下来,创建 TCPRoute 资源,明确指定流量规则:将所有进入 simple-gw 网关 tcp-2084 监听器的 TCP 流量,转发到 default 命名空间下 simple Service 的 80 端口。
$ cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: tcp-simple
spec:
# 绑定到指定的 Gateway
parentRefs:
- name: simple-gw
sectionName: tcp-2084 # 对应 gateway 中 listeners 的名称。若不指定,则应用于该 Gateway 的所有 listeners。
rules:
- backendRefs:
# 默认引用 Service 资源
- name: simple
port: 80
EOF
4. 查看服务暴露的 NodePort
Envoy Gateway 会为 Gateway 的每个监听器创建一个对应的 Service。我们需要找到 TCP 2084 端口映射到集群节点的哪个 NodePort。
$ kubectl -n envoy-gateway-system get svc -l gateway.envoyproxy.io/owning-gateway-name=simple-gw -ojsonpath='{.items[].spec.ports}' | jq .
[
{
"name": "http-80",
"nodePort": 30874,
"port": 80,
"protocol": "TCP",
"targetPort": 10080
},
{
"name": "tcp-2084",
"nodePort": 31486,
"port": 2084,
"protocol": "TCP",
"targetPort": 2084
}
]
提示:若你的环境不是公有云且未安装类似 MetalLB 的负载均衡器,则需要通过上述查询到的 nodePort(本例为 31486)在集群节点 IP 上进行访问。
5. 验证 TCP 路由功能
最后,我们通过访问节点的 NodePort 来验证 TCP 流量是否被正确路由到后端应用。假设后端应用有一个返回主机名的接口。
$ curl 172.139.20.19:31486/who/hostname
simple-97bcd47bd-4vpcx

请求成功并返回了后端 Pod 的主机名,证明 TCP 路由配置完全生效。
实战:配置 UDP 路由
UDP 路由的配置逻辑与 TCP 类似。这里我们以将 Kubernetes 内部的 CoreDNS 服务通过 UDP 协议暴露到集群外为例。为了隔离,我们将在 kube-system 命名空间下创建独立的 Gateway。
1. 在 kube-system 命名空间创建 UDP Gateway
首先,在 kube-system 命名空间下创建一个监听 5300 端口的 UDP 协议 Gateway。
cat <<'EOF' | kubectl apply -f -
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: simple-gw
namespace: kube-system
spec:
# Gateway 关联已创建的 GatewayClass
gatewayClassName: envoy-proxy-gwc
# 配置 Envoy 监听 UDP 端口
listeners:
- name: udp-5300
protocol: UDP
port: 5300
EOF
2. 创建 UDPRoute 资源
接着,创建 UDPRoute 资源,将到达该网关 5300 端口的 UDP 流量(DNS 查询)路由到 kube-system 命名空间下的 kube-dns Service(CoreDNS)的 53 端口。
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: UDPRoute
metadata:
name: udp-coredns
namespace: kube-system
spec:
parentRefs:
- name: simple-gw
sectionName: udp-5300
rules:
- backendRefs:
- name: kube-dns
namespace: kube-system
port: 53
EOF
3. 查看暴露的 UDP NodePort
同样,查询 Envoy Gateway 为这个 UDP 监听器创建的 Service,获取其 NodePort。
$ kubectl -n envoy-gateway-system get svc envoy-kube-system-simple-gw-da10de49 -ojsonpath='{.spec.ports}' | jq .
[
{
"name": "udp-5300",
"nodePort": 32709,
"port": 5300,
"protocol": "UDP",
"targetPort": 5300
}
]

4. 验证 UDP 路由功能
使用 dig 命令,指定 DNS 查询发送到集群节点的 NodePort(32709),查询一个内部 Kubernetes 服务域名,验证 UDP 路由是否正常工作。
$ dig @172.139.20.19 -p 32709 kubernetes.default.svc.cluster.local
; <<>> DiG 9.18.39-0ubuntu0.24.04.2-Ubuntu <<>> @172.139.20.19 -p 32709 kubernetes.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->HEADER<<- opcode: QUERY, status: NOERROR, id: 10409
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 0a5df5c8afe7d534 (echoed)
;; QUESTION SECTION:
;kubernetes.default.svc.cluster.local. IN A
;; ANSWER SECTION:
kubernetes.default.svc.cluster.local. 30 IN A 10.96.0.1
;; Query time: 3 msec
;; SERVER: 172.139.20.19#32709(172.139.20.19) (UDP)
;; WHEN: Tue Feb 24 17:14:23 CST 2026
;; MSG SIZE rcvd: 129

查询成功返回了 kubernetes.default.svc.cluster.local 的内部集群 IP 10.96.0.1,证明 UDP 路由配置正确,外部客户端可以通过 Envoy Gateway 访问集群内的 DNS 服务。
结语
通过以上实战步骤,我们可以看到 Envoy Gateway 通过标准的 Kubernetes Gateway API 资源(TCPRoute/UDPRoute)来管理四层流量,配置清晰且与 Kubernetes 生态无缝集成。对于运维和开发人员而言,掌握这套方法意味着能够统一管理集群的南北向流量,无论是 HTTP 微服务、TCP/IP 数据库还是 UDP 游戏服务,都能纳入同一套优雅的控制平面之下,极大地简化了网络配置与 运维 的复杂度。
希望本文的详细示例能为你在生产环境中落地 Envoy Gateway 提供切实可行的参考。如果你想了解更多云原生网络与运维相关的实战技巧,欢迎访问云栈社区与广大开发者交流探讨。