Kubernetes Pod内应用无法发起外部API调用请求超时如何排查
首先要明确:K8s集群里Pod访问外部地址的源IP,默认既不是Pod自身IP,也不是Service的ClusterIP——这俩都是集群内部的虚拟地址,流量出集群的时候会做SNAT转换,外部服务看到的源IP完全取决于集群的网络部署模式,这也是加了所谓“集群IP”白名单仍然超时的核心原因。
第一步:先拿到真实的出网源IP
在业务所在的命名空间起一个临时调试容器,直接请求能回显请求源IP的服务,拿到外部接口侧实际收到的源地址:kubectl run -it --rm net-debug --image=curlimages/curl --restart=Never -- curl ifconfig.me如果集群没有配置统一出口网关,用的是默认网络插件规则,这里返回的IP就是Pod所在节点的物理网卡IP,也就是执行
kubectl get nodes -o wide输出的节点IP,这部分地址是必须加入白名单的。第二步:核对现有白名单是否有效
之前加的“集群IP”如果是Pod CIDR网段、Service ClusterIP网段,这类地址根本不会出现在集群外的请求里,加了完全不生效。如果集群是通过NAT网关、弹性公网池、专线代理统一出网的,那外部看到的源IP是出口网关的地址,不是节点IP,这种场景要把出口的IP段全部加白,反而不需要单独加节点IP。第三步:补全节点白名单避坑
要是确认用节点IP出网,执行kubectl get nodes -o wide提取IP的时候别漏两类情况:- 别加错网卡IP:走公网调接口就加节点的公网出口IP,走内网专线调就加节点对应内网网卡的IP,不要把其他虚拟网卡的IP加进去
- 别漏覆盖节点:所有可调度的节点都要覆盖,包括打了可调度污点的master节点、边缘节点,只要是能运行业务Pod的节点IP都要加;如果集群开了节点自动扩缩容,最好把节点池的IP段提前加白,避免新节点启动后上面的Pod请求被拦截。
第四步:连通性校验
白名单更新完,先在调试容器里请求www.example.com/api测通,再到业务Pod里验证。要是还是超时,就在承载业务Pod的节点上抓包看链路:# 把eth0换成节点实际的物理网卡名,端口换成接口实际使用的端口 tcpdump -i eth0 host www.example.com and port 443如果抓包只能看到发出去的SYN请求包,收不到对端回的SYN+ACK包,说明链路还是被拦截,优先核对白名单、中间防火墙/安全组规则;如果能正常收到响应包,就去排查业务侧的DNS解析、超时时间配置、请求格式是否存在问题。
长期优化建议
如果集群节点多、扩缩容频繁,每次新增节点更一次白名单运维成本很高,可以部署Egress网关做统一出网,所有访问外部服务的流量都走固定出口IP,只需要把网关IP加白即可,不用跟着节点变动更新白名单。
内容的提问来源于stack exchange,提问作者Jae

