Skip to main content
Version: 1.16.0

Multi-Cluster Slice: BookInfo Deployment

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.

Objective

This tutorial is designed to aid you in improving your understanding of deploying applications.

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 Install KubeSlice.
  • You have Istio installed in all registered worker clusters. For more information, see Install Istio.
  • Before creating a slice, create the bookinfo namespace in all the participating worker clusters. Use the following command to create the bookinfo namespace:
    kubectl create ns bookinfo
  • Use the following command to inject the istio label to the bookinfo namespace:
    kubectl label namespace bookinfo istio-injection=enabled
  • You have the slice created across the worker clusters. For more information, see creating a slice.

Create the BookInfo Deployment YAML Files

Using the templates below, create the configuration YAML files to deploy the BookInfo application.

info

These instructions will guide you through deploying the productpage service to a cluster we will refer to as the productpage cluster. The other services and service exports will be deployed to a cluster referred to here as the services cluster.

Product Page

Create the productpage.yaml file using the below template. All the fields in the template remain the same except for the <slice name>. Replace the <slice name> 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

Create the details.yaml file using the below template. All the fields in the template remain the same except for the <slice name>. Replace the <slice name> 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

Create the ratings.yaml file using the below template. All the fields in the template remain the same except for the <slice name>. Replace the <slice name> 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

Create the reviews.yaml file using the below template. All the fields in the template remain the same except for the <slice name>. Replace the <slice name> 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

Create the serviceexports.yaml file using the below template. All the fields in the template remain the same except for <slice name> instances. Replace the <slice name> 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

Deploy to the Productpage Cluster

To deploy the productpage:

  1. Switch the context to the cluster you will be deploying the productpage using the following command:

    kubectx <services cluster>
  2. Apply the productpage.yaml file using the following command:

    kubectl apply -f productpage.yaml -n bookinfo

    Expected Output:

    service/productpage created
    serviceaccount/bookinfo-productpage created
    deployment.apps/productpage-v1 created
  3. Check if the deployed productpage pod is running on the cluster using the following command:

    kubectl get pods -n bookinfo

    Expected Output

    NAME                              READY   STATUS    RESTARTS   AGE
    productpage-v1-5cc46fc6dc-drd8b 4/4 Running 0 26h

Deploy to the Service Cluster

Use the following command to ensure we are targeting the cluster we deploy reviews, details, and ratings to:

kubectx <services cluster>

Using the following commands, apply the details.yaml, ratings.yaml, reviews.yaml, and serviceexports.yaml files.

Use the following command to apply the details.yaml file.

kubectl apply -f details.yaml -n bookinfo

Expected Output

service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created

Use the following command to apply the ratings.yaml file:

kubectl apply -f ratings.yaml -n bookinfo

Expected Output

service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created

Use the following command to apply the reviews.yaml file:

kubectl apply -f reviews.yaml -n bookinfo

Expected Output

service/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:

kubectl get pods -n bookinfo

Expected Output

NAME                          READY   STATUS    RESTARTS   AGE
details-v1-557b474454-fbfhh 4/4 Running 0 26h
ratings-v1-5846f848bb-4dwtz 4/4 Running 0 26h
reviews-v3-64cf7654f4-cfqz8 4/4 Running 0 26h

Use the following command to apply serviceexports.yaml file:

kubectl apply -f serviceexports.yaml -n bookinfo

Expected Output

serviceexport.networking.kubeslice.io/details created
serviceexport.networking.kubeslice.io/reviews created

Validate the Services

To validate the Details and Review services:

  1. Switch the context to the services cluster.

    kubectx <services cluster>
  2. Use the following command to verify the details and reviews services have been successfully exported to the KubeSlice configuration:

    kubectl get serviceexport -n bookinfo

    Expected Output

    NAME      SLICE   INGRESS  SERVICEPORT(S)   PORT(S)    ENDPOINTS   STATUS
    details white true 9080/TCP 1 READY
    reviews white true 9080/TCP 1 READY

Validate the Productpage on the Cloud Cluster

To validate the Productpage service:

  1. Switch the context to the productpage cluster.

    kubectx <productpage cluster>
  2. Using the following command, verify the details and reviews service imports are present in the cluster:

    kubectl get serviceimport -n bookinfo

    Expected Output

    NAME      SLICE   PORT(S)    ENDPOINTS   STATUS
    details white 9080/TCP 1 READY
    reviews white 9080/TCP 1 READY
  3. Use the following command to check the exposed port for the productpage service.

    kubectl get services -n bookinfo

    Expected Output

    NAME          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
    info

    Use the exposed port for the productpage service to visit the BookInfo webpage.

  4. To view the deployed BookInfo product page, we need the external IP address of an application node and the exposed port we just retrieved.

    info

    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:

    kubectl get nodes -o wide

    Expected Output (your output will differ, here we are just focused on the external IP address).

    kubectl 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
  5. Combine the external IP address the command returns with the port you retrieved in the last step in the format below. Visit the page in a browser to view your multi-cluster BookInfo deployment.

    http://<external ip>:<port>/productpage

    Example alt

success

You have successfully deployed the BookInfo application on a KubeSlice configuration containing at least two clusters.

Uninstall BookInfo

To uninstall BookInfo from your KubeSlice configuration, the instructions in uninstall KubeSlice.