Connecting to mongodb atlas/external service from Google cloud functions via static IP address
I am using google cloud functions for variety of background jobs, batch based ETL jobs etc.
Accessing the database on these jobs are much easier and faster than working via API’s. Accessing the database directly from cloud functions means that we will need to allow all incoming traffic (0.0.0.0), since cloud functions don’t have static IP. This would freak out database administrator !!!
To workaround this problem we can leverage
- Serverless VPC (https://cloud.google.com/vpc/docs/configure-serverless-vpc-access#connectors)
- Cloud NAT (https://cloud.google.com/nat/docs/using-nat)
Couple things about our infra
- We don’t have a separate VPC for our application, instead using the default VPC of google cloud
- The main application and web traffic are hosted on the asia regions
- The database is also hosted on the asia region (same as application)
- The cloud functions are hosted on the us-central1 since the they aren’t available yet in the local region
Step 1 : Cloud function
I have written a small sample cloud function to check mainly 2 things
- Can the function access external API ?
- Is there is a static IP for the cloud function ?
I am using standard external services to verify the above. If above 2 are working as expected, then we should be able to access mongodb database on atlas or any other external accessible service
const simpleExternalAPIAccess = functions.https.onRequest(async (request, response) => {
const result = await axios.get("https://jsonplaceholder.typicode.com/todos/1");
const resultIP = await axios.get("https://api.ipify.org/?format=json")
response.send({
data: JSON.stringify(result.data),
ip: JSON.stringify(resultIP.data)
});
});
Step 2 : Configuring Serverless VPC
Create a serverless VPC connector via console/shell. Ensure that this VPC connector is created in the region of the cloud functions.
Detailed documentation for this is available @ https://cloud.google.com/vpc/docs/configure-serverless-vpc-access#creating_a_connector
gcloud compute networks vpc-access connectors create [CONNECTOR_NAME] \
--network [VPC_NETWORK] \
--region [REGION] \
--range [IP_RANGE]e.g.gcloud compute networks vpc-access connectors create knowledgefactory-taskhub-us-central1
--network default \
--region us-central1 \
--range 10.8.0.0
Step 3: Configure the cloud functions to use the VPC connector
The cloud functions needs to be updated to use the VPC connector. This again can be done via UI or gcloud. Check https://cloud.google.com/functions/docs/networking/connecting-vpc#configuring
gcloud functions deploy helloWorld \
--vpc-connector <full path of connector>
* If you are using firebase-tools for deployment of cloud functions, unfortunately firebase-tools do not have ability to add vpc connector
Step 4 : Configure Cloud NAT
Step 1 and 2 ensure that there is a VPC connector configured, however its the NAT which allows for all the traffic to be routed. We can have ingress and egress rules configured for the cloud NAT.
Ensure that Cloud NAT is created in the same region as the VPC connector. In the above case I am creating it at “us-central1”.
Detailed documentation is available at https://cloud.google.com/nat/docs/using-nat
gcloud compute routers nats create nat-config \
--router=knowledgefactory-router \
--nat-external-ip-pool=<ip_addressses>
Once the above steps are done, cloud functions will be able to access any external traffic using the static ip address
Step 5: Verify running the cloud function written in step 1
- Run the cloud function via console/ui
The response will be something like
{
"data": {
"userId":1,
"id":1,"title":"delectus aut autem",
"completed":false
},
"ip": { "ip": <public_ip_address_configured_in_nat>}
}
- check that you get to access the external api
- check that you get to see the static IP address in the response
Step 6 : Configure mongodb atlas to allow incoming traffic from the static IP address
- Login to mongodb atlas console
- Navigate to the networking under the cluster and ensure that the static IP address configured in cloud NAT is whitlisted
That’s it, we are done. Now we should be able to access the mongodb or for that matter any external service via static ip address.