# Service mesh sample application - Bookinfo
# Bookinfo application overview
The example deploys a sample application composed of four separate microservices used to demonstrate various Istio features. The application displays information about a book, similar to a single catalog entry of an online book store. Displayed on the page is a description of the book, book details (ISBN, number of pages, and so on), and a few book reviews.
The Bookinfo application is broken into four separate microservices:
- productpage: The productpage microservice calls the details and reviews microservices to populate the page.
- details: The details microservice contains book information.
- reviews: The reviews microservice contains book reviews. It also calls the ratings microservice.
- ratings: The ratings microservice contains book ranking information that accompanies a book review.
There are 3 versions of the reviews microservice:
- Version
v1doesn’t call the ratings service. - Version
v2calls the ratings service, and displays each rating as 1 to 5 black stars. - Version
v3calls the ratings service, and displays each rating as 1 to 5 red stars.
The end-to-end architecture of the application is shown below.

Figure. Bookinfo application
# Deploy the Bookinfo application
# Connect to your admin workstation
Connect to your admin workstation, using the appropriate IP address:
ssh -i /root/anthos_secrets/vsphere_workstation ubuntu@10.15.155.200
# Configure KUBECONFIG
Configure KUBECONFIG, using the appropriate cluster name:
export KUBECONFIG=~/kubeconfigs/gmcg-gke-usercluster-1-kubeconfig
# Create namespace
Create a namespace for the application:
kubectl create namespace bookinfo
namespace/bookinfo created
# Enable Istio injection for namespace
If you have already deployed Service Mesh to the user cluster,
you can simply use kubectl to enable Istio injection for the namespace:
kubectl label namespace bookinfo istio-injection=enabled
Otherwise, you need to configure and run the Service Mesh playbook. To summarize, you need to set anthos_service_mesh_enable: true and add the 'bookinfo' namespace to the list of enabled namespaces in the all.yml configuration file:
gke_cluster_config:
- name: 'user-cluster-1'
type: 'user'
...
anthos_service_mesh_enable: true
anthos_service_mesh_externalIP: '10.15.158.55'
anthos_service_mesh_sidecar_enable: ['bookinfo']
Run the service_mesh.yml playbook:
ansible-playbook playbooks/service_mesh.yml
# Check that Istio injection has been enabled
Check that the namespace has been annotated correctly with istio-injection: enabled.
kubectl get namespace bookinfo -o yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: "2020-06-17T15:53:30Z"
labels:
istio-injection: enabled
name: bookinfo
resourceVersion: "661536"
selfLink: /api/v1/namespaces/bookinfo
uid: 403dadce-c754-410f-a2ee-39374bedcfe8
spec:
finalizers:
- kubernetes
status:
phase: Active
# Deploying the Bookinfo application
Download the manifest for deploying the application:
curl https://raw.githubusercontent.com/istio/istio/release-1.6/samples/bookinfo/platform/kube/bookinfo.yaml > bookinfo.yaml
Deploy the application in the namepsace:
kubectl -n bookinfo apply -f bookinfo.yaml
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created
View the resources deployed:
kubectl -n bookinfo get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
details-v1 1/1 1 1 5m58s
productpage-v1 1/1 1 1 5m58s
ratings-v1 1/1 1 1 5m58s
reviews-v1 1/1 1 1 5m58s
reviews-v2 1/1 1 1 5m58s
reviews-v3 1/1 1 1 5m58s
kubectl -n bookinfo get pods
NAME READY STATUS RESTARTS AGE
details-v1-7f6df6f54-cxkdx 2/2 Running 0 6m29s
productpage-v1-69886c8bcb-4g5q9 2/2 Running 0 6m29s
ratings-v1-6665bbd4db-srbmt 2/2 Running 0 6m29s
reviews-v1-7fd87d96bd-74z49 2/2 Running 0 6m29s
reviews-v2-55d9bfb6d8-2gmj5 2/2 Running 0 6m29s
reviews-v3-5776c54c64-rn86f 2/2 Running 0 6m29s
kubectl -n bookinfo get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 10.104.35.78 <none> 9080/TCP 6m54s
productpage ClusterIP 10.96.108.148 <none> 9080/TCP 6m54s
ratings ClusterIP 10.103.184.167 <none> 9080/TCP 6m54s
reviews ClusterIP 10.96.117.99 <none> 9080/TCP 6m54s
Notice that there is a sidecar container istio-proxy in each pod:
kubectl -n bookinfo describe pod productpage
Name: productpage-v1-69886c8bcb-4g5q9
Namespace: bookinfo
Priority: 0
Node: gmcg-gke-user1-node2/10.15.155.122
Start Time: Wed, 17 Jun 2020 16:00:36 +0000
Labels: app=productpage
pod-template-hash=69886c8bcb
security.istio.io/tlsMode=istio
version=v1
Annotations: cni.projectcalico.org/podIP: 192.168.0.23/32
sidecar.istio.io/status:
{"version":"06276c8f39527e9d938cdb12b45ed9dda7fc3bedca74d940552168bfc3d957cc","initContainers":["istio-init"],"containers":["istio-proxy"]...
...
Containers:
productpage:
Container ID: docker://927727491ccd40378e22e5a27f2388e3890689f6f88b997b4092d9d613e4c45c
Image: docker.io/istio/examples-bookinfo-productpage-v1:1.15.1
Image ID: docker-pullable://istio/examples-bookinfo-productpage-v1@sha256:d54717a1bd3c8e4a12fa887aadbb764e594099a255b3b892da1483a528b6856c
Port: 9080/TCP
...
istio-proxy:
Container ID: docker://f6d2863e728d3919171d80975af5255167a8a33377645588a1b7647578e69ca8
Image: gcr.io/gke-release/asm/proxyv2:1.4.9-asm.1
Image ID: docker-pullable://gcr.io/gke-release/asm/proxyv2@sha256:4661ed09fb7f0450aecd2c7cb6aa42ea697955f88b32920437796d6de5b9669e
Port: 15090/TCP
# Test the application
Use curl to ensure that the application is running.
kubectl -n bookinfo exec -it "$(kubectl -n bookinfo get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"
The application title should be returned.
<title>Simple Bookstore App</title>
# Deploy the gateway
Download the appropriate manifest file:
curl https://raw.githubusercontent.com/istio/istio/release-1.6/samples/bookinfo/networking/bookinfo-gateway.yaml > bookinfo-gateway.yaml
Deploy the gateway in the namespace:
kubectl -n bookinfo apply -f bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created
Determine the ingress IP:
kubectl get svc istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.110.50.233 10.15.158.55 15020:30970/TCP,80:32417/TCP,443:30921/TCP,15029:32551/TCP,15030:30335/TCP,15031:30934/TCP,15032:31978/TCP,15443:31414/TCP 4h57m
Note: The ingress IP will match the value in the variable gke_cluster_config.anthos_service_mesh_externalIP in the all.yml
configuration file.
# Confirm the application is accessible from outside the cluster
Using the ingress IP, you can use curl to access the application homepage, for example:
curl -s "http://10.15.158.55/productpage" | grep -o "<title>.*</title>"
The application title should be returned.
<title>Simple Bookstore App</title>
Alternatively, browse to the URL, for example, http://10.15.158.55/productpage:

Figure. Bookinfo homepage
# Access the application using an interal address
In the output for the service istio-ingressgateway above, notice that port 80 is mapped to port 32417.
This means that you can access the application using the internal IP address for any node in your user cluster, along with port 32417.
You can easily discover
the IP addresses of your nodes using the -o wide flag on the kubectl get nodes command. In the sample user cluster, the four IP addresses are statically configured as 10.15.155.121-124.
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
gmcg-gke-user1-node1 Ready <none> 2d2h v1.16.8-gke.6 10.15.155.121 10.15.155.121 Ubuntu 18.04.4 LTS 5.3.0-53-generic docker://19.3.2
gmcg-gke-user1-node2 Ready <none> 2d2h v1.16.8-gke.6 10.15.155.122 10.15.155.122 Ubuntu 18.04.4 LTS 5.3.0-53-generic docker://19.3.2
gmcg-gke-user1-node3 Ready <none> 2d2h v1.16.8-gke.6 10.15.155.123 10.15.155.123 Ubuntu 18.04.4 LTS 5.3.0-53-generic docker://19.3.2
gmcg-gke-user1-node4 Ready <none> 2d2h v1.16.8-gke.6 10.15.155.124 10.15.155.124 Ubuntu 18.04.4 LTS 5.3.0-53-generic docker://19.3.2
Using the IP address of one of the nodes, together with port (in this instance 32417), you can use curl or the browser to access the application homepage:
curl http://10.15.155.124:32417/productpage

Figure. Bookinfo homepage using internal address
# Multiple version of the reviews service
All 3 versions of the reviews service, v1, v2, and v3, are deployed at the same time.
As a result, when you refresh the homepage, you should see different ratings output
(black stars, red stars or no stars).

Figure. Bookinfo homepage - black stars

Figure. Bookinfo homepage - red stars
In a realistic deployment, new versions of a microservice are deployed over time instead of deploying all versions simultaneously.