先说我这次遇到的事:线上服务跑在 Docker 容器里,需要 HTTPS 调外部平台的接口,某天一上班监控就开始报警。进容器里用 curl 复现,请求卡在 TLS handshake timeout,重试多少次都一样。诡异的是,宿主机上直接 curl 同一个地址完全正常,容器里 ping 外网也通,DNS 解析也快,甚至有些 HTTP 请求还能通。当时第一反应是防火墙、证书、环境变量哪一环出了问题,结果折腾一圈全不是,最后把目光放到链路 MTU 上,半小时定位,十分钟修完。这个坑在 Linux 服务器、开发机 Docker Desktop、甚至 Kubernetes 集群里都反复出现过,症状高度相似:TCP 建连成功,但 TLS 握手永远完不成。这篇文章就把完整的定位过程和修复思路写清楚,遇到过同类问题的人可以直接照着排查,没遇到过的也建议存一份,因为这类问题一旦发生,光靠直觉很难找。
1. 事故现场:容器里 HTTPS 集体超时,宿主机却一切正常
1.1 先看一眼现象再下结论
事故最典型的呈现方式是这样的:容器里的应用开始疯狂重试外部接口调用,日志里要么是connection timed out,要么是底层 HTTP 客户端报TLS handshake timeout。手动进容器验证时,命令大概是这样的:
docker exec -it <container> curl -v --connect-timeout 5 --max-time 10 https://api.github.com输出一开始还正常,DNS 解析秒回,TCP 连接也建立了,然后停在:
* connect to api.github.com port 443 succeeded * TLS handshake timeoutcurl