我已经使用mongo k8s sidecar在kubernetes上设置了3个成员副本集mongo集群。我需要在外部公开mongodb服务,因此创建了LoadBalancer。
这是服务的外观
LoadBalancer Ingress: xxx.yyy.elb.amazonaws.com
Port: <unset> 27017/TCP
TargetPort: 27017/TCP
NodePort: <unset> 30994/TCP
Endpoints: 100.14.1.3:27017,100.14.1.4:27017,100.14.2.5:27017
尝试使用mongodb shell 3.6正常连接
mongo --host xxx.yyy.elb.amazonaws.com
但是在Java客户端代码中,我看到以下异常。
java.net.UnknownHostException: mongo-1.mongo.dev.svc.cluster.local
我可以确认mongo pod已启动并正在运行。我能够从集群中的其他Pod连接到mongo-只是无法从外部访问它。
我不明白的是Java客户端中到底发生了什么。
如下创建Java客户端(使用spring-data-mongo进行配置)。
MongoClient mongoClient = new MongoClient( "xxx.yyy.elb.amazonaws.com" , 27017 );
全栈跟踪如下
Caused by: com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting for a server that matches com.mongodb.client.internal.MongoClientDelegate$1@161f6623. Client view of cluster state is {type=REPLICA_SET, servers=[{address=mongo-2.mongo.dev.svc.cluster.local:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketException: mongo-2.mongo.dev.svc.cluster.local}, caused by {java.net.UnknownHostException: mongo-2.mongo.dev.svc.cluster.local}}, {address=mongo-0.mongo.dev.svc.cluster.local:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketException: mongo-0.mongo.dev.svc.cluster.local}, caused by {java.net.UnknownHostException: mongo-0.mongo.dev.svc.cluster.local}}, {address=mongo-1.mongo.dev.svc.cluster.local:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketException: mongo-1.mongo.dev.svc.cluster.local}, caused by {java.net.UnknownHostException: mongo-1.mongo.dev.svc.cluster.local}}]
at com.mongodb.internal.connection.BaseCluster.createTimeoutException(BaseCluster.java:401)
at com.mongodb.internal.connection.BaseCluster.selectServer(BaseCluster.java:120)
即使我已通过负载均衡器地址,为什么mongoClient仍使用pod名称?我该如何解决?
预先感谢
答案 0 :(得分:2)
您遇到mongo-1.mongo.dev.svc.cluster.local
的错误,这是群集内的内部端点。换句话说,这就是从集群中的其他Pod进入Mongo实例的方式。
在Java客户端上,您需要使用xxx.yyy.elb.amazonaws.com:27017
作为Mongo端点配置。
类似这样的东西:
MongoClient mongoClient = new MongoClient( "xxx.yyy.elb.amazonaws.com" , 27017 );
为了给您提供路径概述,您的Mongo实例通过27017
端口上的LoadBalancer Kubernetes服务公开。
然后,流量进入负载均衡器,并从那里转发到端点100.14.1.3:27017
等。
然后从那里,它们在每个节点的NodePort 30994
上进入Node。
然后有运行pod的节点回答一个答案。
容器本身的Mongo进程在端口27017
上运行,因此,当流量到达端口30994
上的节点时,容器运行时会将流量转发到容器中的应用程序到{{1 }}。