10

So I've been struggling with this all afternoon. I can't at all get my NodeJS application running on kubernetes to connect to my MongoDB Atlas database.

In my application I've tried running

mongoose.connect('mongodb+srv://admin:<password>@<project>.gcp.mongodb.net/project_prod?retryWrites=true&w=majority', { useNewUrlParser: true })

but I simply get the error

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)

I've tried setting up a ExternalName service too, but using either the URL or the ExternalName results in me not being able to connect to the database.

I've whitelisted my IP on MongoDB Atlas, so I know that isn't the issue.

It also seems to work on my local machine, but not in the kubernetes pod. What am I doing wrong?

2
  • 1
    Can you allow all IP addresses to be whitelisted and then try the same? Commented Jun 1, 2019 at 19:46
  • Doesn't seem to make a difference, which makes sense because it appears to be a DNS error. Mongoose will give an error stating your IP is not whitelisted if you connect from an invalid host. Commented Jun 3, 2019 at 15:12

3 Answers 3

9

I figured out the issue, my pod DNS was not configured to allow external connections, so I set dnsPolicy: Default in my YML, because oddly enough Default is not actually the default value

Sign up to request clarification or add additional context in comments.

Comments

1

I use MongoDB Atlas from Kubernetes but on AWS. Although for testing purposes you can enable all IP addresses and test, here is the approach for a production setup:

  • MongoDB Atlas supports Network Peering
  • Under Network Access > New Peering Connection
  • In the case of AWS, VPC ID, CIDR and Region have to be specified. For GCP it should be the standard procedure used for VPC peering.

3 Comments

So I've set this all up on google cloud platform, but I can't seem to figure out how I am supposed to connect my application once I'm using this. How do you do it?
First, can you verify if your app is able to connect to the service from within a local Docker image of your app?
Great. Can you create a temperory VM in the same VPC as that of your K8s cluster and connect to Atlas? This is to verify peering
1

Firstly, Pods are deployed on nodes in a cluster and not on your service (so Mongo won't recognise your service endpoints e.g; load balancer IP). Based on this, there are two solutions:

solution A

  1. Add the endpoint of the Kubernetes cluster to the MongoDB network access IP whitelist.

  2. Under the pod spec of your k8s pod (or deployment) manifest, add a dnsPolicy field with value set to Default. Hence, your Pods (your container basically) will connect to mongo through the name resolution configuration of the master node.

solution B

  1. Add all node endpoints in your k8s cluster to the MongoDB network access IP whitelist.

  2. Under the pod spec of your k8s pod (or deployment) manifest, add a dnsPolicy field with the value set to ClusterFirstWithHostNet. Since the pods run with your host network, they gain access to services listening on localhost.

Kubernetes documentation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.