About this codelab
1. Introduction
In this codelab you will learn how to deploy a Private Service Connection for AlloyDB and how to access the AlloyDB service using the deployed Private Service Connect.
You can get more information about Private Service Connect here.
Prerequisites
- A basic understanding of the Google Cloud Console
- Basic skills in command line interface and Google Cloud shell
What you'll learn
- How to deploy an AlloyDB cluster and instance
- How to deploy a Private Service Connect
- How to connect from a VM to a AlloyDB Instance via Private Service Connect
What you'll need
- A Google Cloud Account and Google Cloud Project
- A web browser such as Chrome
2. 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 update it at any time.
- The Project ID must be 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 the Project ID (it is typically identified as
PROJECT_ID
). If you don't like the generated ID, you may generate another random one. Alternatively, you can try your own and see if it's available. It cannot be changed after this step and will remain 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.
Caution: A project ID is globally unique and can't be used by anyone else after you've selected it. You are the only user of that ID. Even if a project is deleted, the ID can't be used again
- 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.
3. Before you begin
Enable API
Please be aware that some resources you enable are going to incur some cost if you are not using the promotional tier. In normal circumstances if all the resources are destroyed upon completion of the lab the cost of all resources would not exceed $5. We recommend checking your billing and making sure the exercise is acceptable for you.
Inside Cloud Shell, make sure that your project ID is setup:
Usually the project ID is shown in parentheses in the command prompt in the cloud shell as it is shown in the picture:
gcloud config set project [YOUR-PROJECT-ID]
A window will pop up which asks for Cloud Shell Authorization. Please click on Authorize
Then set the PROJECT_ID environment variable to your Google Cloud project ID:
PROJECT_ID=$(gcloud config get-value project)
Set the REGION and ZONE environment variable to your preferred region and zone:
REGION=europe-west4
ZONE=europe-west4-a
Enable all necessary services:
gcloud services enable compute.googleapis.com \
alloydb.googleapis.com \
dns.googleapis.com \
servicenetworking.googleapis.com \
iam.googleapis.com
Expected output:
student@cloudshell:~ (psc-alloydb-test)$ gcloud services enable compute.googleapis.com \ alloydb.googleapis.com \ dns.googleapis.com \ servicenetworking.googleapis.com \ iam.googleapis.com Operation "operations/acat.p2-981315804223-09b8112e-2c2c-4a30-9018-c27e6a06c199" finished successfully.
4. Deploy an AlloyDB Cluster
In the Cloud Shell you can use the command line to create a new AlloyDB cluster with Private Service Connect enabled:
gcloud alloydb clusters create alloydb-cluster-01 \
--password=changeme \
--region=$REGION \
--project=$PROJECT_ID \
--enable-private-service-connect
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud alloydb clusters create alloydb-cluster-01 \ --password=changeme \ --region=$REGION \ --project=$PROJECT_ID \ --enable-private-service-connect Operation ID: operation-1739367760591-62df21d80fae8-9aa7c3ab-64604bae Creating cluster...done.
Now create an AlloyDB primary instance:
gcloud alloydb instances create alloydb-instance-01 \
--instance-type=PRIMARY \
--cpu-count=2 \
--availability-type=ZONAL \
--region=$REGION \
--cluster=alloydb-cluster-01 \
--project=$PROJECT_ID \
--allowed-psc-projects=$PROJECT_ID
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud alloydb instances create alloydb-instance-01 \ --instance-type=PRIMARY \ --cpu-count=2 \ --availability-type=ZONAL \ --region=$REGION \ --cluster=alloydb-cluster-01 \ --project=$PROJECT_ID \ --allowed-psc-projects=$PROJECT_ID Operation ID: operation-1739368280521-62df23c7e7bda-7e52597c-8c7d9d79 Creating instance...done.
5. Setup Private Service Connect
For the following network related tasks the assumption is that a VPC named default is in place.
Reserve an internal IP address
Find the VPC subnet CIDR range in the GCP region referred to in the environment variable REGION and choose a free IP address in this CIDR range for the Privat Service Connect endpoint:
gcloud compute networks subnets describe default \
--region=$REGION --project=$PROJECT_ID \
--format="value(ipCidrRange)"
Expected Output
student@cloudshell:~ (psc-cloud-sql-test)$ gcloud compute networks subnets describe default \ --region=$REGION --project=$PROJECT_ID \ --format="value(ipCidrRange)" 10.164.0.0/20
Reserve an internal IP address for the Private Service Connect endpoint in the derived VPC subnet CIDR range above:
gcloud compute addresses create alloydb-psc \
--project=$PROJECT_ID \
--region=$REGION \
--subnet=default \
--addresses=10.164.0.10
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute addresses create alloydb-psc \ --project=$PROJECT_ID \ --region=$REGION \ --subnet=default \ --addresses=10.164.0.10 Created [https://www.googleapis.com/compute/v1/projects/psc-alloydb-test/regions/europe-west4/addresses/alloydb-psc].
Verify that the internal IP address is reserved and that the status RESERVED appears for the IP address.
gcloud compute addresses list --project=$PROJECT_ID \
--filter="name=alloydb-psc"
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute addresses list --project=$PROJECT_ID \ --filter="name=alloydb-psc" NAME: alloydb-psc ADDRESS/RANGE: 10.164.0.10 TYPE: INTERNAL PURPOSE: GCE_ENDPOINT NETWORK: REGION: europe-west4 SUBNET: default STATUS: RESERVED
Get the service attachment URI
After creating an AlloyDB instance with Private Service Connect enabled, get the service attachment URI and use it to create the Private Service Connect endpoint with the reserved internal IP address above.
gcloud alloydb instances describe alloydb-instance-01 \
--cluster=alloydb-cluster-01 \
--region="$REGION" \
--format="value(pscInstanceConfig.serviceAttachmentLink)" | \
sed 's|.*/projects/|projects/|'
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud alloydb instances describe alloydb-instance-01 \ --cluster=alloydb-cluster-01 \ --region="$REGION" \ --format="value(pscInstanceConfig.serviceAttachmentLink)" | \ sed 's|.*/projects/|projects/|' projects/se8c7a64d55e2e1f9p-tp/regions/europe-west4/serviceAttachments/alloydb-69f67b56-9fa-alloydb-instance-sa
Create the Private Service Connect
Create the Private Service Connect endpoint and point it to the AlloyDB service attachment URI:
gcloud compute forwarding-rules create alloydb-psc-ep \
--address=alloydb-psc \
--project=$PROJECT_ID \
--region=$REGION \
--network=default \
--target-service-attachment=projects/se8c7a64d55e2e1f9p-tp/regions/europe-west4/serviceAttachments/alloydb-69f67b56-9fa-alloydb-instance-sa \
--allow-psc-global-access
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute forwarding-rules create alloydb-psc-ep \ --address=alloydb-psc \ --project=$PROJECT_ID \ --region=$REGION \ --network=default \ --target-service-attachment=projects/se8c7a64d55e2e1f9p-tp/regions/europe-west4/serviceAttachments/alloydb-69f67b56-9fa-alloydb-instance-sa \ --allow-psc-global-access Created [https://www.googleapis.com/compute/v1/projects/psc-alloydb-test/regions/europe-west4/forwardingRules/alloydb-psc-ep].
Verify that the endpoint can connect to the service attachment:
gcloud compute forwarding-rules describe alloydb-psc-ep \
--project=$PROJECT_ID \
--region=$REGION \
--format="value(pscConnectionStatus)"
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute forwarding-rules describe alloydb-psc-ep \ --project=$PROJECT_ID \ --region=$REGION \ --format="value(pscConnectionStatus)" ACCEPTED
Configure a DNS managed zone
To add the suggested DNS name for the AlloyDB instance it is best to create a private DNS zone in the corresponding VPC network:
gcloud dns managed-zones create alloydb-dns \
--project=$PROJECT_ID \
--description="DNS zone for the AlloyDB instances" --dns-name=$REGION.alloydb-psc.goog. \
--networks=default \
--visibility=private
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud dns managed-zones create alloydb-dns \ --project=$PROJECT_ID \ --description="DNS zone for the AlloyDB instances" --dns-name=$REGION.alloydb-psc.goog. \ --networks=default \ --visibility=private Created [https://dns.googleapis.com/dns/v1/projects/psc-alloydb-test/managedZones/alloydb-dns].
Add a DNS record for the Private Service Connect
Get the suggested DNS record for the AlloyDB instance:
gcloud alloydb instances describe alloydb-instance-01 \
--cluster=alloydb-cluster-01 --region=$REGION --project=$PROJECT_ID \
--format="value(pscInstanceConfig.pscDnsName)"
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud alloydb instances describe alloydb-instance-01 \ --cluster=alloydb-cluster-01 --region=$REGION --project=$PROJECT_ID \ --format="value(pscInstanceConfig.pscDnsName)" 69f67b56-9fa2-4480-89f6-3f1a38ee51cb.6a495301-4802-4ec1-bb9b-69b57d2616ec.europe-west4.alloydb-psc.goog.
Add the suggested DNS record to the DNS managed zone
gcloud dns record-sets create 69f67b56-9fa2-4480-89f6-3f1a38ee51cb.6a495301-4802-4ec1-bb9b-69b57d2616ec.europe-west4.alloydb-psc.goog. \
--project=$PROJECT_ID \
--type=A \
--rrdatas=10.164.0.10 \
--zone=alloydb-dns
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud dns record-sets create 69f67b56-9fa2-4480-89f6-3f1a38ee51cb.6a495301-4802-4ec1-bb9b-69b57d2616ec.europe-west4.alloydb-psc.goog. \ --project=$PROJECT_ID \ --type=A \ --rrdatas=10.164.0.10 \ --zone=alloydb-dns NAME: 69f67b56-9fa2-4480-89f6-3f1a38ee51cb.6a495301-4802-4ec1-bb9b-69b57d2616ec.europe-west4.alloydb-psc.goog. TYPE: A TTL: 0 DATA: 10.164.0.10
6. Prepare Google Compute Engine Virtual Machine
Deploy Google Compute Engine Virtual Machine
The Virtual Machine (VM) will be used to connect to the AlloyDB instance.
gcloud compute instances create alloydb-client \
--zone=$ZONE \
--create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \
--scopes=https://www.googleapis.com/auth/cloud-platform \
--shielded-secure-boot \
--network-interface=no-address
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute instances create alloydb-client \ --zone=$ZONE \ --create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --network-interface=no-address Created [https://www.googleapis.com/compute/v1/projects/psc-alloydb-test/zones/europe-west4-a/instances/alloydb-client]. NAME: alloydb-client ZONE: europe-west4-a MACHINE_TYPE: n1-standard-1 PREEMPTIBLE: INTERNAL_IP: 10.164.0.2 EXTERNAL_IP: STATUS: RUNNING
Install Postgres Client
Create a Cloud NAT for outbound traffic to the internet that the VM is able to access the Linux repositories:
gcloud compute routers create cloud-nat-router \
--network=default \
--region=$REGION
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute routers create cloud-nat-router \ --network=default \ --region=$REGION Creating router [cloud-nat-router]...done. NAME: cloud-nat-router REGION: europe-west4 NETWORK: default
gcloud compute routers nats create cloud-nat \
--router=cloud-nat-router \
--region=$REGION \
--nat-all-subnet-ip-ranges \
--auto-allocate-nat-external-ips
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute routers nats create cloud-nat \ --router=cloud-nat-router \ --region=$REGION \ --nat-all-subnet-ip-ranges \ --auto-allocate-nat-external-ips Creating NAT [cloud-nat] in router [cloud-nat-router]...done.
Install the PostgreSQL client software on the deployed VM
Connect to the VM:
gcloud compute ssh --zone $ZONE "alloydb-client" --tunnel-through-iap --project $PROJECT_ID
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute ssh --zone $ZONE "alloydb-client" --tunnel-through-iap --project $PROJECT_ID WARNING: To increase the performance of the tunnel, consider installing NumPy. For instructions, please see https://cloud.google.com/iap/docs/using-tcp-forwarding#increasing_the_tcp_upload_bandwidth Warning: Permanently added 'compute.3358765012415130370' (ED25519) to the list of known hosts. Linux alloydb-client 6.1.0-29-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.123-1 (2025-01-02) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Creating directory '/home/student_tampferl_altostrat_com'.
Install the software running command inside the VM:
sudo apt-get update
sudo apt-get install --yes postgresql-client
Expected Output
sudo apt-get update sudo apt-get install --yes postgresql-client Get:1 file:/etc/apt/mirrors/debian.list Mirrorlist [30 B] Get:5 file:/etc/apt/mirrors/debian-security.list Mirrorlist [39 B] Get:7 https://packages.cloud.google.com/apt google-compute-engine-bookworm-stable InRelease [1321 B] Get:2 https://deb.debian.org/debian bookworm InRelease [151 kB] Get:3 https://deb.debian.org/debian bookworm-updates InRelease [55.4 kB] Get:4 https://deb.debian.org/debian bookworm-backports InRelease [59.0 kB] ...redacted... update-alternatives: using /usr/share/postgresql/15/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode Setting up postgresql-client (15+248) ... Processing triggers for man-db (2.11.2-2) ... Processing triggers for libc-bin (2.36-9+deb12u9) ...
7. Connect to AlloyDB for Postgres Instance via Private Service Connect
Connect to the Instance
psql "dbname=postgres user=postgres host=69f67b56-9fa2-4480-89f6-3f1a38ee51cb.6a495301-4802-4ec1-bb9b-69b57d2616ec.europe-west4.alloydb-psc.goog."
Expected Output
student_tampferl_altostrat_com@alloydb-client:~$ psql "dbname=postgres user=postgres host=69f67b56-9fa2-4480-89f6-3f1a38ee51cb.6a495301-4802-4ec1-bb9b-69b57d2616ec.europe-west4.alloydb-psc.goog." Password for user postgres: psql (15.10 (Debian 15.10-0+deb12u1), server 15.7) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off) Type "help" for help. postgres=>
Create and test database
Create a database
CREATE DATABASE company;
Expected Output
postgres=> CREATE DATABASE company; CREATE DATABASE postgres=>
List all databases
\l
Expected Output
Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges -----------------+------------------+----------+---------+-------+------------+-----------------+--------------------------------------- alloydbadmin | alloydbadmin | UTF8 | C | C | und-x-icu | icu | alloydbmetadata | alloydbadmin | UTF8 | C | C | und-x-icu | icu | alloydbadmin=CTc/alloydbadmin + | | | | | | | alloydbmetadata=c/alloydbadmin company | postgres | UTF8 | C | C | und-x-icu | icu | postgres | alloydbsuperuser | UTF8 | C | C | und-x-icu | icu | template0 | alloydbadmin | UTF8 | C | C | und-x-icu | icu | =c/alloydbadmin + | | | | | | | alloydbadmin=CTc/alloydbadmin template1 | alloydbsuperuser | UTF8 | C | C | und-x-icu | icu | =c/alloydbsuperuser + | | | | | | | alloydbsuperuser=CTc/alloydbsuperuser (6 rows)
Connect to employees database
\c company
Expected Output
postgres=> \c company psql (15.10 (Debian 15.10-0+deb12u1), server 15.7) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off) You are now connected to database "company" as user "postgres". company=>
Create a table in the company database
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
first VARCHAR(255) NOT NULL,
last VARCHAR(255) NOT NULL,
salary DECIMAL (10, 2)
);
Expected Output
company=> CREATE TABLE employees ( id SERIAL PRIMARY KEY, first VARCHAR(255) NOT NULL, last VARCHAR(255) NOT NULL, salary DECIMAL (10, 2) ); CREATE TABLE
Insert data into the table employees of company database
INSERT INTO employees (first, last, salary) VALUES
('Max', 'Mustermann', 5000.00),
('Anna', 'Schmidt', 7000.00),
('Peter', 'Mayer', 6000.00);
Expected Output
company=> INSERT INTO employees (first, last, salary) VALUES ('Max', 'Mustermann', 5000.00), ('Anna', 'Schmidt', 7000.00), ('Peter', 'Mayer', 6000.00); INSERT 0 3 company=>
Query employees table
SELECT * FROM employees;
Expected Output
company=> SELECT * FROM employees; id | first | last | salary ----+-------+------------+--------- 1 | Max | Mustermann | 5000.00 2 | Anna | Schmidt | 7000.00 3 | Peter | Mayer | 6000.00 (3 rows) company=>
Exit the Postgres database and the VM and return to Cloud Shell:
\q
exit
Expected Output
company=> \q student_tampferl_altostrat_com@alloydb-client:~$ exit logout Connection to compute.3358765012415130370 closed. student@cloudshell:~ (psc-alloydb-test)$
8. Clean up environment
Destroy all Google Cloud resources in the project when you are done with the lab.
Delete AlloyDB cluster
In the Cloud Shell delete the AlloyDB for Postgres cluster:
gcloud alloydb clusters delete alloydb-cluster-01 --region=$REGION --force --quiet
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud alloydb clusters delete alloydb-cluster-01 --region=$REGION --force --quiet Operation ID: operation-1739488287386-62e0e2d75ead0-f8ffd91f-9c0f56c1 Deleting cluster...done.
Delete Google Compute Engine Virtual Machine
In the Cloud Shell delete the VM:
gcloud compute instances delete alloydb-client \
--zone=$ZONE \
--quiet
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute instances delete alloydb-client \ --zone=$ZONE \ --quiet Deleted [https://www.googleapis.com/compute/v1/projects/psc-alloydb-test/zones/europe-west4-a/instances/alloydb-client].
Delete network components
Delete network related components: Cloud NAT, Cloud Router, Private Service Connect Endpoint, reserved internal IP address, DNS record and DNS managed zone.
Delete Cloud NAT:
gcloud compute routers nats delete cloud-nat \
--router=cloud-nat-router \
--region=$REGION \
--quiet
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute routers nats delete cloud-nat \ --router=cloud-nat-router \ --region=$REGION \ --quiet Updated [https://www.googleapis.com/compute/v1/projects/psc-alloydb-test/regions/europe-west4/routers/cloud-nat-router].
Delete Cloud Router:
gcloud compute routers delete cloud-nat-router \
--region=$REGION \
--quiet
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute routers delete cloud-nat-router \ --region=$REGION \ --quiet Deleted [https://www.googleapis.com/compute/v1/projects/psc-alloydb-test/regions/europe-west4/routers/cloud-nat-router].
Delete Private Service Connect Endpoint:
gcloud compute forwarding-rules delete alloydb-psc-ep \
--project=$PROJECT_ID \
--region=$REGION \
--quiet
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute forwarding-rules delete alloydb-psc-ep \ --project=$PROJECT_ID \ --region=$REGION \ --quiet Deleted [https://www.googleapis.com/compute/v1/projects/psc-alloydb-test/regions/europe-west4/forwardingRules/alloydb-psc-ep].
Release reserved internal IP address::
gcloud compute addresses delete alloydb-psc \
--project=$PROJECT_ID \
--region=$REGION \
--quiet
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud compute addresses delete alloydb-psc \ --project=$PROJECT_ID \ --region=$REGION \ --quiet Deleted [https://www.googleapis.com/compute/v1/projects/psc-alloydb-test/regions/europe-west4/addresses/alloydb-psc].
Delete DNS record:
gcloud dns record-sets delete 69f67b56-9fa2-4480-89f6-3f1a38ee51cb.6a495301-4802-4ec1-bb9b-69b57d2616ec.europe-west4.alloydb-psc.goog. \
--project=$PROJECT_ID \
--type=A \
--zone=alloydb-dns
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud dns record-sets delete 69f67b56-9fa2-4480-89f6-3f1a38ee51cb.6a495301-4802-4ec1-bb9b-69b57d2616ec.europe-west4.alloydb-psc.goog. \ --project=$PROJECT_ID \ --type=A \ --zone=alloydb-dns Deleted [https://dns.googleapis.com/dns/v1/projects/psc-alloydb-test/managedZones/alloydb-dns/rrsets/69f67b56-9fa2-4480-89f6-3f1a38ee51cb.6a495301-4802-4ec1-bb9b-69b57d2616ec.europe-west4.alloydb-psc.goog./A].
Delete DNS managed zone:
gcloud dns managed-zones delete alloydb-dns \
--project=$PROJECT_ID \
--quiet
Expected Output
student@cloudshell:~ (psc-alloydb-test)$ gcloud dns managed-zones delete alloydb-dns \ --project=$PROJECT_ID \ --quiet Deleted [https://dns.googleapis.com/dns/v1/projects/psc-alloydb-test/managedZones/alloydb-dns].
9. Congratulations
Congratulations for completing the codelab.
What we've covered
- How to deploy a AlloyDB cluster and instance
- How to deploy a Private Service Connect
- How to connect from a VM to a AlloyDB Instance via Private Service Connect