1. Introduction
Private Service Connect (PSC) is a capability of Google Cloud networking that allows consumers to access managed services privately from inside their VPC network. Similarly, it allows managed service producers to host these services in their own separate VPC networks and offer a private connection to their consumers.
Cloud Run is a managed compute platform that lets you run containers directly on top of Google's scalable infrastructure.
Cloud Run is able to be consumed as a PSC service in two different ways.
- Through PSC for Google APIs by calling Cloud Run through the Cloud Run provided run.app URL
- Through a custom PSC producer service where Cloud Run is exposed through a Service Attachment via an Internal Application Load Balancer with a Serverless NEG.
This codelab will explore how to set up Cloud Run with PSC for both of these scenarios
What you'll learn
- Deploying basic apps on Cloud Run
- Cloud Run ingress and egress controls
- Deploying Cloud Run through an Internal Application Load Balancer with a Serverless NEG
- Setting up a PSC Producer Service through a Service Attachment
- Deploying PSC Endpoints
What you'll need
- Google Cloud Project with Owner permissions
2. Codelab topology
In this codelab, you will deploy two Cloud Run services that will be accessible via PSC - first as a custom published service with PSC, and second as PSC for Google APIs. You will create two VPCs, a consumer-vpc and a producer-vpc. You'll first deploy the Hello World Cloud Run service and make it accessible via a Regional Internal Application Load Balancer and Serverless NEG in the producer-vpc. You'll verify that the service is working through the load balancer via producer-client before setting up the Cloud Run service to be accessible as a PSC producer service via a Service Attachment.
Moving on to the consumer-vpc, you'll deploy a PSC endpoint pointing to the Cloud Run Service Attachment we set up in the producer-vpc. You'll then verify that the service is accessible via PSC from a consumer-client in the consumer-vpc. Next, you'll create another Cloud Run service that calls your PSC Endpoint. Finally, you'll deploy a PSC Endpoint for Google APIs. From consumer-client, you'll access Cloud Run via the Cloud Run provided URL, which will use the PSC for Google APIs endpoint.
3. Setup and Requirements
Self-paced environment setup
- Sign-in to the Google Cloud Console and create a new project or reuse an existing one. If you don't already have a Gmail or Google Workspace account, you must create one.
- The Project name is the display name for this project's participants. It is a character string not used by Google APIs. You can always update it.
- The Project ID is unique across all Google Cloud projects and is immutable (cannot be changed after it has been set). The Cloud Console auto-generates a unique string; usually you don't care what it is. In most codelabs, you'll need to reference your Project ID (typically identified as
PROJECT_ID
). If you don't like the generated ID, you might generate another random one. Alternatively, you can try your own, and see if it's available. It can't be changed after this step and remains for the duration of the project. - For your information, there is a third value, a Project Number, which some APIs use. Learn more about all three of these values in the documentation.
- Next, you'll need to enable billing in the Cloud Console to use Cloud resources/APIs. Running through this codelab won't cost much, if anything at all. To shut down resources to avoid incurring billing beyond this tutorial, you can delete the resources you created or delete the project. New Google Cloud users are eligible for the $300 USD Free Trial program.
Start Cloud Shell
While Google Cloud can be operated remotely from your laptop, in this codelab you will be using Google Cloud Shell, a command line environment running in the Cloud.
From the Google Cloud Console, click the Cloud Shell icon on the top right toolbar:
It should only take a few moments to provision and connect to the environment. When it is finished, you should see something like this:
This virtual machine is loaded with all the development tools you'll need. It offers a persistent 5GB home directory, and runs on Google Cloud, greatly enhancing network performance and authentication. All of your work in this codelab can be done within a browser. You do not need to install anything.
4. Before you begin
Enable APIs
Inside Cloud Shell, make sure that your project is set up and configure variables.
gcloud auth login gcloud config list project gcloud config set project [YOUR-PROJECT-ID] export projectid=[YOUR-PROJECT-ID] export projectnum=[YOUR-PROJECT-NUM] export region=us-central1 export zone=us-central1-a echo $projectid echo $projectnum echo $region echo $zone
Enable all necessary services
gcloud services enable compute.googleapis.com gcloud services enable run.googleapis.com gcloud services enable servicedirectory.googleapis.com gcloud services enable dns.googleapis.com gcloud services enable cloudbuild.googleapis.com gcloud services enable cloudresourcemanager.googleapis.com
5. Create Producer VPC Network
VPC Network
From Cloud Shell
gcloud compute networks create producer-vpc --subnet-mode custom
Create Subnets
From Cloud Shell
gcloud compute networks subnets create producer-subnet \ --network=producer-vpc \ --range=10.0.0.0/28 \ --region=$region gcloud compute networks subnets create lb-proxy-subnet \ --network=producer-vpc \ --range=10.100.100.0/24 \ --region=$region \ --purpose=REGIONAL_MANAGED_PROXY \ --role=ACTIVE gcloud compute networks subnets create psc-nat-subnet \ --network=producer-vpc \ --region=$region \ --range=10.100.101.0/24 \ --purpose=PRIVATE_SERVICE_CONNECT
The PSC subnet will be associated with the PSC Service Attachment for the purpose of Network Address Translation. For production use cases, this subnet needs to be sized appropriately to support the number of endpoints attached. See PSC NAT subnet sizing documentation for more information.
Create Producer Network Firewall Policy and Firewall Rules
From Cloud Shell
gcloud compute network-firewall-policies create producer-vpc-policy --global gcloud compute network-firewall-policies associations create \ --firewall-policy producer-vpc-policy \ --network producer-vpc \ --name network-producer-vpc \ --global-firewall-policy
To allow IAP to connect to your VM instances, create a firewall rule that:
- Applies to all VM instances that you want to be accessible by using IAP.
- Allows ingress traffic from the IP range 35.235.240.0/20. This range contains all IP addresses that IAP uses for TCP forwarding.
From Cloud Shell
gcloud compute network-firewall-policies rules create 1000 \ --action ALLOW \ --firewall-policy producer-vpc-policy \ --description "SSH with IAP" \ --direction INGRESS \ --src-ip-ranges 35.235.240.0/20 \ --layer4-configs tcp:22 \ --global-firewall-policy
6. Create Hello World Cloud Run
Follow the directions here to write a sample application in Python. Run these commands in Cloud Shell. After you have finished step 3 in "Write the Sample Application" return to this Codelab and follow the instructions below to Deploy to Cloud Run from Source.
Before deploying your Cloud Run service, ensure your default compute service account has the proper permissions by running the following command.
From Cloud Shell
gcloud projects add-iam-policy-binding $projectid --member=serviceAccount:$projectnum-compute@developer.gserviceaccount.com --role=roles/run.builder
NOTE: This codelab assumes that your organization does not have the Domain Restricted Sharing Organization Policy enabled. If you do have this policy enabled, you'll have to perform extra steps to deploy Cloud Run with authentication, configuring an OAuth Consent Screen, and set up IAP for your load balancer backend. It is recommended that all of these configuration steps are followed in a production environment.
From Cloud Shell
gcloud beta run deploy helloworld \ --source . \ --platform=managed \ --ingress=internal \ --allow-unauthenticated \ --no-default-url \ --region=$region
Using the --no-default-url
flag will deploy your Cloud Run service without the provided run.app URL. We will not be using the URL for this service. As of the publishing of this codelab, this feature is still in preview.
Before moving on, change back to the main directory of your Cloud Shell.
From Cloud Shell
cd ..
7. Expose Hello World Cloud Run through an Internal Application Load Balancer
Reserve a static internal IP address for your load balancer forwarding rule.
In Cloud Shell
gcloud compute addresses create cloudrun-ip \ --region=$region \ --subnet=producer-subnet gcloud compute addresses describe cloudrun-ip --region=$region
Sample Output
address: 10.0.1.31 addressType: INTERNAL creationTimestamp: '2025-03-17T09:04:06.620-07:00' description: '' id: 'xxxx' kind: compute#address labelFingerprint: xxxx name: cloudrun-ip networkTier: PREMIUM purpose: GCE_ENDPOINT region: https://www.googleapis.com/compute/v1/projects/$projectid/regions/$region selfLink: https://www.googleapis.com/compute/v1/projects/$projectid/regions/$region/addresses/cloudrun-ip status: RESERVED subnetwork: https://www.googleapis.com/compute/v1/projects/$projectid/regions/$region/subnetworks/producer-subnet
Make note of the IP address that you just created.
Create the Regional Internal Application Load Balancer
In Cloud Shell
gcloud compute network-endpoint-groups create cloudrun-producer-neg \ --region=$region \ --network-endpoint-type=serverless \ --cloud-run-service=helloworld gcloud compute backend-services create cloudrun-producer-bes \ --load-balancing-scheme=INTERNAL_MANAGED \ --protocol=HTTP \ --region=$region gcloud compute backend-services add-backend cloudrun-producer-bes \ --region=$region \ --network-endpoint-group=cloudrun-producer-neg \ --network-endpoint-group-region=$region gcloud compute url-maps create producer-urlmap \ --default-service=cloudrun-producer-bes \ --region=$region gcloud compute target-http-proxies create producer-http-proxy \ --url-map=producer-urlmap \ --region=$region
In Cloud Shell
gcloud compute forwarding-rules create cloudrun-fr \ --load-balancing-scheme=INTERNAL_MANAGED \ --network=producer-vpc \ --subnet=producer-subnet \ --address=cloudrun-ip \ --target-http-proxy=producer-http-proxy \ --target-http-proxy-region=$region \ --region=$region \ --ports=80 \ --allow-global-access
8. Test Hello World Cloud Run Exposed Through Load Balancer
Create Test VM
From Cloud Shell
gcloud compute instances create producer-client \ --zone=$zone \ --subnet=producer-subnet \ --no-address \ --scopes=cloud-platform
In Cloud Shell
gcloud compute ssh \ --zone "$zone" "producer-client" \ --tunnel-through-iap \ --project $projectid
Replace <loadbalancer-ip> with the IP address that you created earlier (example 10.0.0.2).
Test Hello World
In producer-vm
curl <loadbalancer-ip>
Expected Output
Hello World!
Exit from the VM.
In producer-vm
exit
9. Create Service Attachment
From Cloud Shell
gcloud compute service-attachments create cloudrun-attachment \ --region=$region \ --producer-forwarding-rule=cloudrun-fr \ --connection-preference=ACCEPT_MANUAL \ --consumer-accept-list=$projectid=5 \ --nat-subnets=psc-nat-subnet
Next, retrieve and note the Service Attachment URI to configure the PSC endpoint in the consumer environment.
In Cloud Shell
gcloud compute service-attachments describe cloudrun-attachment --region=$region
Example Expected Output
connectionPreference: ACCEPT_MANUAL consumerAcceptLists: - connectionLimit: 5 projectIdOrNum: $projectid creationTimestamp: '2025-03-10T08:49:08.134-07:00' description: '' enableProxyProtocol: false fingerprint: -F0Kpe3Fi8o= id: '2679595584727463707' kind: compute#serviceAttachment name: cloudrun-attachment natSubnets: - https://www.googleapis.com/compute/v1/projects/$projectid/regions/$region/subnetworks/psc-nat-subnet pscServiceAttachmentId: high: 'xxxxx' low: 'xxxx' reconcileConnections: false region: https://www.googleapis.com/compute/v1/projects/$projectid/regions/$region selfLink: https://www.googleapis.com/compute/v1/projects/$projectid/regions/$region/serviceAttachments/cloudrun-attachment targetService: https://www.googleapis.com/compute/v1/projects/$projectid/regions/$projectid/forwardingRules/cloudrun-fr
10. Create Consumer VPC network
VPC Network
From Cloud Shell
gcloud compute networks create consumer-vpc --subnet-mode custom
Create Subnet
From Cloud Shell
gcloud compute networks subnets create consumer-subnet \ --network=consumer-vpc \ --range=10.0.0.0/24 \ --region=$region \ --enable-private-ip-google-access gcloud compute networks subnets create cloudrun-egress \ --network=consumer-vpc \ --range=10.0.1.0/24 \ --region=$region \ --enable-private-ip-google-access
Create Cloud NAT
From Cloud Shell
gcloud compute routers create central-cr \ --network=consumer-vpc \ --region=$region gcloud compute routers nats create central-nat \ --router=central-cr \ --region=$region \ --nat-all-subnet-ip-ranges \ --auto-allocate-nat-external-ips
Create Consumer Network Firewall Policy and Firewall Rules
We'll create another Network Firewall Policy for the consumer-vpc.
From Cloud Shell
gcloud compute network-firewall-policies create consumer-vpc-policy --global gcloud compute network-firewall-policies associations create --firewall-policy consumer-vpc-policy --network consumer-vpc --name network-consumer-vpc --global-firewall-policy gcloud compute network-firewall-policies rules create 1000 --action ALLOW --firewall-policy consumer-vpc-policy --description "SSH with IAP" --direction INGRESS --src-ip-ranges 35.235.240.0/20 --layer4-configs tcp:22 --global-firewall-policy
11. Create PSC Endpoint for Hello World Cloud Run Service
At this point, we'll create a PSC endpoint and connect it to the Cloud Run service you exposed via the Service Attachment. You'll use the service attachment URI that you noted earlier in this section. Make sure that the format of the URI in the gcloud command matches your URI.
Create PSC Endpoint
From Cloud Shell
gcloud compute addresses create cloudrun-service-ip --region=$region --subnet=consumer-subnet --ip-version=IPV4 gcloud compute forwarding-rules create cloudrun-ep --region=$region --network=consumer-vpc --address=cloudrun-service-ip --target-service-attachment=projects/$projectid/regions/$region/serviceAttachments/cloudrun-attachment
Get the IP address of the PSC Endpoint you just created. You'll use the IP address in the next step to test the endpoint.
From Cloud Shell
gcloud compute addresses list --filter="name=cloudrun-service-ip"
Example Expected Output
NAME: cloudrun-service-ip ADDRESS/RANGE: 10.0.0.2 TYPE: INTERNAL PURPOSE: GCE_ENDPOINT NETWORK: REGION: us-central1 SUBNET: consumer-subnet STATUS: IN_USE
12. Create consumer-client VM and Test Connectivity to Endpoint
Create consumer-client VM
From Cloud Shell
gcloud compute instances create consumer-client \ --zone=$zone \ --subnet=consumer-subnet \ --no-address \ --metadata startup-script='#! /bin/bash sudo apt-get update sudo apt-get install dnsutils -y'
Test Connectivity
From Cloud Shell
gcloud compute ssh \ --zone "$zone" "consumer-client" \ --tunnel-through-iap \ --project $projectid
Replace <cloudrun-service-ip> with the actual IP address.
From consumer-client VM
curl <cloudrun-service-ip>
Expected Output
Hello World!
From consumer-client VM
exit
13. Create Cloud Run Loop Service
Next we will create a Cloud Run service that will make a private call back into the consumer-vpc to call the previous Cloud Run HelloWorld service that we exposed through PSC.
Follow the "Write the sample application" directions here to write a loop application in PHP. Instead of helloworld-php, name your directory cloudrun-loop. Run these commands in Cloud Shell. In step two, use the PHP code below in your index.php file. Return to the codelab when you are ready to deploy to Cloud Run. Do not follow the instructions in the documentation for this step.
Use this code for your index.php file. Replace <cloudrun-service-ip> with the IP address of your PSC endpoint that you tested in the previous step.
From Cloud Shell
<?php if(!function_exists('curl_init')) { die('cURL not available!'); } $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'http://<cloudrun-service-ip>/'); curl_setopt($curl, CURLOPT_FAILONERROR, true); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $output = curl_exec($curl); if ($output === FALSE) { echo 'An error has occurred: ' . curl_error($curl) . PHP_EOL; } else { echo $output; } ?>
We're specifying a network and subnet in this Cloud Run deployment because Cloud Run traffic needs to egress back into the VPC to access the PSC endpoint. We're directing Cloud Run to use the cloudrun-egress subnet for Direct VPC Egress. We're directing all traffic to egress through the Direct VPC Egress subnet back into the VPC.
From Cloud Shell
gcloud run deploy cloudrun-loop \ --source . \ --platform=managed \ --ingress=internal \ --allow-unauthenticated \ --vpc-egress=all-traffic \ --network=consumer-vpc \ --subnet=cloudrun-egress \ --region=$region
When the Cloud Run service finishes deploying it will provide a Service URL in the format https://cloudrun-loop-<projectnum>.<region>.run.app. Note this URL as well will test it in the next step.
14. Test Connectivity to CloudRun-Loop through Cloud Run URL
From Cloud Shell
gcloud compute ssh \ --zone "$zone" "consumer-client" \ --tunnel-through-iap \ --project $projectid
Replace <Cloud-Run-ServiceURL> with the Service URL you noted in the previous step.
From consumer-client VM
curl <Cloud-Run-ServiceURL>
Expected Output
Hello World!
This result shows that our CloudRun-Loop service is successfully calling back into the consumer-vpc to call our PSC endpoint connected to our Hello World Cloud Run service. However, at this point, our consumer-client VM is egressing to the internet through our Cloud NAT to make a call to our public Cloud Run URL. We can run a dig on the URL to show that it will resolve to a public IP address.
From consumer-client VM
dig <Cloud-Run-ServiceURL>
Sample Output
; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> https://cloudrun-loop-<projectnum>.<region>.run.app ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1938 ;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 65494 ;; QUESTION SECTION: ;https://cloudrun-loop-<projectnum>.<region>.run.app. IN A ;; ANSWER SECTION: https://cloudrun-loop-<projectnum>.<region>.run.app. 300 IN A 216.239.38.53 https://cloudrun-loop-<projectnum>.<region>.run.app. 300 IN A 216.239.36.53 https://cloudrun-loop-<projectnum>.<region>.run.app. 300 IN A 216.239.32.53 https://cloudrun-loop-<projectnum>.<region>.run.app. 300 IN A 216.239.34.53 ;; Query time: 4 msec ;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP) ;; WHEN: Tue Mar 11 19:05:36 UTC 2025 ;; MSG SIZE rcvd: 147
We can create a PSC for Google APIs endpoint to change this resolution to private to keep the traffic off the public internet.
From consumer-client VM
exit
15. Create PSC for Google APIs Endpoint
This PSC Endpoint is different from the one we created previously. PSC for Google APIs points to a bundle of Google APIs (either all APIs, or VPC-SC compatible APIs). The IP address is not sourced from a regional subnet, but rather is created as a single /32 IP address that is global that cannot overlap with any existing VPC subnets, peered VPC subnets, or hybrid routes.
From Cloud Shell
export pscgoogip=100.100.100.100 echo $pscgoogip gcloud compute addresses create psc-goog-ep-ip \ --global \ --purpose=PRIVATE_SERVICE_CONNECT \ --addresses=$pscgoogip \ --network=consumer-vpc
From Cloud Shell
gcloud compute forwarding-rules create psc4googapi \ --global \ --network=consumer-vpc \ --address=psc-goog-ep-ip \ --target-google-apis-bundle=all-apis
16. Create Cloud DNS Private Zone for run.app
When a PSC for Google APIs endpoint is created, a Cloud Run private DNS zone will be created for all APIs that fall under the googleapis.com domain. Since Cloud Run uses run.app, we'll need to create another private zone to map run.app to our PSC for Google APIs endpoint.
From Cloud Shell
gcloud dns managed-zones create "cloudrun" \ --dns-name=run.app \ --description="run.app psc resolution" \ --visibility=private \ --networks=consumer-vpc gcloud dns record-sets transaction start \ --zone="cloudrun" gcloud dns record-sets transaction add $pscgoogip \ --name=*.run.app \ --ttl=300 \ --type=A \ --zone="cloudrun" gcloud dns record-sets transaction execute \ --zone="cloudrun"
17. Test Private DNS Resolution
We'll log back into our consumer-client VM and run the dig again, and we should now see that our Cloud Run URL will resolve to our PSC for Google APIs endpoint.
From Cloud Shell
gcloud compute ssh \ --zone "$zone" "consumer-client" \ --tunnel-through-iap \ --project $projectid
First we'll clear the DNS cache. Replace <Cloud-Run-ServiceURL> with the Service URL you noted previously.
From consumer-client VM
sudo resolvectl flush-caches curl <CloudRun-Loop-ServiceURL>
The curl should still work as previously seen.
From consumer-client VM
curl <CloudRun-Loop-ServiceURL>
Expected Output
Hello World!
From consumer-client VM
dig <CloudRun-Loop-ServiceURL>
The dig should show that our Cloud Run Loop service is now resolving to our PSC for Google APIs endpoint.
Sample Output
; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> https://cloudrun-loop-<projectnum>.<region>.run.app ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30179 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 65494 ;; QUESTION SECTION: ;https://cloudrun-loop-<projectnum>.<region>.run.app. IN A ;; ANSWER SECTION: https://cloudrun-loop-<projectnum>.<region>.run.app. 300 IN A 100.100.100.100 ;; Query time: 8 msec ;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP) ;; WHEN: Tue Mar 11 20:04:05 UTC 2025 ;; MSG SIZE rcvd: 99
SUCCESS!
18. Cleanup steps
Exit from VM instance
exit
From Cloud Shell
gcloud dns record-sets delete *.run.app --zone="cloudrun" --type=A -q gcloud dns managed-zones delete "cloudrun" -q gcloud compute instances delete consumer-client --zone=$zone --project=$projectid -q gcloud compute forwarding-rules delete psc4googapi --global -q gcloud compute addresses delete psc-goog-ep-ip --global -q gcloud run services delete cloudrun-loop --region=$region -q gcloud artifacts docker images delete $region-docker.pkg.dev/$projectid/cloud-run-source-deploy/cloudrun-loop -q gcloud compute forwarding-rules delete cloudrun-ep --region=$region -q gcloud compute addresses delete cloudrun-service-ip --region=$region -q gcloud compute network-firewall-policies rules delete 1000 --firewall-policy consumer-vpc-policy --global-firewall-policy -q gcloud compute network-firewall-policies associations delete --firewall-policy=consumer-vpc-policy --name=network-consumer-vpc --global-firewall-policy -q gcloud compute network-firewall-policies delete consumer-vpc-policy --global -q gcloud compute routers nats delete central-nat --router=central-cr --region=$region -q gcloud compute routers delete central-cr --region=$region -q gcloud compute networks subnets delete consumer-subnet --region $region -q
It's possible that running the next two commands could fail with "resource in use" errors. The Cloud Run docs say that sometimes Cloud Run takes 1 to 2 hours to release subnet resources after the Cloud Run service is deleted. If your deletion fails, skip these two commands and continue to the next section then return to this section to delete after some time.
From Cloud Shell
gcloud compute networks subnets delete cloudrun-egress --region $region -q gcloud compute networks delete consumer-vpc -q
From Cloud Shell
gcloud compute service-attachments delete cloudrun-attachment --region=$region -q gcloud compute instances delete producer-client --zone=$zone --project=$projectid -q gcloud compute forwarding-rules delete cloudrun-fr --region=$region -q gcloud compute target-http-proxies delete producer-http-proxy --region=$region -q gcloud compute url-maps delete producer-urlmap --region=$region -q gcloud compute backend-services delete cloudrun-producer-bes --region=$region -q gcloud compute network-endpoint-groups delete cloudrun-producer-neg --region=$region -q gcloud compute addresses delete cloudrun-ip --region=$region -q gcloud run services delete helloworld --region=$region -q gcloud artifacts docker images delete $region-docker.pkg.dev/$projectid/cloud-run-source-deploy/helloworld -q gcloud artifacts repositories delete cloud-run-source-deploy --location=$region -q gcloud compute network-firewall-policies rules delete 1000 --firewall-policy producer-vpc-policy --global-firewall-policy -q gcloud compute network-firewall-policies associations delete --firewall-policy=producer-vpc-policy --name=network-producer-vpc --global-firewall-policy -q gcloud compute network-firewall-policies delete producer-vpc-policy --global -q gcloud compute networks subnets delete lb-proxy-subnet --region $region -q gcloud compute networks subnets delete psc-nat-subnet --region $region -q gcloud compute networks subnets delete producer-subnet --region $region -q gcloud compute networks delete producer-vpc -q
19. Congratulations!
Congratulations for completing the codelab.
What we've covered
- Deploying basic apps on Cloud Run
- Cloud Run ingress and egress controls
- Deploying Cloud Run through an Internal Application Load Balancer with a Serverless NEG
- Setting up a PSC Producer Service through a Service Attachment
- Deploying PSC Endpoints