Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

Integrate Online Boutique with Spanner

By default the cartservice stores its data in an in-cluster Redis database. Using a fully managed database service outside your GKE cluster (such as Google Cloud Spanner) could bring more resiliency and more security.

Provision a Spanner database

To provision a Spanner instance you can follow the following instructions:

gcloud services enable spanner.googleapis.com

SPANNER_REGION_CONFIG="<your-spanner-region-config-name>" # e.g. "regional-us-east5"
SPANNER_INSTANCE_NAME=onlineboutique

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

Note: With latest version of gcloud we are creating a free Spanner instance.

To provision a Spanner database you can follow the following instructions:

SPANNER_DATABASE_NAME=carts

gcloud 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

Important note: Your GKE cluster should have Workload Identity enabled.

As a good practice, let's create a dedicated least privilege Google Service Account to allow the cartservice to communicate with the Spanner database:

PROJECT_ID=<your-project-id>
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=default
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} \
    --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 a Spanner database

To automate the deployment of Online Boutique integrated with Spanner you can leverage the following variation with Kustomize.

From the kustomize/ folder at the root level of this repository, execute these commands:

kustomize edit add component components/service-accounts
kustomize edit add component components/spanner

Note: this Kustomize component will also remove the redis-cart Deployment and Service not used anymore.

This will update the kustomize/kustomization.yaml file which could be similar to:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- base
components:
- components/service-accounts
- components/spanner

Update current Kustomize manifest to target this Spanner database.

sed -i "s/SPANNER_PROJECT/${PROJECT_ID}/g" components/spanner/kustomization.yaml
sed -i "s/SPANNER_INSTANCE/${SPANNER_INSTANCE_NAME}/g" components/spanner/kustomization.yaml
sed -i "s/SPANNER_DATABASE/${SPANNER_DATABASE_NAME}/g" components/spanner/kustomization.yaml
sed -i "s/SPANNER_DB_USER_GSA_ID/${SPANNER_DB_USER_GSA_ID}/g" components/spanner/kustomization.yaml

You can locally render these manifests by running kubectl kustomize . as well as deploying them by running kubectl apply -k ..

Note on Spanner connection environment variables

The following environment variables will be used by the cartservice, if present:

  • SPANNER_INSTANCE: defaults to onlineboutique, unless specified.
  • SPANNER_DATABASE: defaults to carts, unless specified.
  • SPANNER_CONNECTION_STRING: defaults to projects/${SPANNER_PROJECT}/instances/${SPANNER_INSTANCE}/databases/${SPANNER_DATABASE}. If this variable is defined explicitly, all other environment variables will be ignored.

Resources