refused 不是 timeout

英文版:English

症状

外部连接数据库服务瞬间失败,报 connection refused。「瞬间」就是线索:refused 意味着包到了、没人在听,快速且确定。timeout 意味着有监听者但不应答。两个词指向栈的不同半边,混为一谈会浪费掉第一个小时。

逐跳走,停在第一个失败处

链路有八跳:client → DNS → 负载均衡 → NodePort → ingress → Service → Endpoints → pod。方法毫无花哨:按序核实每一跳确实在监听或解析,停在第一个失败的跳。在这类事故上,它找到过两个不同的根因:

  • **看起来配置了的监听者。**ingress controller 的 TCP services ConfigMap 存在且条目正确,但 controller 从未加载它。配置在,监听者不在。ingress 上游的一切当场无罪。

  • **变陈旧的标签。**更隐蔽:一次异常重启后,数据库 operator 没有刷新 pod 的就绪标签。Service 选择器要求那个标签,于是 Endpoints 是空的:Service 存在、pod 实际在服务,而流量永远到不了。控制面真相偏离了数据面真相,只有 Endpoints 这一跳暴露它。

修复与验证

第一种情况 reload controller;第二种重启工作负载,让 operator 重新评估标签。验证与诊断互为镜像:确认端口真的处于监听状态、Endpoints 非空。就是坏掉的那两件事,不是一个泛泛的健康检查。

先分类症状再上工具:refused 还是 timeout,然后逐跳。方法很无聊,所以它在凌晨三点也管用。