Kubernetes ExternalName服务无法通过mongodb+srv连接MongoDB Atlas
问题场景
你用ExternalName Service映射MongoDB Atlas地址,配置如下:
# mongodb accounting kind: Service apiVersion: v1 metadata: name: mongodb-accounting namespace: kasirmudah spec: type: ExternalName externalName: accounting.xxxxx.mongodb.net
原地址mongodb+srv://accounting.xxxxx.mongodb.net可正常连接,但用集群内域名mongodb-accounting.kasirmudah.svc.cluster.local通过mongodb+srv连接时抛出错误:
root@nginx-from-dev-6fb76d7868-fnqmv:/# mongosh "mongodb+srv://mongodb-accounting.kasirmudah.svc.cluster.local" Current Mongosh Log ID: 6481c0914bfb085aeb92a7d4 Connecting to: mongodb+srv://mongodb-accounting.kasirmudah.svc.cluster.local/?appName=mongosh+1.9.1 Error: querySrv ENOTFOUND _mongodb._tcp.mongodb-accounting.kasirmudah.svc.cluster.local
该ExternalName映射普通网页地址时curl可正常访问,想知道这种SRV连接场景能否实现。
核心原因
Kubernetes的ExternalName Service仅负责A/AAAA记录的别名映射,不会同步原域名的SRV记录。而mongodb+srv://协议的工作流程是先查询目标域名的_mongodb._tcp.xxx SRV记录,获取副本集节点信息后再建立连接。集群内DNS找不到对应SRV记录,自然会报错。
可行解决方案
1. 直接使用原SRV地址(推荐)
无需绕ExternalName,直接在应用配置里写mongodb+srv://accounting.xxxxx.mongodb.net,只要集群节点能访问公网MongoDB Atlas,就能正常连接。如果不想硬编码,可把地址存入ConfigMap或Secret,让应用读取这类配置资源。
2. 自定义CoreDNS SRV记录重写
如果必须使用集群内域名,可修改CoreDNS的配置,添加SRV记录重写规则:
- 编辑CoreDNS的ConfigMap:
kubectl edit configmap coredns -n kube-system - 在对应区域块中新增重写规则,比如针对
kasirmudah命名空间:kasirmudah.svc.cluster.local:53 { forward . 8.8.8.8 rewrite name _mongodb._tcp.mongodb-accounting.kasirmudah.svc.cluster.local _mongodb._tcp.accounting.xxxxx.mongodb.net } - 重启CoreDNS Pod让配置生效:
这样集群内查询该SRV记录时,会被重写为原Atlas域名的SRV查询,就能正确解析副本集节点。kubectl rollout restart deployment coredns -n kube-system
3. 手动维护Headless Service + Endpoints(不推荐)
先手动解析原Atlas域名的SRV记录,得到所有副本集节点的地址和端口,然后创建Headless Service和对应的Endpoints:
# Headless Service kind: Service apiVersion: v1 metadata: name: mongodb-accounting namespace: kasirmudah spec: type: ClusterIP clusterIP: None ports: - port: 27017 name: mongodb
# Endpoints kind: Endpoints apiVersion: v1 metadata: name: mongodb-accounting namespace: kasirmudah subsets: - addresses: - ip: "xxx.xxx.xxx.xxx" # 副本集节点IP - ip: "yyy.yyy.yyy.yyy" ports: - port: 27017 name: mongodb
但这种方式的问题是,MongoDB Atlas的节点地址可能动态变更,一旦节点调整,你需要手动更新Endpoints,维护成本很高,仅适合临时测试场景。
内容的提问来源于stack exchange,提问作者Alkaaf

