GCP环境下Kubernetes集群连接外部VM数据库超时问题排查
让我们一步步拆解你的问题,核心问题大概率出在防火墙规则上,另外也可以验证几个配置细节来确认:
问题排查与解决方案
1. 最直接的原因:VM网络标签的防火墙限制
你的数据库VM只配置了http-server和https-server这两个网络标签——这两个标签对应的默认规则通常只放行80(HTTP)和443(HTTPS)端口的入站流量,而你的MongoDB用的是27017端口,完全不在允许范围内。这几乎是连接超时的核心原因。
解决方法:
- 给VM新增一个自定义网络标签(比如
mongodb-server),然后创建对应的防火墙规则,允许K8s集群节点的IP段(或整个集群的Pod CIDR范围)访问VM的27017端口。 - 如果你只是临时测试,也可以直接修改现有规则,把27017端口加入允许的入站端口列表(但生产环境更推荐用标签隔离规则)。
2. 验证Service和Endpoints的配置正确性
你的配置逻辑是对的(手动创建Endpoints绑定无selector的Service,用于外部服务发现),但需要确认几个细节:
- 替换
<internal-ip>的VM内部IP是否完全正确?可以在VM上执行hostname -I或ip addr确认,避免拼写错误。 - Service和Endpoints的
name和namespace必须完全匹配(你的配置里都是db-service和production,这点没问题,但可以用命令验证状态:
确保Endpoints的输出里显示了你配置的IP,且端口是27017。kubectl get service db-service -n production kubectl get endpoints db-service -n production
3. 测试集群内到VM的连通性
为了定位到底是网络问题还是配置问题,你可以在集群内的Pod里直接测试连接:
- 临时启动一个busybox Pod用于测试:
kubectl run -it --rm busybox --image=busybox:1.35 --namespace=production - 在Pod内用telnet或nc命令测试端口连通性:
telnet <internal-ip> 27017 # 或者用nc更直观 nc -zv <internal-ip> 27017
如果连接失败,说明是VM端的防火墙或网络路由问题;如果能成功连接,再检查你的应用程序是否正确使用了db-service.production.svc.cluster.local:27017这个K8s服务域名。
4. 其他潜在排查点
- MongoDB监听地址:确认MongoDB配置文件中的
bindIp参数是0.0.0.0(允许所有IP访问),而不是127.0.0.1(仅本地访问)。你用netstat确认了监听27017,但要注意监听的地址:
输出应该包含netstat -plnt | grep 270170.0.0.0:27017或:::27017,而不是仅127.0.0.1:27017。 - K8s网络策略:如果你的集群启用了NetworkPolicy,检查是否有策略阻止了Pod访问外部IP。可以临时禁用相关策略测试,或者添加允许Pod访问27017端口的规则。
内容的提问来源于stack exchange,提问作者user2779450




