This is a fork of the official Google Hipster Shop demo that replaces the Redis backend with a YugabyteDB. The application is a web-based e-commerce app called “Hipster Shop” where users can browse items, add them to the cart, and purchase them.
Google uses this application to demonstrate use of technologies like Kubernetes/GKE, Istio, Stackdriver, gRPC and OpenCensus. This application works on any Kubernetes cluster (such as a local one), as well as Google Kubernetes Engine. It’s easy to deploy with little to no configuration.
If you’re using this demo, please ★Star this repository to show your interest!
Home Page | Checkout Screen |
---|---|
Hipster Shop is composed of many microservices written in different languages that talk to each other over gRPC.
Find Protocol Buffers Descriptions at the ./pb
directory.
Service | Language | Description |
---|---|---|
frontend | Go | Exposes an HTTP server to serve the website. Does not require signup/login and generates session IDs for all users automatically. |
cartservice | C# | Stores the items in the user's shopping cart in YugabyteDB and retrieves it. |
productcatalogservice | Go | Provides the list of products from a JSON file and ability to search products and get individual products. |
currencyservice | Node.js | Converts one money amount to another currency. Uses real values fetched from European Central Bank. It's the highest QPS service. |
paymentservice | Node.js | Charges the given credit card info (mock) with the given amount and returns a transaction ID. |
shippingservice | Go | Gives shipping cost estimates based on the shopping cart. Ships items to the given address (mock) |
emailservice | Python | Sends users an order confirmation email (mock). |
checkoutservice | Go | Retrieves user cart, prepares order and orchestrates the payment, shipping and the email notification. |
recommendationservice | Python | Recommends other products based on what's given in the cart. |
adservice | Java | Provides text ads based on given context words. |
loadgenerator | Python/Locust | Continuously sends requests imitating realistic user shopping flows to the frontend. |
- Kubernetes/GKE: The app is designed to run on Kubernetes (both locally on "Docker for Desktop", as well as on the cloud with GKE).
- gRPC: Microservices use a high volume of gRPC calls to communicate to each other.
- Istio: Application works on Istio service mesh *permissive mode only at this time with yugabyte.
- OpenCensus Tracing: Most services are instrumented using OpenCensus trace interceptors for gRPC/HTTP.
- Stackdriver APM: Many services are instrumented with Profiling, Tracing and Debugging. In addition to these, using Istio enables features like Request/Response Metrics and Context Graph out of the box. When it is running out of Google Cloud, this code path remains inactive.
- Skaffold: Application is deployed to Kubernetes with a single command using Skaffold.
- Synthetic Load Generation: The application demo comes with a background job that creates realistic usage patterns on the website using Locust load generator.
You can deploy the microservices-demo application stack and YugabyteDB to any Kubernetes environment. For reference, install steps will be provided for GKE.
-
Running on Google Kubernetes Engine (GKE)” (~30 minutes) You will build, upload and deploy the container images to a Kubernetes cluster on Google Cloud.
-
Install tools to run a Kubernetes cluster locally:
- kubectl (can be installed via
gcloud components install kubectl
) - Docker for Desktop (Mac/Windows): It provides Kubernetes support as noted here.
- skaffold (ensure version ≥v0.20)
- Helm v3 (https://helm.sh/docs/intro/install/)
- YugabyteDB install local CLI and add to PATH (https://docs.yugabyte.com/latest/quick-start/install/)
wget https://downloads.yugabyte.com/yugabyte-2.0.10.0-darwin.tar.gz tar xvfz yugabyte-2.0.10.0-darwin.tar.gz PATH=PATH:yugabyte-2.0.10.0/bin
- kubectl (can be installed via
-
Create a Google Kubernetes Engine cluster and make sure
kubectl
is pointing to the cluster.gcloud services enable container.googleapis.com
gcloud container clusters create demo --enable-autoupgrade \ --enable-autoscaling --min-nodes=3 --max-nodes=10 --num-nodes=5 --zone=us-central1-a
kubectl get nodes
-
Prep your cluster and deploy a YugabyteDB cluster via Helm
kubectl create namespace yb-demo kubectl config set-context --namespace yb-demo --current helm repo add yugabytedb https://charts.yugabyte.com helm repo update helm search repo yugabytedb/yugabyte helm install yb-demo yugabytedb/yugabyte -f https://raw.githubusercontent.com/YugaByte/charts/master/stable/yugabyte/expose-all.yaml --version 2.0.9 --wait
-
Prep your YugabyteDB instance with the following DDL
bin/ysqlsh -h YOUR_YSQL_IP # default database & user = yugabyte \l CREATE DATABASE sample; \c sample CREATE TABLE carts(id serial PRIMARY KEY, userid VARCHAR(50), productid VARCHAR(50), quantity integer);
-
Enable Google Container Registry (GCR) on your GCP project and configure the
docker
CLI to authenticate to GCR:gcloud services enable containerregistry.googleapis.com
gcloud auth configure-docker -q
-
In the root of this repository, run
skaffold run --default-repo=gcr.io/[PROJECT_ID]
, where [PROJECT_ID] is your GCP project ID.This command:
- builds the container images
- pushes them to GCR
- applies the
./kubernetes-manifests
deploying the application to Kubernetes.
Troubleshooting: If you get "No space left on device" error on Google Cloud Shell, you can build the images on Google Cloud Build: Enable the Cloud Build API, then run
skaffold run -p gcb --default-repo=gcr.io/[PROJECT_ID]
instead. -
Find the IP address of your application, then visit the application on your browser to confirm installation.
kubectl get service frontend-external
Troubleshooting: A Kubernetes bug (will be fixed in 1.12) combined with a Skaffold bug causes load balancer to not to work even after getting an IP address. If you are seeing this, run
kubectl get service frontend-external -o=yaml | kubectl apply -f-
to trigger load balancer reconfiguration.
Note: you followed GKE deployment steps above, run
skaffold delete
first to delete what's deployed. Enabling Istio-on-GKE sidecar injection may not allow previous deployed versions to be re-deployed until it is disabled and removed.
-
Create a GKE cluster and deploy YugabyteDB (described in "Option 2").
-
Use Istio on GKE add-on to install Istio to your existing GKE cluster.
gcloud beta container clusters update demo \ --zone=us-central1-a \ --update-addons=Istio=ENABLED \ --istio-config=auth=MTLS_PERMISSIVE
NOTE: MTLS_STRICT is unsupported at this time. If you would like to enable
MTLS_STRICT
mode, you will need to update several manifest files:kubernetes-manifests/frontend.yaml
: delete "livenessProbe" and "readinessProbe" fields.kubernetes-manifests/loadgenerator.yaml
: delete "initContainers" field.
-
(Optional) Enable Stackdriver Tracing/Logging with Istio Stackdriver Adapter by following this guide. Work still needs to be done for Prometheus monitoring to update metrics here: https://cloud.google.com/istio/docs/istio-on-gke/installing
-
Install the automatic sidecar injection (annotate the
yb-demo
namespace with the label):kubectl label namespace yb-demo istio-injection=enabled
-
Apply the manifests in
./istio-manifests
directory. (This is required only once.)kubectl apply -f ./istio-manifests
-
Deploy the application with
skaffold run --default-repo=gcr.io/[PROJECT_ID]
. -
Run
kubectl get pods
to see pods are in a healthy and ready state. -
Find the IP address of your Istio gateway Ingress or Service, and visit the application.
INGRESS_HOST="$(kubectl -n istio-system get service istio-ingressgateway \ -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" echo "$INGRESS_HOST"
curl -v "http://$INGRESS_HOST"
If you've deployed the application with skaffold run
command, you can run
skaffold delete
to clean up the deployed resources.
If you've deployed the application with kubectl apply -f [...]
, you can
run kubectl delete -f [...]
with the same argument to clean up the deployed
resources.
This is given as an example deployment of Yugabyte in a microservices environment.