consul connect 的 mtls 默认开启但仅作用于控制平面,服务间加密通信必须在服务注册中显式配置 connect 块;python 应用应通过 localhost:21000 经 envoy sidecar 透明代理调用,而非直连或手动处理 tls。

Consul Connect 的 mTLS 默认就开启,但服务注册时没配 connect 块就等于白搭
Consul 1.9+ 默认启用全局 mTLS,但这个“启用”只管控制平面(agent 之间通信),不影响服务间流量。真正让两个服务走 mTLS 加密通信,得在服务注册里显式声明 connect 配置。否则即使 Consul agent 开着 TLS,curl http://service:8080 还是明文直连——你看到的健康检查通过、服务注册成功,跟实际连接是否加密完全无关。
常见错误现象:consul catalog services 能查到服务,consul connect envoy -service=myapp 启得起来,但下游调用报 503 no healthy upstream 或 Envoy 日志里反复出现 upstream connect error or disconnect/reset before headers。
- 必须在服务注册 JSON/YAML 里加
connect字段,哪怕只是空对象:{"connect": {"sidecar_service": {}}} - 如果用了 sidecar 模式,
sidecar_service下还要配proxy,否则 Envoy 不知道监听哪个端口、上游是谁 - 不配
connect,Consul 根本不会为该服务生成证书、下发配置,mTLS 流量路径从第一步就断了
Python 应用怎么接上 Consul Connect 的 mTLS?别碰证书文件,用 localhost:21000 走本地 proxy 就行
Python 应用本身不需要加载 consul-agent-ca.pem 或配置 TLS 上下文。Connect 的设计哲学是“透明代理”:Envoy sidecar 在本地监听 127.0.0.1:21000(默认 upstream 端口),所有出向请求发给它,由它完成证书签发、mTLS 握手、服务发现和负载均衡。你的 Python 代码照常发 HTTP 请求,目标地址改成 http://localhost:21000 即可。
使用场景:Django/Flask/FastAPI 服务作为上游调用另一个 Connect 服务;或 Python 脚本做定时任务,需要安全调用内部 API。
立即学习“Python免费学习笔记(深入)”;
- 不要用
requests.get("https://svc-name.service.consul")—— DNS 解析会绕过 Envoy,且没证书信任链 - 正确写法:
requests.get("http://localhost:21000", headers={"Host": "svc-name.service.consul"}),靠Host头触发 Envoy 路由 - 如果下游服务监听 HTTPS(比如用
https://backend:443),Envoy 默认会降级成 HTTP 转发;如需保持上游 HTTPS,得在proxy.config里设protocol = "https" - Python 的
urllib3默认复用连接,而 Envoy 的 HTTP/2 连接管理可能引发ConnectionResetError,建议加requests.adapters.HTTPAdapter(pool_connections=10, pool_maxsize=10)
consul connect envoy 启动失败?重点盯 upstream 配置里的服务名和命名空间
启动命令返回 failed to generate bootstrap config: unknown service 或日志里反复刷 no endpoints found for service,八成是 upstream 配置写错了。Consul Connect 对服务名大小写、命名空间、分区极其敏感,且不报语法错,只静默失败。
参数差异:service 字段必须和 consul catalog services 输出的名称**完全一致**(包括破折号、下划线);namespace 默认是 default,但如果你启用了 Namespaces,漏写或写错就会找不到服务。
- 查真实服务名:
consul catalog services -ns=my-ns,注意输出里带命名空间前缀的完整名 -
upstream示例必须长这样:{"destination_type": "service", "destination_name": "api-gateway", "local_bind_port": 8080, "datacenter": "dc1", "namespace": "my-ns"} - 如果目标服务在另一个分区(Partition),还得加
"partition": "test",缺了就查不到实例 - Envoy 启动后,用
curl http://localhost:19000/config_dump看cluster列表里有没有对应 upstream,没有就是配置没生效
Python 日志里出现 ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED]?说明你误走了 HTTPS 直连
这个错误不是证书过期或 CA 不对,而是 Python 客户端试图直接跟远端服务做 TLS 握手,但对方(比如 Envoy sidecar)根本没开 HTTPS 监听,或者你连的是纯 HTTP 的 upstream 端口。Consul Connect 的 mTLS 是双向的、发生在 Envoy 层,应用层走 HTTP + localhost proxy 才是正路。
性能影响:强行在 Python 里做 TLS(比如用 certifi 和自签名 CA)不仅多此一举,还会让连接无法复用、增加握手延迟,而且绕过 Envoy 后,熔断、重试、指标采集全失效。
- 删掉所有类似
verify="/var/lib/consul/tls/ca.pem"的 requests 参数 - 确认你调用的目标 URL 是
http://localhost:21000,不是https://...或http://svc-name.service.consul - 如果必须用 HTTPS(比如对接外部系统),应该在 Consul 的
proxy.upstreams里配protocol = "https",让 Envoy 去处理 TLS,Python 仍走 HTTP - Envoy 默认只监听 localhost,如果 Python 在容器里跑,确保
network_mode: "host"或用host.docker.internal(Mac/Win)替代localhost
最易被忽略的点:Consul 的 mTLS 是“服务网格层”的事,不是“应用 TLS 配置”的事。一旦开始手动管理证书、改 Python 的 SSL 上下文,方向就反了。










