You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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';

验证步骤

  1. 重新部署资源:
kubectl apply -f statefulset.yaml
  1. 等待所有Mongo Pod启动,进入mongo-0验证副本集状态:
kubectl exec -it mongo-0 -- mongo admin -u admin -p password --eval 'rs.status()'
  1. 重启Node.js Pod,观察连接日志是否正常。

内容的提问来源于stack exchange,提问作者Sudharsan Srinivasan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 20:55:56