一、Envoy 是什么:从边车到数据平面
Envoy 是一款由 Lyft 开源、现已从 CNCF 毕业的高性能 L4/L7 代理,使用 C++ 编写、基于现代事件驱动架构。它既能以边车(sidecar)形态注入服务网格承担数据平面,也能独立充当边缘网关或 API 网关,统一管理路由、限流、鉴权与可观测性。与传统的反向代理相比,Envoy 的强项在于原生支持 xDS 动态配置、丰富的 L7 过滤器以及开箱即用的指标输出,这让它在云原生流量治理层里几乎成为事实标准。
对于一个正在做微服务拆分的团队来说,Envoy 的价值在于”把网络能力从应用里抽出来”。限流、重试、熔断、灰度、JWT 校验这些原本要写进每个服务的逻辑,现在可以下沉到统一的代理层。配合 Kubernetes 与 eBPF 网络策略,你能用一套声明式配置治理整张集群的南北向与东西向流量。
二、核心架构:Listener、Filter Chain、Cluster、Route
理解 Envoy,关键是抓住四个核心抽象,它们的数据流向是:请求先到达 Listener,经过 Filter Chain 处理,再由 Route 匹配到目标 Cluster,最后转发到后端端点(Endpoint)。
2.1 Listener 与 Filter Chain
Listener 负责监听端口,Filter Chain 是一串有序的网络/L7 过滤器。最典型的 L7 过滤器是 http_connection_manager,它负责解析 HTTP、执行路由、注入头信息、做限流与访问日志。每个过滤器都可以链式组合,这也是 Envoy 可扩展性强的根源。
2.2 Cluster 与 Endpoint
Cluster 描述一组逻辑上的后端服务,包含负载均衡策略、健康检查、连接池与超时配置。Endpoint 则是真正的上游实例地址。Cluster 既可以用静态地址写死,也可以由 EDS(Endpoint Discovery Service)动态下发,从而实现自动扩缩容感知。
三、快速上手:用 Docker 起一个 Envoy 边缘代理
下面用最小可运行的例子,让 Envoy 监听 8080 端口,把流量反向代理到后端 httpbin 服务。先准备静态配置文件与编排文件。
# envoy.yaml —— 静态配置的最小边缘代理
admin:
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }
static_resources:
listeners:
- name: listener_http
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains: ["*"]
routes:
- match: { prefix: "/" }
route: { cluster: backend }
http_filters:
- name: envoy.filters.http.router
clusters:
- name: backend
connect_timeout: 5s
type: logical_dns
lb_policy: round_robin
load_assignment:
cluster_name: backend
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: httpbin, port_value: 80 }
用 Docker Compose 把 Envoy 和后端一起拉起,访问 http://localhost:8080 即可看到被代理的响应。
# docker-compose.yaml
services:
envoy:
image: envoyproxy/envoy:v1.31-latest
command: ["-c", "/etc/envoy/envoy.yaml", "--log-level", "info"]
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml:ro
ports:
- "8080:8080"
- "9901:9901" # admin 端口,仅供调试
httpbin:
image: kennethreitz/httpbin
expose:
- "80"
启动后访问 http://localhost:9901/stats 就能拿到 Envoy 暴露的全部内部指标。如果你更习惯用 Docker Compose 编排多服务,这个组合是非常顺手的本地试验台。
四、动态配置与 xDS:让代理学会”自己变”
静态配置适合学习,生产环境则离不开 xDS——一组基于 gRPC 或 REST 的发现服务,包括 LDS(监听器)、RDS(路由)、CDS(集群)、EDS(端点)、SDS(密钥)。控制平面(如 Istio 的 pilot、或独立的 go-control-plane)推送配置,Envoy 热加载而无需重启进程。
# 在 bootstrap 里声明 ADS(聚合发现服务)即可接入动态配置
dynamic_resources:
ads_config:
api_type: GRPC
grpc_services:
- envoy_grpc: { cluster_name: xds_cluster }
lds_config: { ads: {} }
cds_config: { ads: {} }
static_resources:
clusters:
- name: xds_cluster
type: logical_dns
connect_timeout: 5s
load_assignment:
cluster_name: xds_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: control-plane, port_value: 18000 }
动态化的好处是立竿见影的:新增一个后端、改一条路由、下发一份证书,都不需要滚动重启代理。这也是 Istio 服务网格 能把流量治理玩出花的核心机制——Istio 的 pilot 本质上就是把 Kubernetes 资源翻译成 xDS 下发给每个 Envoy 边车。
五、把 Envoy 当 API 网关用:限流、JWT 鉴权与 ext_authz
Envoy 不止能做反向代理,它本身就能充当轻量 API 网关。最实用的三块能力是限流、JWT 校验和外部鉴权。
5.1 外部鉴权 ext_authz
把鉴权决策交给一个独立服务,Envoy 通过 envoy.filters.http.ext_authz 过滤器在转发前调用它。这样业务团队可以自己实现鉴权逻辑,而代理只负责”要不要放行”。
http_filters:
- name: envoy.filters.http.ext_authz
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
grpc_service:
envoy_grpc:
cluster_name: authz_service
failure_mode_allow: false # 鉴权服务不可用时拒绝,安全第一
- name: envoy.filters.http.router
5.2 JWT 校验与本地限流
Envoy 内置 jwt_authn 过滤器,可在代理层直接校验 Token 签名与声明,省去每个服务重复实现。限流则可结合本地 token bucket 过滤器或外接 Ratelimit 服务实现全局配额。需要更细的网关级路由与熔断编排时,也可以和 Spring Cloud Gateway 这类应用网关分层配合。
六、可观测性:stats、access log 与 Prometheus
Envoy 自带的指标非常丰富,默认覆盖了 upstream 连接数、请求成功率、往返时延、重试次数等。只要在配置里打开 Prometheus 格式的输出,就能直接被抓取。
static_configs:
- targets: ['envoy:9901'] # Envoy admin 端口暴露 /stats/prometheus
# Envoy 侧无需额外插件,admin 已原生支持:
# curl http://localhost:9901/stats/prometheus
# 关键指标示例:
# envoy_cluster_upstream_rq_2xx -> 成功请求数
# envoy_cluster_upstream_rq_5xx -> 5xx 错误数
# envoy_cluster_upstream_rq_time -> 上游时延直方图
# envoy_http_downstream_rq_total -> 总入站请求数
把 Envoy 的指标接进 Prometheus 后,再配合 Grafana 看板,你能直观看到每个集群的黄金信号。在 Kubernetes 里,Envoy 常作为 Ingress 或边车 与集群监控体系联动,是云原生可观测性的关键数据源。
七、Envoy vs Nginx vs Istio 数据面:怎么选
三者定位不同,常被放在一起比较。简单说:Nginx 是成熟稳定的经典反向代理;Envoy 是高性能、可编程、云原生原生的代理;Istio 是基于 Envoy 的服务网格控制平面,不是代理本体。
| 维度 | Nginx | Envoy | Istio(数据面=Envoy) |
| 定位 | 反向代理 / Web 服务器 | 通用 L4/L7 代理 | 服务网格控制平面 |
| 配置方式 | 静态文件为主 | xDS 动态优先 | 声明式 CRD 自动翻译 |
| 可观测性 | 需第三方模块 | 原生丰富指标 | 继承 Envoy 指标 |
| 上手成本 | 低 | 中 | 高 |
| 典型场景 | 静态站 / 简单反代 | 网关 / 边车 / 网格 | 多语言微服务治理 |
如果你的需求只是把流量转给一个后端,Nginx 反向代理 足够简单可靠;一旦要做细粒度流量治理、灰度发布或与 Kubernetes 深度集成,Envoy 才真正发挥价值。
八、生产落地检查清单
| 检查项 | 建议 |
| 配置管理 | 生产一律用 xDS 动态下发,避免静态配置漂移 |
| 健康检查 | 开启 active/outlier 健康检查,自动剔除异常端点 |
| 超时与重试 | 显式设置 connect/route/stream 超时,重试带退避 |
| TLS | 用 SDS 托管证书,启用双向 mTLS 保护东西向流量 |
| 限流 | 本地 token bucket 或外接 Ratelimit 服务做全局配额 |
| 可观测 | 开启 Prometheus stats 与结构化 access log |
| admin 端口 | 9901 仅绑内网,生产禁止公网暴露 |
| 熔断 | 配合 微服务治理 策略设置 outlier_detection |
九、常见误区与排障
- admin 端口暴露公网:9901 能执行热重启、改日志级别,务必只绑内网或加防火墙,可与 eBPF / Cilium 网络策略 配合做零信任隔离。
- 热更新配置失败:多半是 YAML 缩进或类型字段写错,先用
envoy --mode validate -c envoy.yaml校验。 - 路由匹配不到:确认 virtual_host 的 domains 是否覆盖请求 Host,通配用
["*"]但要小心优先级。 - 限流不生效:检查 rate limit 服务是否连得上,以及 descriptor 是否正确对应到过滤器配置。
- 503 突增:通常是上游端点被 outlier_detection 踢掉,先看 upstream_rq 指标与 EDS 端点健康状态。
十、结语
Envoy 把”网络治理”从应用代码里解放出来,用声明式、动态化、可观测的方式统一了流量层。无论是作为边缘网关、API 网关还是服务网格数据平面,它的学习曲线虽陡,但换来的是一整套可复用的云原生流量能力。建议从本文的静态配置例子起步,跑通后再接入 xDS 与控制平面,循序渐进地把代理层变成你基础设施里最稳的那一层。




