Deploying the Bookinfo Application
Introduction
Bookinfo is a sample application from Istio that is composed of four separate microservices: productpage, details, reviews, and ratings. In this topic, we will use the Bookinfo application to demonstrate inter-slice communication.
Prerequisites
Before you begin, ensure the following prerequisites are met:
- You have a KubeSlice configuration with two or more clusters registered. For more information, see Installing KubeSlice.
- You have Istio installed in all registered worker clusters. For more information, see Installing Istio.
- Before creating a slice, create the bookinfonamespace in all the participating worker clusters. Use the following command to create thebookinfonamespace:kubectl create ns bookinfo
- Inject the istio label to the bookinfonamespace using the following command:kubectl label namespace bookinfo istio-injection=enabled
- You have the slice created across the worker clusters. For more information, see Creating a Slice.
Creating the BookInfo Deployment YAML Files
Using the templates below, create the necessary .yaml files to deploy the BookInfo application.
All fields in the template will remain the same except for the slice name which must be replaced with the
name of your slice.
These instructions will guide you through deploying the Product Page service to a cluster we will refer to as
the productpage cluster, and the remaining services as well as service exports will be deployed to a cluster
referred to here as the services cluster.
Productpage
Using the template below, create productpage.yaml. All fields in the template will remain the same except for
the slice name which must be replaced with the name of your slice.
##################################################################################################
# Productpage service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
 name: productpage
 labels:
   app: productpage
   service: productpage
spec:
 type: NodePort
 ports:
 - port: 9080
   name: http
 selector:
   app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
 name: bookinfo-productpage
 labels:
   account: productpage
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: productpage-v1
 labels:
   app: productpage
   version: v1
spec:
 replicas: 1
 selector:
   matchLabels:
     app: productpage
     version: v1
 template:
   metadata:
     labels:
       app: productpage
       version: v1
   spec:
     serviceAccountName: bookinfo-productpage
     containers:
     - name: productpage
       image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 9080
       volumeMounts:
       - name: tmp
         mountPath: /tmp
       securityContext:
         runAsUser: 1000
       env:
       - name: REVIEWS_HOSTNAME
         value: reviews.bookinfo.svc.slice.local
       - name: DETAILS_HOSTNAME
         value: details.bookinfo.svc.slice.local
     - name: netshoot
       image: nicolaka/netshoot
       imagePullPolicy: IfNotPresent
       command: ["/bin/sleep", "3650d"]
       securityContext:
         capabilities:
           add: ["NET_ADMIN"]
         allowPrivilegeEscalation: true
         privileged: true
     volumes:
     - name: tmp
       emptyDir: {}
Details
Using the template below, create details.yaml. All fields in the template will remain the same except for
the slice name which must be replaced with the name of your slice.
##################################################################################################
# Details service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
 name: details
 labels:
   app: details
   service: details
spec:
 ports:
 - port: 9080
   name: http
 selector:
   app: details
---
apiVersion: v1
kind: ServiceAccount
metadata:
 name: bookinfo-details
 labels:
   account: details
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: details-v1
 labels:
   app: details
   version: v1
spec:
 replicas: 1
 selector:
   matchLabels:
     app: details
     version: v1
 template:
   metadata:
     labels:
       app: details
       version: v1
   spec:
     serviceAccountName: bookinfo-details
     containers:
     - name: details
       image: docker.io/istio/examples-bookinfo-details-v1:1.16.2
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 9080
       securityContext:
         runAsUser: 1000
     - name: netshoot
       image: nicolaka/netshoot
       imagePullPolicy: IfNotPresent
       command: ["/bin/sleep", "3650d"]
       securityContext:
         capabilities:
           add: ["NET_ADMIN"]
         allowPrivilegeEscalation: true
         privileged: true
Ratings
Using the template below, create ratings.yaml. All fields in the template will remain the same except for
the slice name which must be replaced with the name of your slice.
##################################################################################################
# Ratings service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
 name: ratings
 labels:
   app: ratings
   service: ratings
spec:
 ports:
 - port: 9080
   name: http
 selector:
   app: ratings
---
apiVersion: v1
kind: ServiceAccount
metadata:
 name: bookinfo-ratings
 labels:
   account: ratings
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: ratings-v1
 labels:
   app: ratings
   version: v1
spec:
 replicas: 1
 selector:
   matchLabels:
     app: ratings
     version: v1
 template:
   metadata:
     labels:
       app: ratings
       version: v1
   spec:
     serviceAccountName: bookinfo-ratings
     containers:
     - name: ratings
       image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 9080
       securityContext:
         runAsUser: 1000
     - name: netshoot
       image: nicolaka/netshoot
       imagePullPolicy: IfNotPresent
       command: ["/bin/sleep", "3650d"]
       securityContext:
         capabilities:
           add: ["NET_ADMIN"]
         allowPrivilegeEscalation: true
         privileged: true
Reviews
Using the template below, create reviews.yaml. All fields in the template will remain the same except for
the slice name which must be replaced with the name of your slice.
##################################################################################################
# Reviews service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
 name: reviews
 labels:
   app: reviews
   service: reviews
spec:
 ports:
 - port: 9080
   name: http
 selector:
   app: reviews
---
apiVersion: v1
kind: ServiceAccount
metadata:
 name: bookinfo-reviews
 labels:
   account: reviews
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: reviews-v3
 labels:
   app: reviews
   version: v3
spec:
 replicas: 1
 selector:
   matchLabels:
     app: reviews
     version: v3
 template:
   metadata:
     labels:
       app: reviews
       version: v3
   spec:
     serviceAccountName: bookinfo-reviews
     containers:
     - name: reviews
       image: docker.io/istio/examples-bookinfo-reviews-v3:1.16.2
       imagePullPolicy: IfNotPresent
       env:
       - name: LOG_DIR
         value: "/tmp/logs"
       ports:
       - containerPort: 9080
       volumeMounts:
       - name: tmp
         mountPath: /tmp
       - name: wlp-output
         mountPath: /opt/ibm/wlp/output
       securityContext:
         runAsUser: 1000
     - name: netshoot
       image: nicolaka/netshoot
       imagePullPolicy: IfNotPresent
       command: ["/bin/sleep", "3650d"]
       securityContext:
         capabilities:
           add: ["NET_ADMIN"]
         allowPrivilegeEscalation: true
         privileged: true
     volumes:
     - name: wlp-output
       emptyDir: {}
     - name: tmp
       emptyDir: {}
ServiceExports
Using the template below, create serviceexports.yaml. All fields in the template will remain the same except
for two slice name instances which must be replaced with the name of your slice.
##################################################################################
# Details ServiceExport
##################################################################################
apiVersion: networking.kubeslice.io/v1beta1
kind: ServiceExport
metadata:
 name: details
spec:
 slice: <slice name>  #Replace Slice Name
 selector:
   matchLabels:
     app: details
  ingressEnabled: false
 ports:
 - name: http
   containerPort: 9080
   protocol: TCP
---
##################################################################################
# Reviews ServiceExport
##################################################################################
apiVersion: networking.kubeslice.io/v1beta1
kind: ServiceExport
metadata:
 name: reviews
spec:
 slice: <slice name>  #Replace Slice Name
 selector:
   matchLabels:
     app: reviews
 ingressEnabled: false
 ports:
 - name: http
   containerPort: 9080
   protocol: TCP
Deploying to the Productpage Cluster
Perform these steps:
- Use the following command to ensure we are targeting the cluster we will be deploying the product page to:
kubectx <services cluster>
- Use the following command to apply the productpage.yamlfile:Expected Output:kubectl apply -f productpage.yaml -n bookinfoservice/productpage created
 serviceaccount/bookinfo-productpage created
 deployment.apps/productpage-v1 created
- Use the following command to check if the deployed productpage pod is running on the cluster:
Expected Outputkubectl get pods -n bookinfoNAME READY STATUS RESTARTS AGE
 productpage-v1-5cc46fc6dc-drd8b 5/5 Running 0 26h
Deploying to the Service Cluster
Perform these steps:
- Use the following command to ensure we are targeting the cluster we deploy reviews, details, and ratings to:
kubectx <services cluster>
- Use the following command to create the bookinfonamespace that we deploy these services on:kubectl create ns bookinfo
- Use the following command to label the bookinfonamespace for istio-injection:kubectl label namespace bookinfo istio-injection=enabled
- Using the following commands, apply the details.yaml, ratings.yaml, reviews.yaml, and serviceexports.yaml files.
Use the following command to apply the details.yamlfile.Expected Outputkubectl apply -f details.yaml -n bookinfoservice/details created
 serviceaccount/bookinfo-details created
 deployment.apps/details-v1 created
- Use the following command to apply the ratings.yamlfile:Expected Outputkubectl apply -f ratings.yaml -n bookinfoservice/ratings created
 serviceaccount/bookinfo-ratings created
 deployment.apps/ratings-v1 created
- Use the following command to apply the reviews.yamlfile:Expected Outputkubectl apply -f reviews.yaml -n bookinfoservice/reviews created
 serviceaccount/bookinfo-reviews created
 deployment.apps/reviews-v3 created
- Use the following command to verify if the deployed pods are running on the cluster:
Expected Outputkubectl get pods -n bookinfoNAME READY STATUS RESTARTS AGE
 details-v1-557b474454-fbfhh 5/5 Running 0 26h
 ratings-v1-5846f848bb-4dwtz 5/5 Running 0 26h
 reviews-v3-64cf7654f4-cfqz8 5/5 Running 0 26h
- Use the following command to apply serviceexports.yamlfile:Expected Outputkubectl apply -f serviceexports.yaml -n bookinfoserviceexport.networking.kubeslice.io/details created
 serviceexport.networking.kubeslice.io/reviews created
Validating the BookInfo Deployment
Validating the Services
Perform these steps:
- Switch the contexts to target the services cluster.kubectx <services cluster>
- Use the following command to verify the details and reviews services have been successfully exported to the
KubeSlice configuration:
Expected Outputkubectl get serviceexport -n bookinfokubectl get serviceexport -n bookinfo
 NAME SLICE INGRESS PORT(S) ENDPOINTS STATUS
 details white true 9080/TCP 1 READY
 reviews white true 9080/TCP 1 READY
Validating the Productpage on the Cloud Cluster
Perform these steps:
- Switch contexts to target the productpage cluster.kubectx <productpage cluster>
- Using the following command, verify the details and reviews service imports are present in the cluster:
Expected Outputkubectl get serviceimport -n bookinfoNAME SLICE PORT(S) ENDPOINTS STATUS
 details white 9080/TCP 1 READY
 reviews white 9080/TCP 1 READY
- Use the following command to check the exposed port for the product page service. In a moment, use this port to
visit the BookInfo webpage.
Expected Outputkubectl get services -n bookinfoNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
 details ClusterIP 10.0.116.23 <none> 9080/TCP 2d2h
 productpage NodePort 10.0.20.209 <none> 9080:31194/TCP 2d2h
 reviews ClusterIP 10.0.146.220 <none> 9080/TCP 2d2h
To view the deployed BookInfo product page, we need the external IP of an application node and the exposed port we just retrieved.Take note of the external IP address of one of the application nodes to use it later.
- Use the following command to get your node details:
Expected Output (your output will differ, here we are just focused on the external IP address).kubectl get nodes -o widekubectl get nodes -o wide
 NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE
 KERNEL-VERSION CONTAINER-RUNTIME
 gke-preprod-knative--preprod-knative--aba5a0cc-9jrq Ready <none> 27h v1.20.15-gke.3600 10.6.0.4 35.231.181.81 Container-Optimized OS from Google 5.4.170+ containerd://1.4.8
 gke-preprod-knative--preprod-knative--aba5a0cc-xj3j Ready <none> 27h v1.20.15-gke.3600 10.6.0.5 35.243.229.81 Container-Optimized OS from Google 5.4.170+ containerd://1.4.8
 gke-preprod-knative--preprod-knative--d19d3a9f-c32x Ready <none> 28h v1.20.15-gke.3600 10.6.0.3 104.196.200.27 Container-Optimized OS from Google 5.4.170+ containerd://1.4.8
- Combine the external IP address the command returns with the port you retrieved in the last step in the format below,
and visit the page in a browser to view your multi-cluster BookInfo deployment.
Examplehttp://<external ip>:<port>/productpage 
Validating the Productpage on the Kind Cluster
Accessing the Productpage from the Local Machine
If the kind clusters are on a local machine, perform these steps:
- Set up port-forwarding from a local machine using the following command:
Examplekubectl port-forward svc/<service-name> -n <namespace-name> <host-port>:<container-port>kubectl port-forward svc/productpage -n bookinfo 31986:9080
- Open the browser to access the product page using the following URL:
Examplehttp://localhost:<host-port>/productpagehttp://localhost:31986/productpage
The following is an example of the product page:

Accessing the Productpage from the Cloud EC2 Machine
If the kind clusters are on Cloud EC2 Machine, perform these steps:
- Connect to your EC2 machine using SSH from your local machine using the following command:
Examplessh -i <pemfile> ubuntu@<public IP> -N -L <hostport>:<nodeinternalip>:<container-port>ssh -i mykeypair.pem ubuntu@54.234.57.178 -N -L 8080:172.18.0.6:31986
- Open the browser to access the product page using the following URL:
Examplehttp://localhost:<hostport>/productpagehttp://localhost:8080/productpage
The following is an example of the product page:

You have successfully deployed BookInfo application on a KubeSlice configuration containing at least two clusters.
Uninstalling Istio BookInfo
To uninstall BookInfo application from your KubeSlice configuration, follow the instructions in offboarding namespaces.