Use Google Cloud Spanner with the Online Boutique sample

Mathieu Benoit
Google Cloud - Community
4 min readOct 18, 2022

Updated on April 1st, 2024 with the new way to configure Workload Identity with GKE workload.

Updated on December 8th, 2022 with the deployment of Online Boutique via its Helm chart.

By default the cartservice of the Online Boutique sample stores its data in an in-cluster Redis database. However, using a fully managed database service outside your Google Kubernetes Engine (GKE) cluster such as Memorystore (Redis) could bring more resiliency and more security.

Since the recent v0.4.0 version, the Online Boutique sample can now store its data in Google Cloud Spanner.

Cloud Spanner is a fully managed relational database with unlimited scale, strong consistency, and up to 99.999% availability.

In this tutorial, let’s see how you can connect the Online Boutique sample to Google Cloud Spanner.

Objectives

  • Create a Google Kubernetes Engine (GKE) cluster with Workload Identity
  • Provision a Spanner database with a free Spanner instance
  • Grant the cartservice’s service account access to the Spanner database with a least privilege role assignment via Workload Identity
  • Deploy the Online Boutique sample connected to the Spanner database with its Helm chart

Costs

This tutorial uses billable components of Google Cloud, including the following:

Use the pricing calculator to generate a cost estimate based on your projected usage.

Before you begin

This guide assumes that you have owner IAM permissions for your Google Cloud project. In production, you do not require owner permission.

  1. Select or create a Google Cloud project.
  2. Verify that billing is enabled for your project.

Set up your environment

Initialize the common variables used throughout this tutorial:

PROJECT_ID=FIXME-WITH-YOUR-PROJECT-ID
REGION=us-east5
ZONE=us-east5-a

To avoid repeating the --project in the commands throughout this tutorial, let’s set the current project and get the associated project number:

gcloud config set project ${PROJECT_ID}PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} \
--format='get(projectNumber)')

Enable the required APIs in your project

Enable the required APIs in your project:

gcloud services enable \
spanner.googleapis.com \
container.googleapis.com

Create a GKE cluster

Create a GKE cluster with Workload Identity enabled:

CLUSTER=spanner-with-onlineboutique
gcloud container clusters create ${CLUSTER} \
--zone ${ZONE} \
--machine-type=e2-standard-4 \
--num-nodes 4 \
--workload-pool ${PROJECT_ID}.svc.id.goog

Provision a Spanner database

Provision the Spanner instance:

SPANNER_REGION_CONFIG=regional-${REGION}
SPANNER_INSTANCE_NAME=onlineboutique
gcloud spanner instances create ${SPANNER_INSTANCE_NAME} \
--description="online boutique shopping cart" \
--instance-type free-instance \
--config ${SPANNER_REGION_CONFIG}

Notes: with the latest version of gcloud we are able to provision a free Spanner instance.

Provision the Spanner database:

SPANNER_DATABASE_NAME=cartsgcloud spanner databases create ${SPANNER_DATABASE_NAME} \
--instance ${SPANNER_INSTANCE_NAME} \
--database-dialect GOOGLE_STANDARD_SQL \
--ddl "CREATE TABLE CartItems (userId STRING(1024), productId STRING(1024), quantity INT64) PRIMARY KEY (userId, productId); CREATE INDEX CartItemsByUserId ON CartItems(userId);"

Grant the cartservice’s service account access to the Spanner database

Grant access to the cartservice’s Kubernetes Service Account to communicate with the Spanner database:

ONLINEBOUTIQUE_NAMESPACE=onlineboutique
CARTSERVICE_KSA_NAME=cartservice
gcloud spanner databases add-iam-policy-binding ${SPANNER_DATABASE_NAME} \
--instance ${SPANNER_INSTANCE_NAME} \
--member "principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/${ONLINEBOUTIQUE_NAMESPACE}/sa/${CARTSERVICE_KSA_NAME}" \
--role roles/spanner.databaseUser

Note: no need anymore to create a dedicated Google Service Account nor annotate the Kubernetes Service Account automatically, this is now simplified.

Deploy Online Boutique connected to the Spanner database

To automate the deployment of Online Boutique integrated with Spanner we will leverage its associated Helm chart:

SPANNER_CONNECTION_STRING=projects/${PROJECT_ID}/instances/${SPANNER_INSTANCE_NAME}/databases/${SPANNER_DATABASE_NAME}helm upgrade onlineboutique oci://us-docker.pkg.dev/online-boutique-ci/charts/onlineboutique \
--install \
--create-namespace \
-n onlineboutique \
--set cartDatabase.inClusterRedis.create=false \
--set cartDatabase.type=spanner \
--set cartDatabase.connectionString=${SPANNER_CONNECTION_STRING} \
--set serviceAccounts.create=true

After that all the apps have successfully been deployed, you could navigate to the Online Boutique website by clicking on the link below:

echo -n "http://" && kubectl get svc frontend-external -n ${ONLINEBOUTIQUE_NAMESPACE} -o json | jq -r '.status.loadBalancer.ingress[0].ip'

From the Online Boutique website, you can add some products in your shopping cart and then you can click on the link below to see all the data serialized in the Spanner database by you and the loadgenerator app:

echo -e "https://console.cloud.google.com/spanner/instances/${SPANNER_INSTANCE_NAME}/databases/${SPANNER_DATABASE_NAME}/tables/CartItems/details/data?project=${PROJECT_ID}"

And voilà! That’s how easy you can connect your Online Boutique sample to a Spanner database, congrats!

Cleaning up

To avoid incurring charges to your Google Cloud account, you can delete the resources used in this tutorial.

Delete the GKE cluster:

gcloud container clusters delete ${CLUSTER} \
--zone ${ZONE}

Delete the Spanner database:

gcloud spanner instances delete ${SPANNER_INSTANCE_NAME}

Conclusion

Having the database outside of your GKE cluster with a managed service can bring you more resiliency and security, and with this new Cloud Spanner option the Online Boutique will become more highly available. This setup allows complex scenarios like having your apps spread across multiple clusters, etc.

Thanks to the original implementation of Daniel Quinlan, this new Spanner option is now available to everyone in the Online Boutique GitHub repository, feel free to either give the Helm chart or the Kustomize overlay a try!

Happy sailing, cheers!

Originally posted at mathieu-benoit.github.io.

--

--

Mathieu Benoit
Google Cloud - Community

Customer Success Engineer at Humanitec | CNCF Ambassador | GDE Cloud