Use Google Cloud Spanner with the Online Boutique sample

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.

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
  • 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:

gcloud config set project ${PROJECT_ID}

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

Create a dedicated least privilege Google Service Account to allow the cartservice’s Kubernetes Service Account to communicate with the Spanner database:

SPANNER_DB_USER_GSA_NAME=spanner-db-user-sa
SPANNER_DB_USER_GSA_ID=${SPANNER_DB_USER_GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
ONLINEBOUTIQUE_NAMESPACE=onlineboutique
CARTSERVICE_KSA_NAME=cartservice
gcloud iam service-accounts create ${SPANNER_DB_USER_GSA_NAME} \
--display-name=${SPANNER_DB_USER_GSA_NAME}
gcloud spanner databases add-iam-policy-binding ${SPANNER_DATABASE_NAME} \
--instance ${SPANNER_INSTANCE_NAME} \
--member "serviceAccount:${SPANNER_DB_USER_GSA_ID}" \
--role roles/spanner.databaseUser
gcloud iam service-accounts add-iam-policy-binding ${SPANNER_DB_USER_GSA_ID} \
--member "serviceAccount:${PROJECT_ID}.svc.id.goog[${ONLINEBOUTIQUE_NAMESPACE}/${CARTSERVICE_KSA_NAME}]" \
--role roles/iam.workloadIdentityUser

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 \
--set serviceAccounts.annotationsOnlyForCartservice=true \
--set "serviceAccounts.annotations.iam\.gke\.io/gcp-service-account=${SPANNER_DB_USER_GSA_ID}"

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.

--

--

A collection of technical articles and blogs published or curated by Google Cloud Developer Advocates. The views expressed are those of the authors and don't necessarily reflect those of Google.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store