Kubernetes集群中NATS Streaming连接报ECONNREFUSED跨服务异常排查
问题根因排查
从你贴的报错就能看出来,NATS服务的域名解析是完全正常的——已经成功解析到nats-srv对应的ClusterIP 10.105.230.126,出现的连接拒绝属于TCP传输层的链路故障,和你写的连接代码本身没有关系。毕竟相同代码在其他服务可以正常连通,故障点只存在于当前运行publisher的Pod、集群网络规则、NATS服务三者的传输链路上,常见的诱因有以下几种:
- NetworkPolicy规则不匹配(最高发)
集群里部署NATS的时候,通常会配套配置入站网络规则,只允许打了特定标签(比如access-nats: "true")的Pod访问4222端口。之前能正常连接的服务,它的Pod刚好匹配了这个规则的标签条件,流量可以正常放行;但当前运行publisher的Pod没有打对应标签,流量在到达NATS后端Pod之前就被Netfilter规则拦截,直接返回TCP RST包,触发ECONNREFUSED报错。
如果集群配置了跨命名空间的网络隔离规则,还会出现“同命名空间的其他服务能连NATS、跨空间的当前服务连不上”的错位情况。 - 节点层面的Kube-proxy规则同步延迟
nats-srv的ClusterIP是固定的,但后端实际承载服务的Pod如果出现滚动更新、健康检查状态变化,Kube-proxy下发的流量转发规则不会瞬间在所有节点同步完成。能正常连接的服务刚好调度在规则已经同步的节点上,当前publisher所在的节点还没拿到最新的后端Pod转发地址,流量发到节点后找不到对应的后端服务,就会直接返回连接拒绝。 - 当前服务自身的出站网络限制
不少团队会给每个微服务单独配置出站NetworkPolicy,限定这个服务只能访问固定的依赖端口。如果当前publisher的出站规则里,没有放通到NATS服务4222端口的流量权限,哪怕其他同类服务的出站规则是全通的,当前服务也会出现连接被拒的问题。
对应排查步骤
- 在当前出问题的Pod内部执行
nc -vz nats-srv 4222,确认TCP层的连通性状态 - 检查当前Pod、NATS服务关联的所有NetworkPolicy规则,核对标签匹配条件有没有遗漏
- 执行
kubectl get endpoints nats-srv,确认后端Endpoint里的Pod地址都是处于就绪状态的,没有未就绪的无效地址 - 核对当前publisher的Pod和NATS服务是不是处于同一个命名空间,避免短域名解析巧合连接到同命名空间下的其他同名服务
内容的提问来源于stack exchange,提问作者Süleyman Ali Akpınar
相关产品推荐
相关产品推荐

