Envoy 无法连接控制平面的常见原因是网络或配置不匹配:需确认DNS可解析、端口可达,bootstrap中cluster地址不能写localhost,自建control plane须监听0.0.0.0,Istio需检查istiod xDS服务是否启用,且iptables规则必须生效。

Envoy 作为 sidecar 启动时无法连接到控制平面(xDS)
常见现象是 envoy 日志里反复出现 gRPC config stream closed: 14, no healthy upstream 或 Unable to establish new stream。本质不是 Envoy 配置错,而是它根本连不上 Pilot/Control Plane(比如 Istio 的 istiod 或自建的 go-control-plane)。
- 确认控制平面服务 DNS 可解析且端口可达:从 sidecar 容器内执行
telnet istiod.istio-system.svc.cluster.local 15012(xDS gRPC 端口) - Envoy 的
bootstrap.yaml中static_resources.clusters[0].hosts[0].socket_address.address必须指向控制平面 Service 的 ClusterIP + 端口,不能写 localhost 或 127.0.0.1 - 若用自建 control plane(如
go-control-plane),确保其监听地址绑定了0.0.0.0:18000而非127.0.0.1:18000,否则 Pod 内部无法访问 - Istio 场景下,检查
istiod是否启用了 SDS 和 EDS:默认开启,但若手动关闭了--set values.pilot.envoyAccessLogService.enabled=false等参数,可能间接影响 xDS 健康检查逻辑
Go 微服务容器中注入 Envoy sidecar 后 HTTP 请求超时或 503
不是 Envoy 没启动,而是流量路由没对上——典型是 Go 服务监听 localhost:8080,而 Envoy 默认只劫持 127.0.0.1:8080 流量,但容器内 localhost 解析行为不一致,导致部分请求绕过 Envoy。
- Go 服务必须绑定
0.0.0.0:8080,而非localhost:8080或127.0.0.1:8080;Envoy 的original_dst过滤器依赖实际目标 IP,绑定 localhost 会导致原始目标被替换为 127.0.0.1,破坏透明代理逻辑 - 检查 iptables 规则是否生效:在 Pod 内运行
iptables -t nat -L OUTPUT -n,确认有类似REDIRECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 redir ports 15001的规则(Istio 默认用 15001 拦截入站,15006 出站) - 若用 manual injection(非 istioctl auto-inject),需确认
initContainer已成功运行并完成 iptables 设置;常见失败原因是 init container 权限不足(缺少NET_ADMINcapability)
Envoy 配置中 cluster 与 Go 服务 endpoint 不匹配导致 503 No healthy upstream
Envoy 的 cluster 定义和实际 Go 服务的 endpoint(host:port)必须严格一致,尤其在非 Kubernetes 环境下容易出错。错误配置会让 Envoy 认为所有 upstream 都不健康。
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- Cluster 的
hosts字段必须指向 Go 服务真实监听地址:K8s 场景下通常是service-name.namespace.svc.cluster.local:8080;裸机或 Docker Compose 下则是host.docker.internal:8080或具体宿主机 IP - 健康检查配置(
health_checks)必须能访问 Go 服务的 readiness path(如/healthz),且 Go 服务需返回 HTTP 200;若 Go 服务未暴露该 endpoint 或监听地址不对,Envoy 会持续标记 upstream unhealthy - 注意 DNS 解析时机:Envoy 启动时解析一次 DNS,若后端服务 IP 变更(如 K8s Pod 重建),需启用
dns_refresh_rate或改用STRICT_DNS+lb_policy: ROUND_ROBIN配合主动健康检查
Go 服务日志中看不到真实客户端 IP,全是 127.0.0.6
这是 Envoy 默认使用 127.0.0.6 作为“假源 IP”注入到上游请求头中的行为,目的是让 Go 服务知道请求来自 Envoy。但如果你需要原始 client IP,不能靠 X-Forwarded-For 简单取第一个值——Envoy 默认不透传,也不验证 header。
立即学习“go语言免费学习笔记(深入)”;
- 在 Envoy
http_filters中启用envoy.filters.http.ext_authz或直接配置envoy.filters.http.router的use_remote_address为 true,并设置xff_num_trusted_hops: 1 - Go 服务中读取
X-Forwarded-For时,必须结合X-Envoy-External-Address(Envoy 自动添加)或信任的 proxy IP 列表做校验,否则存在伪造风险 - 若用 Istio,更推荐在
DestinationRule或PeerAuthentication中统一配置 mTLS 和 header 透传策略,避免在每个 Envoy bootstrap 里硬编码
Envoy 作为全托管 mesh proxy 的难点不在 YAML 写法,而在网络层可见性缺失——你永远得同时盯着三处:Go 进程监听地址、iptables 规则生效状态、Envoy xDS 配置最终落地结果。任何一层没对齐,表现都是“请求不通”,但原因可能隔了两层抽象。

















