Static IP for Google Cloud Cloud Functions internet access (Serverless VPC access + Cloud NAT)
GCP Cloud functions are a serverless computing platform that allows you to run code without provisioning or managing servers. They are triggered by events, such as an HTTP request, a file upload to Cloud Storage, or a message on a Pub/Sub topic. Cloud functions are highly scalable and can be used to build a wide variety of applications, including microservices, APIs, and event-driven workflows.
Cloud functions often need to access third-party or on-premises applications, and cloud function uses the default internet gateway provided by GCP for internet access. However, many organizations require a static IP address for these internet requests to whitelist the IP address and restrict the connections. Unfortunately, this is not possible with the default internet gateway because no static IP is attached.
In this blog post, We will explore how to solve this issue using Serverless VPC access and cloud NAT.
Serverless VPC Access allows connecting directly to the Virtual Private Cloud (VPC) network from serverless environments such as Cloud functions, App Engine, or Cloud Run. Public Cloud NAT lets Google Cloud resources that do not have public IP addresses communicate with the Internet.
Reference Architecture
Here’s a sample reference architecture for this setup.
Setup Network resources and deploy cloud function
Step 1: Set up the necessary environment variables.
export PROJECT_ID="chimbuc-playground" #your-project-id
export REGION="us-central1"
export VPC_NAME="egress-test-vpc"
export SERVERLESS_VPC_ACCESS_SUBNET_NAME="serverless-vpc-access"
export SERVERLESS_VPC_ACCESS_SUBNET_CIDR="10.150.0.0/28"
export SERVERLESS_VPC_ACCESS_CONNECTOR_NAME="serverless-vpc-connector"
Step 2: Create the VPC network and subnets for the serverless vpc connector. This subnet must be used exclusively by the connector and cannot be used by other resources such as VMs, Private Service Connect, or load balancers. Make sure the subnet range doesn’t overlap with any in-use CIDR ranges.
gcloud beta compute networks create $VPC_NAME \
--subnet-mode=custom
gcloud beta compute networks subnets create $SERVERLESS_VPC_ACCESS_SUBNET_NAME \
--network=$VPC_NAME \
--role="ACTIVE" \
--purpose="PRIVATE" \
--range=$SERVERLESS_VPC_ACCESS_SUBNET_CIDR \
--region=$REGION
Step 3: Create public cloud NAT resources for internet access.
#Reserve a new static external IP address for cloud nat
gcloud compute addresses create $REGION-public-cloud-nat \
--region=$REGION
#Cloud router
gcloud compute routers create $REGION-cloud-nat \
--network=$VPC_NAME \
--asn=65001 \
--region=$REGION
gcloud compute routers nats create $REGION-public-cloud-nat \
--router=$REGION-cloud-nat \
--region=$REGION \
--nat-all-subnet-ip-ranges \
--nat-external-ip-pool=$REGION-public-cloud-nat \
--enable-logging
Step 4: Create a serverless VPC access connector.
#Enable google cloud api for vpc access
gcloud services enable vpcaccess.googleapis.com
gcloud compute networks vpc-access connectors create $SERVERLESS_VPC_ACCESS_CONNECTOR_NAME \
--region $REGION \
--subnet $SERVERLESS_VPC_ACCESS_SUBNET_NAME
#Verify that connector is in the READY state before using it
gcloud compute networks vpc-access connectors describe $SERVERLESS_VPC_ACCESS_CONNECTOR_NAME \
--region $REGION
Step 5: Let’s deploy a sample cloud function. It is attached to the serverless vpc connector. Copy the below simple sample cloud function to your local machine.
cat << EOF > main.py
import requests
def ip_check(request):
response = requests.get('http://ipecho.net/plain') #sends sample external request and returns the ip address of the machine.
print(response.text)
return "my ip address is "+ str(response.text)
EOF
cat << EOF > requirements.txt
requests
EOF
Deploy the cloud function.
gcloud functions deploy egress-test-function \
--gen2 \
--region=$REGION \
--runtime=python38 \
--source=. \
--entry-point=ip_check \
--trigger-http \
--allow-unauthenticated \
--vpc-connector=projects/$PROJECT_ID/locations/$REGION/connectors/$SERVERLESS_VPC_ACCESS_CONNECTOR_NAME \
--egress-settings=all #forward-all-the-cloud-function-egress-to-vpc-via-serverless-vpc-connector
Test the outbound connections
After completing the above steps, you should be able to verify that the cloud function has been successfully deployed and is now ready for testing. With the help of the serverless VPC connector, all outbound connections to the VPC internal IPs and external internet requests will now be forwarded to the VPC, while Cloud NAT will handle the internet requests.
Invoke the cloud function, and you should see the cloud NAT IP in the IP address for the internet requests.
You can verify the same in cloud logging if cloud NAT logging is enabled.
Conclusion
By implementing the configurations outlined in this post, you can confidently deploy Cloud Functions that meet your organization’s networking and security requirements. Thus, making it easier to build a wide range of applications while maintaining control over internet access.
You can also apply a similar setup to Cloud Run with a serverless VPC connector (Cloud NAT is currently not supported in Direct VPC egress). I hope this post has been helpful. Please let me know if you have any questions or feedback.