高性能L4/L7代理,是众多网关与服务网格共用的数据平面
Envoy 是一个用 C++ 编写的高性能代理,在 Kubernetes 生态里的位置非常特殊:它通常不是给人直接用的产品,而是别人产品里的数据平面。
把这一点想清楚,很多困惑就消失了:
istio-proxy 就是 Envoy。projectcontour 命名空间里跑的那个 envoy Deployment 就是 Envoy。GatewayClass 与控制器。所以「在 k8s 上运维 Envoy」有两种截然不同的场景:
理解这四个概念,就能看懂 Envoy 的配置结构:
Listener 监听器,绑定 IP 与端口,负责接收连接
Filter Chain 过滤器链,在连接上挂载编解码、鉴权、限流等能力
Cluster 上游集群,一组逻辑相同的后端实例,定义负载均衡与连接池
Endpoint 集群里的具体实例地址
以及它的两套配置来源:
静态配置 写在 bootstrap 文件里,启动时加载,改动需重启
xDS 动态配置 由控制平面通过 gRPC 下发(LDS/RDS/CDS/EDS/SDS),热更新
xDS 是 Envoy 最关键的设计。控制平面可以不停机地推送新的监听器、路由、集群和证书,这正是 Istio 能做到「改一条 CRD 立刻生效」的原因。
如果目的是把 Envoy 当成 Kubernetes 的网关来用,现在的标准做法是 Envoy Gateway —— 它把 Envoy 包装成一个符合 Gateway API 的实现:
# 一条命令同时装 Gateway API CRD 与 Envoy Gateway 控制器
helm install eg oci://docker.io/envoyproxy/gateway-helm \
--version v1.9.1 -n envoy-gateway-system --create-namespace
# 等待控制器就绪
kubectl wait --timeout=5m -n envoy-gateway-system \
deployment/envoy-gateway --for=condition=Available
# 应用官方示例:GatewayClass、Gateway、HTTPRoute 与示例应用
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.9.1/quickstart.yaml -n default
# 查看控制器自动创建的 Envoy 代理与地址
kubectl get gatewayclass
kubectl get pods -n envoy-gateway-system
kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}'
Envoy Gateway 会自动根据 Gateway 资源拉起一批 Envoy 代理 Pod,你只操作 Gateway API 资源,不直接写 Envoy 配置。
自己跑一个 Envoy,用 ConfigMap 挂载 bootstrap 配置:
apiVersion: v1
kind: ConfigMap
metadata:
name: envoy-bootstrap
namespace: default
data:
envoy.yaml: |
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
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: web
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: web
type: STRICT_DNS
load_assignment:
cluster_name: web
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: web-svc
port_value: 80
admin:
address:
socket_address:
address: 127.0.0.1
port_value: 9901
注意 admin 绑定在 127.0.0.1,这是有意的:管理接口能读取全部配置、还能改日志级别,绝不能暴露到集群外。
配套的 Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: envoy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: envoy
template:
metadata:
labels:
app: envoy
spec:
containers:
- name: envoy
image: envoyproxy/envoy:v1.31-latest
args: ["-c", "/etc/envoy/envoy.yaml", "--log-level", "info"]
ports:
- containerPort: 10000
name: http
readinessProbe:
httpGet:
path: /ready
port: 9901
volumeMounts:
- name: bootstrap
mountPath: /etc/envoy
volumes:
- name: bootstrap
configMap:
name: envoy-bootstrap
Envoy 自带 --mode validate,可以在不启动的情况下检查配置是否合法:
# 本地校验配置文件
envoy --mode validate -c envoy.yaml
# 容器里校验
kubectl exec -it deploy/envoy -- envoy --mode validate -c /etc/envoy/envoy.yaml
管理接口(admin)是 Envoy 排障的核心工具:
# 转发管理端口到本地
kubectl port-forward deploy/envoy 9901:9901
# 查看完整配置(静态与动态合并后的最终结果)
curl -s localhost:9901/config_dump | jq '.configs | length'
# 查看所有集群
curl -s localhost:9901/clusters
# 查看所有监听器
curl -s localhost:9901/listeners
# 查看统计指标
curl -s localhost:9901/stats | grep upstream_rq
# 只看关键指标
curl -s localhost:9901/stats?filter=upstream_rq_5xx
# 就绪状态
curl -s localhost:9901/ready
# 版本与运行信息
curl -s localhost:9901/server_info
# 临时改日志级别
curl -X POST "localhost:9901/logging?level=debug"
# 优雅排空连接,摘流量时用
curl -X POST localhost:9901/healthcheck/fail
Envoy Gateway 托管的代理,管理端口是 19000:
kubectl port-forward -n envoy-gateway-system pod/<envoy-pod> 19000:19000
curl -s localhost:19000/config_dump | head
# Prometheus 指标(需要配置 stats listener)
curl -s localhost:9901/stats/prometheus | head
# 打开访问日志需要显式配置
access_log:
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
admin 端口绝不能暴露到集群外。管理接口可以读取全部配置(含证书)、修改日志级别、主动让实例退出健康检查,等于把整个服务交给任何能访问它的人。默认绑定 127.0.0.1 是刻意为之,不要为了「方便调试」改成 0.0.0.0 或加公网 Service。--mode validate 只能检查语法与结构,不做连通性验证。它能发现字段拼写错误、类型不匹配,但后端地址写错、证书路径不存在这类问题只有真正启动才会暴露,所以 Deployment 里要配 readinessProbe 打到 /ready。/healthcheck/fail 是排空流量的开关,不是关机。调用后实例会主动让负载均衡把流量摘走,但进程仍在运行。节点维护前先调它、等待连接数归零,比直接 kubectl delete pod 平滑得多。config_dump 的输出可能非常大。集群里服务多时动辄几十万行,务必配合 jq 或 --filter 使用,直接输出到终端容易把会话卡死。kubectl — Kubernetes集群管理工具istio — 用Envoy作为数据平面的服务网格contour — 基于Envoy的Ingress Controlleremissary — 基于Envoy的API网关higress — 基于Envoy与Istio的云原生网关gateway-api — Envoy Gateway实现的路由API标准