Kubernetes node.js 容器无法连接到 MongoDB Atlas
Kubernetes node.js container cannot connect to MongoDB Atlas
所以我整个下午都在为此苦苦挣扎。我根本无法在 kubernetes 上让我的 NodeJS 应用程序 运行 连接到我的 MongoDB Atlas 数据库。
在我的应用程序中,我已经尝试过 运行
mongoose.connect('mongodb+srv://admin:<password>@<project>.gcp.mongodb.net/project_prod?retryWrites=true&w=majority', { useNewUrlParser: true })
但我只是得到了错误
UnhandledPromiseRejectionWarning: Error: querySrv ETIMEOUT _mongodb._tcp.<project>.gcp.mongodb.net
at QueryReqWrap.onresolve [as oncomplete] (dns.js:196:19)
(node:32) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 17)
我也尝试过设置 ExternalName 服务,但是使用 URL 或 ExternalName 导致我无法连接到数据库。
我已经在 MongoDB Atlas 上将我的 IP 列入白名单,所以我知道这不是问题所在。
它似乎也适用于我的本地机器,但不适用于 kubernetes pod。我做错了什么?
我使用来自 Kubernetes 但在 AWS 上的 MongoDB Atlas。虽然出于测试目的,您可以启用所有 IP 地址并进行测试,但这里是生产设置的方法:
- MongoDB Atlas 支持网络对等
- 在网络访问 > 新建对等连接下
- 对于 AWS,必须指定 VPC ID、CIDR 和区域。对于 GCP,它应该是用于 VPC 对等互连的标准程序。
我发现了问题,我的 pod DNS 没有配置为允许外部连接,所以我在我的 YML 中设置了 dnsPolicy: Default
,因为奇怪的是 Default
实际上不是默认值
首先,Pods 部署在集群中的节点上而不是您的服务上(因此 Mongo 无法识别您的服务端点 例如;负载均衡器 IP)。基于此,有两种解决方案:
解决方案 A
将Kubernetes集群端点加入MongoDB网络访问IP白名单
在您的 k8s pod(或部署)清单的 pod 规范下,添加一个 dnsPolicy 字段,并将值设置为 Default。因此,您的Pods(基本上是您的容器)将通过主节点的名称解析配置连接到mongo。
方案B
将您的 k8s 集群中的所有节点端点添加到 MongoDB 网络访问 IP 白名单。
在您的 k8s pod(或部署)清单的 pod 规范下,添加一个 dnsPolicy 字段,并将值设置为 ClusterFirstWithHostNet。由于 pods 运行 与您的主机网络,他们可以访问在本地主机上侦听的服务。
所以我整个下午都在为此苦苦挣扎。我根本无法在 kubernetes 上让我的 NodeJS 应用程序 运行 连接到我的 MongoDB Atlas 数据库。
在我的应用程序中,我已经尝试过 运行
mongoose.connect('mongodb+srv://admin:<password>@<project>.gcp.mongodb.net/project_prod?retryWrites=true&w=majority', { useNewUrlParser: true })
但我只是得到了错误
UnhandledPromiseRejectionWarning: Error: querySrv ETIMEOUT _mongodb._tcp.<project>.gcp.mongodb.net
at QueryReqWrap.onresolve [as oncomplete] (dns.js:196:19)
(node:32) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 17)
我也尝试过设置 ExternalName 服务,但是使用 URL 或 ExternalName 导致我无法连接到数据库。
我已经在 MongoDB Atlas 上将我的 IP 列入白名单,所以我知道这不是问题所在。
它似乎也适用于我的本地机器,但不适用于 kubernetes pod。我做错了什么?
我使用来自 Kubernetes 但在 AWS 上的 MongoDB Atlas。虽然出于测试目的,您可以启用所有 IP 地址并进行测试,但这里是生产设置的方法:
- MongoDB Atlas 支持网络对等
- 在网络访问 > 新建对等连接下
- 对于 AWS,必须指定 VPC ID、CIDR 和区域。对于 GCP,它应该是用于 VPC 对等互连的标准程序。
我发现了问题,我的 pod DNS 没有配置为允许外部连接,所以我在我的 YML 中设置了 dnsPolicy: Default
,因为奇怪的是 Default
实际上不是默认值
首先,Pods 部署在集群中的节点上而不是您的服务上(因此 Mongo 无法识别您的服务端点 例如;负载均衡器 IP)。基于此,有两种解决方案:
解决方案 A
将Kubernetes集群端点加入MongoDB网络访问IP白名单
在您的 k8s pod(或部署)清单的 pod 规范下,添加一个 dnsPolicy 字段,并将值设置为 Default。因此,您的Pods(基本上是您的容器)将通过主节点的名称解析配置连接到mongo。
方案B
将您的 k8s 集群中的所有节点端点添加到 MongoDB 网络访问 IP 白名单。
在您的 k8s pod(或部署)清单的 pod 规范下,添加一个 dnsPolicy 字段,并将值设置为 ClusterFirstWithHostNet。由于 pods 运行 与您的主机网络,他们可以访问在本地主机上侦听的服务。