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

Kubernetes中MongoDB集群无法通过集群域名连接问题排查

问题描述

使用以下Terraform配置创建单节点MongoDB StatefulSet及对应Service后,无法通过集群内部域名或外部CLI连接MongoDB:

  • 进入Pod内部用localhost:27017可正常连接
  • 同Pod内用集群域名mongodb.default.svc.cluster.local:27017连接时提示连接拒绝
  • MongoDB日志显示已绑定0.0.0.0

附带配置代码:

locals {
  labels = {
    "app" = "mongo"
  }
  volume_config_name = "mongo-config"
}

module "mongo" {
  source  = "terraform-iaac/stateful-set/kubernetes"
  version = "1.4.2"
  image     = "mongo:4.4"
  name      = "mongodb"
  namespace = kubernetes_namespace.cmprimg.metadata[0].name

  custom_labels = local.labels

  volume_host_path = [
    {
      volume_name  = "data"
      path_on_node = "/data/db"
    },
  ]
  volume_mount = [
    {
      mount_path  = "/data/db"
      volume_name = "data"
    },
    {
      mount_path  = "/etc/mongod.conf.orig"
      volume_name = "mongodb-conf"
      sub_path    = "configfile" // Key from configmap
    }
  ]

  volume_config_map = [{
    mode        = "0777"
    volume_name = "mongodb-conf"
    name        = "mongodb-confmap"
  }]

  # volume_claim = [
  #   {
  #     name                   = "mongo"
  #     namespace              = kubernetes_namespace.cmprimg.metadata[0].name
  #     access_modes           = ["ReadWriteOnce"]
  #     requests_storage       = "4Gi"
  #     persistent_volume_name = "mongo"
  #     storage_class_name     = "linode-block-storage-retain"
  #   }
  # ]
  env = {
    "MONGO_INITDB_ROOT_USERNAME" = var.username,
    "MONGO_INITDB_ROOT_PASSWORD" = var.password,
  }
  command = [
    "mongod",
    "--bind_ip",
    "0.0.0.0",
  ]

  internal_port = [
    {
      name          = "mongo"
      internal_port = 27017
    }
  ]

  resources = {
    request_cpu    = "100m"
    request_memory = "800Mi"
    limit_cpu      = "120m"
    limit_memory   = "900Mi"
  }

  replicas = 1
}

module "mongo_service" {
  source  = "terraform-iaac/service/kubernetes"
  version = "1.0.4"

  app_name      = module.mongo.name
  app_namespace = kubernetes_namespace.cmprimg.metadata[0].name
  port_mapping = [
    {
      name          = "mongo"
      internal_port = 27107
      external_port = 27017
    }
  ]

  custom_labels = local.labels
}

resource "kubernetes_persistent_volume_claim" "example" {
  metadata {
    name      = "mongo"
    namespace = kubernetes_namespace.cmprimg.metadata[0].name
    labels    = local.labels
  }

  spec {
    access_modes = ["ReadWriteOnce"]
    resources {
      requests = {
        storage = "20Gi"
      }
    }
    storage_class_name = "linode-block-storage-retain"
  }
}

resource "kubernetes_config_map" "mongodb_conf" {
  metadata {
    name      = "mongodb-confmap"
    namespace = kubernetes_namespace.cmprimg.metadata[0].name
    labels    = local.labels
  }

  data = {
    "configfile" = yamlencode({
      storage : {
        dbPath : "/data/db",
      },
      net : {
        port : 27017,
        bindIp : "0.0.0.0",
      }
    })
  }
}
问题分析与修复方案

1. Service端口映射错误(核心问题)

你的mongo_service模块中,port_mapping的internal_port写成了27107,但MongoDB实际监听的是27017,导致Service转发到了错误的端口,直接引发连接拒绝。

修复:将internal_port改为27017:

port_mapping = [
  {
    name          = "mongo"
    internal_port = 27017
    external_port = 27017
  }
]

2. Service与Pod标签选择器不匹配风险

检查terraform-iaac/service/kubernetes模块的标签选择逻辑:

  • 你的StatefulSet Pod标签是app: mongo(来自local.labels)
  • Service模块的app_name设置为module.mongo.name(即mongodb),如果该模块默认用app: ${app_name}作为选择器,那么Service会去匹配app: mongodb的Pod,但你的Pod标签是app: mongo,导致Service找不到后端Pod。

验证方法:执行kubectl describe service mongodb -n <你的命名空间>查看Selector字段,确认是否和Pod标签一致。

修复:如果模块支持自定义选择器,显式指定匹配Pod的标签:

# 参考模块文档,添加selector配置(如果支持)
selector = local.labels

或者调整StatefulSet的custom_labels为app: mongodb,保持和Service选择器一致。

3. 未启用PersistentVolumeClaim(非连接问题,但建议修复)

你定义了kubernetes_persistent_volume_claim.example,但StatefulSet模块中注释掉了volume_claim配置,当前使用的是hostPath存储,Pod迁移后数据会丢失。建议启用PVC:

volume_claim = [
  {
    name                   = "mongo"
    namespace              = kubernetes_namespace.cmprimg.metadata[0].name
    access_modes           = ["ReadWriteOnce"]
    requests_storage       = "20Gi"
    storage_class_name     = "linode-block-storage-retain"
  }
]

同时删除volume_host_path配置,避免存储冲突。

4. 验证修复步骤

  1. 应用修改后的Terraform配置:terraform apply
  2. 确认Service后端Pod状态:kubectl get endpoints mongodb -n <你的命名空间>,查看是否有READY的Pod
  3. 在Pod内重新测试集群域名连接:mongosh mongodb.default.svc.cluster.local:27017 -u <用户名> -p <密码>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:20:28