Kubernetes中从其他Pod(Node.js)连接Mongo StatefulSet失败排查
解决MongoDB StatefulSet连接失败问题
错误信息
MongooseServerSelectionError: getaddrinfo ENOTFOUND mongo-0.mongo-svc.default.svc.cluster.local
MongooseServerSelectionError: Server selection timed out after 30000 ms
核心问题与修复方案
1. 修正无头服务配置
StatefulSet需要**无头服务(Headless Service)**才能生成每个Pod的稳定DNS记录,当前Service是普通ClusterIP类型,缺少clusterIP: None配置,导致无法解析Pod级域名。
修改后的Service YAML:
--- apiVersion: v1 kind: Service metadata: name: mongo-svc labels: app: mongo spec: clusterIP: None # 声明为无头服务,必须添加 ports: - port: 27017 targetPort: 27017 selector: app: mongo
2. 初始化MongoDB副本集
当前Mongo实例是单机模式,但连接字符串指定了replicaSet=rs0,驱动无法识别副本集。需要修改容器启动命令,添加副本集初始化逻辑:
更新后的StatefulSet YAML:
apiVersion: apps/v1 kind: StatefulSet metadata: name: mongo spec: serviceName: mongo-svc replicas: 3 selector: matchLabels: app: mongo template: metadata: labels: app: mongo spec: containers: - name: mongo image: mongo command: ["mongod", "--replSet", "rs0", "--bind_ip_all"] # 启动时指定副本集名称 ports: - containerPort: 27017 volumeMounts: - name: mongo-data mountPath: /data/db env: - name: MONGO_INITDB_ROOT_USERNAME value: "admin" - name: MONGO_INITDB_ROOT_PASSWORD value: "password" - name: MONGO_INITDB_DATABASE value: "skippy" lifecycle: postStart: exec: command: - /bin/sh - -c - > if [ ! -f /data/db/replica-init.lock ]; then sleep 10; touch /data/db/replica-init.lock if [ "$HOSTNAME" = "mongo-0" ]; then # 初始化副本集,加入所有节点 mongo admin -u admin -p password --eval ' rs.initiate({ _id: "rs0", members: [ { _id: 0, host: "mongo-0.mongo-svc.default.svc.cluster.local:27017" }, { _id: 1, host: "mongo-1.mongo-svc.default.svc.cluster.local:27017" }, { _id: 2, host: "mongo-2.mongo-svc.default.svc.cluster.local:27017" } ] }); '; fi; fi; volumeClaimTemplates: - metadata: name: mongo-data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi
3. 修正MongoDB连接字符串
- 参数分隔符错误:用
&代替逗号分隔参数 - 副本集模式下,列出所有Pod域名或使用无头服务域名,避免单点依赖
- 去掉
directConnection=true,副本集模式下驱动会自动发现节点 - 添加
authSource=admin指定认证数据库
修正后的连接字符串:
const uri = `mongodb://${username}:${password}@mongo-0.mongo-svc.default.svc.cluster.local:27017,mongo-1.mongo-svc.default.svc.cluster.local:27017,mongo-2.mongo-svc.default.svc.cluster.local:27017/${database}?replicaSet=${replicaSetName}&authSource=admin`;
4. 修正Node.js代码冗余错误
代码中clusterServiceName变量值错误,修正为实际服务名:
const clusterServiceName = 'mongo-svc';
验证步骤
- 重新部署资源:
kubectl apply -f statefulset.yaml
- 等待所有Mongo Pod启动,进入
mongo-0验证副本集状态:
kubectl exec -it mongo-0 -- mongo admin -u admin -p password --eval 'rs.status()'
- 重启Node.js Pod,观察连接日志是否正常。
内容的提问来源于stack exchange,提问作者Sudharsan Srinivasan
相关产品推荐
相关产品推荐

