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.
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-instanceNote: 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);"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 instances add-iam-policy-binding ${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.workloadIdentityUserTo 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/spannerNote: 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/spannerUpdate 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.yamlYou can locally render these manifests by running kubectl kustomize . as well as deploying them by running kubectl apply -k ..
The following environment variables will be used by the cartservice, if present:
SPANNER_INSTANCE: defaults toonlineboutique, unless specified.SPANNER_DATABASE: defaults tocarts, unless specified.SPANNER_CONNECTION_STRING: defaults toprojects/${SPANNER_PROJECT}/instances/${SPANNER_INSTANCE}/databases/${SPANNER_DATABASE}. If this variable is defined explicitly, all other environment variables will be ignored.