You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

手动搭建Docker+Envoy环境出现No healthy upstream错误求解

核心差异及问题根因

你遇到的503错误本质不是网络连通性问题(毕竟Envoy内部curl能正常访问服务端),而是Envoy的DNS解析策略和Docker网络特性的匹配问题,docker-compose部署和手动部署的核心差异有以下几点:

1. 网络默认配置差异

  • docker-compose会自动创建专用的自定义桥接网络,默认关闭IPv6分配,Docker内置DNS对该网络下的服务名只会返回IPv4的A记录,刚好匹配你Envoy默认只支持IPv4的配置
  • 手动执行docker network create创建的网络,Docker新版本默认会开启IPv6支持,内置DNS会同时返回server-stub的IPv4 A记录和IPv6 AAAA记录
    你Envoy配置中的cluster没有开启IPv6支持,解析到AAAA记录后无法建立连接,就会标记上游不健康返回503,而curl默认优先尝试IPv4,所以手动curl能正常访问。

2. 容器启动顺序的隐性差异

  • docker-compose默认按服务字典序启动容器,你的示例中server-stub镜像启动速度通常快于Envoy,Envoy启动后第一次DNS解析时server-stub已经完成DNS注册,能正常解析到地址
  • 手动部署如果按Envoy→服务端的顺序启动,Envoy的STRICT_DNS模式启动时第一次解析server-stub失败,未配置DNS刷新规则的情况下,旧版本Envoy不会主动刷新解析结果,会一直标记上游不健康。

3. 网络别名的自动配置差异

  • docker-compose会自动把服务名作为该服务所有容器的网络别名,无需额外配置
  • 手动部署如果只指定了--hostname而没有显式指定--network-alias server-stub,部分Docker版本可能只会在容器启动时注册一次DNS,更新不及时也可能导致解析异常。

适配手动部署的修复方案

你可以按以下步骤调整部署脚本:

  1. 创建网络时显式关闭IPv6:
docker network create --ipv6=false my-envoy-network
  1. 先启动服务端容器,再启动Envoy容器,两个容器都加入同一个网络,服务端显式设置网络别名:
# 启动服务端
docker run -d --name server-stub --network my-envoy-network --network-alias server-stub -p 5000:5000 你的服务端镜像名

# 启动Envoy
docker run -d --name envoy --network my-envoy-network -p 10000:10000 -p 9901:9901 -v $(pwd)/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy:v1.16-latest
  1. 也可以修改Envoy配置,给cluster添加DNS刷新配置和IPv4强制解析规则,避免启动顺序和IPv6的干扰:
clusters:
  - name: service
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: round_robin
    dns_refresh_rate: 1s # 每秒刷新DNS解析
    dns_lookup_family: V4_ONLY # 只解析IPv4,避免AAAA记录干扰
    # 保留原有load_assignment等配置不变

内容的提问来源于stack exchange,提问作者TalR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 04:24:03