GKE跨VPC集群访问NodePort服务源IP不稳定故障求助
根因说明
Kubernetes 1.16及之后版本调整了kube-proxy的默认SNAT策略:对于目标地址属于集群内网、VPC内网或Peering VPC内网段的流量,默认不做SNAT保留源Pod IP;对于公网地址才会SNAT为节点IP。你升级Cluster-A到1.18后命中了这个策略变更:
- Cluster-B的节点IP属于Peering VPC的内网段,请求保留源Pod IP,而Cluster-B的VPC没有到Cluster-A Pod段的回程路由,导致包无法返回,请求超时
- Cluster-C的节点IP刚好未被kube-proxy识别为内网段,请求被SNAT为节点IP,节点IP在Peering路由表中存在,因此访问正常
排查思路
- 对比Cluster-B和Cluster-C的节点IP所属网段,核对Cluster-A上kube-proxy配置的
clusterCIDR以及本地路由规则的覆盖范围,确认访问Cluster-B的目标IP是否被kube-proxy判定为「不需要SNAT」的内网段,访问Cluster-C的目标IP被判定为「需要SNAT」的公网/未知网段 - 登录Cluster-A的工作节点,执行
iptables -t nat -L POSTROUTING -n -v,比对访问Cluster-B节点IP和Cluster-C节点IP时的规则匹配情况,确认前者未命中SNAT规则、后者命中了MASQUERADE规则 - 登录Cluster-B所在VPC的路由表,检查是否存在指向Cluster-A与Cluster-B之间VPC Peering连接的、目标为Cluster-A Pod CIDR的路由条目,确认回程流量能否回到Cluster-A的节点
- 核对Cluster-B的防火墙规则,确认Cluster-A的Pod CIDR确实被放通了31000端口的入站访问,排除规则配置错误(比如端口写错、协议写错、网段写错)
解决方案
方案一:补充回程路由(推荐,保留源IP便于审计)
在Cluster-B所在VPC的路由表中添加静态路由:
- 目标网段:填写Cluster-A的Pod CIDR段
- 下一跳:选择Cluster-A与Cluster-B之间的VPC Peering连接
验证方式:在Cluster-B的节点上ping Cluster-A的Pod IP,能通则配置生效,此时Cluster-A的Pod访问serviceb的请求就可以正常收到回程包
方案二:强制Cluster-A对外访问时均SNAT为节点IP
修改Cluster-A的kube-proxy配置,开启masqueradeAll参数:
- 执行
kubectl edit cm kube-proxy -n kube-system - 在
config.conf下添加masqueradeAll: true配置 - 重启所有kube-proxy Pod:
kubectl rollout restart daemonset kube-proxy -n kube-system
验证方式:在Cluster-A的测试Pod内再次curl myserviceb.x.com:31000,同时在节点抓包确认源IP已经变成节点内网IP,访问正常即可
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

