【问题标题】:Exposing mongodb on kubernetes statefulsets to external world将 kubernetes statefulsets 上的 mongodb 暴露给外部世界
【发布时间】:2017-06-23 21:20:34
【问题描述】:

我已经使用这个 helm chart 在带有 Statefulsets 的 kubernetes 上设置了 mongodb 副本集

我可以访问集群内的 mongo 实例。但我想打开它以访问外部世界。我尝试了两种方法来完成它

  1. 使用选择器标签创建一个“NodePort”类型的附加服务映射到 mongo 实例。

  2. 在外部公开所有 3 个 mongodb pod。

    kubectl expose pods mongo-release-mongodb-replicaset-2 --type=NodePort

这是我的测试脚本。

 from pymongo import MongoClient
 client = MongoClient('192.168.99.100',30738) #approach 1
 #client = MongoClient('mongodb://192.168.99.100:31455,192.168.99.100:31424,192.168.99.100:31569/?replicaSet=rs0') #approach 2
 db=client.test
 db.test.insert({"key1":1})
 values=db.test.find({'key1': 1})
 for value in values:
    print value

使用第一种方法,我得到以下错误,这是有道理的,因为外部服务并没有始终命中副本集中的主节点。多次尝试最终会连接到 master 并且写入工作。

File "/Library/Python/2.7/site-packages/pymongo/pool.py", line 552, in _raise_connection_failure
raise error
pymongo.errors.NotMasterError: not master

使用第二种方法,因为我们是通过 IP:port 直接访问每个 pod,所以我希望它可以工作,但它会引发以下异常

pymongo.errors.ServerSelectionTimeoutError: mongo-release-mongodb-replicaset-0.mongo-release-mongodb-replicaset.default.svc.cluster.local:27017: [Errno 8] nodename nor servname provided, or not known,mongo-release-mongodb-replicaset-2.mongo-release-mongodb-replicaset.default.svc.cluster.local:27017: [Errno 8] nodename nor servname provided, or not known,mongo-release-mongodb-replicaset-1.mongo-release-mongodb-replicaset.default.svc.cluster.local:27017: [Errno 8] nodename nor servname provided, or not known

从错误看来,DNS 转换引起了问题?我查看了这个question,但没有从中得到太多帮助

我的想法已经不多了。任何人都可以帮助解决这个问题吗?任何替代解决方案也值得赞赏。

谢谢

【问题讨论】:

  • 1.和 2. 是严格等价的,在 2. 你应该使用 expose rs 而不是 expose pod

标签: mongodb kubernetes mongodb-replica-set


【解决方案1】:

在花了更多时间解决这个问题后,我发现上述脚本中的 mongo 端点正在以以下格式返回副本集的 DNS - 'mongo-release-mongodb-replicaset-0.mongo-release-mongodb-副本集.default.svc.cluster.local:27017'。这些地址只能在集群命名空间内解析。通过在另一个 pod 中运行以下脚本来验证是否相同

from pymongo import MongoClient
client = MongoClient('mongodb://mongo-release-mongodb-replicaset-0.mongo-release-mongodb-replicaset:27017,mongo-release-mongodb-replicaset-1.mongo-release-mongodb-replicaset:27017,mongo-release-mongodb-replicaset-2.mongo-release-mongodb-replicaset:27017/?replicaSet=rs0')
db=client.test
db.test.insert({"key1":1})
values=db.test.find({'key1': 1})
for value in values:
   print value

【讨论】:

  • 确实,如果您创建 NodePort 类型的服务,您必须访问暴露端口(私有/公共网络接口)的节点的 IP。服务名只能被 kube-dns 解析,返回的 IP 只能是内部的(pods/cluster 节点)。
  • 主要问题是 MongoDB 集群根据您为启动副本集提供的配置向客户端提供其拓扑。外部端点仅用于获取此拓扑,然后客户端尝试直接访问 mongo 节点。您需要多点: - rs.initiate() 中提供的名称必须可以从您的客户端解析 - 解析的 IP 必须可以从您的客户端路由
猜你喜欢
  • 1970-01-01
  • 2016-11-03
  • 2020-01-28
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
  • 1970-01-01
  • 1970-01-01
  • 2021-08-30
相关资源
最近更新 更多