---
# System prepended metadata

title: '`Istio` Example: `Bookinfo` Application Installation'
tags: [ITRI, istio, example]

---

# `Istio` Example: `Bookinfo` Application Installation

###### tags: `ITRI`, `istio`, `example`

***

## Reference
- Official Website: ISTIO/DOCS/EXAMPLES/BOOKINFO APPLICATION: [Bookinfo Application](https://istio.io/docs/examples/bookinfo/)
    - Chinese Version: [Bookinfo 应用](https://istio.io/zh/docs/examples/bookinfo/)
- Blog of 青蛙小白: [Istio 1.0学习笔记(二)：部署官方示例Bookinfo](https://blog.frognew.com/2018/08/learning-istio-1.0-2.html)

***

## *Bookinfo* Architecture

![Bookinfo Application without Istio](https://istio.io/docs/examples/bookinfo/noistio.svg)

Four separate microservices in `Bookinfo`:
- `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. (提供圖書評論功能，可以調用 `rating` 給圖書星星)
    - After following the steps below, 我們可以看到：
```bash
# kubectl get pod  -l app=reviews -n istio-example
NAME                          READY   STATUS    RESTARTS   AGE
reviews-v1-5787f7b87-5g6k4    2/2     Running   0          5h9m
reviews-v2-6d8b975647-t9t2m   2/2     Running   0          5h9m
reviews-v3-7d5549f9-sphc8     2/2     Running   0          5h9m
```
- `ratings` The `ratings` microservice contains book ranking information that accompanies a book review. (提供圖書給星星功能)
    - There are 3 versions of the reviews microservice:

|Version|GUI|
|-|-|
|v1|<li>Version v1 doesn’t call the `ratings` service.</li> ![](https://i.imgur.com/PNhiDXp.png)|
|v2|<li>Version v2 calls the `ratings` service, and displays each rating as 1 to 5 ++black++ stars.</li> ![](https://i.imgur.com/APSJl4R.png)|
|v3|<li>Version v3 calls the `ratings` service, and displays each rating as 1 to 5 ++red++ stars.</li> ![](https://i.imgur.com/lOKghEK.png)|

Notice that: 
- this application is polyglot (多語言的)
- these services have no dependencies on *Istio*
仍不失它是一個有趣的 service mesh 示例。

***

## Deploying the application

官方的 example 並不需要我們再去修改 application。 We only simply need to configure and run the services in an *Istio-enabled* environment, with *Envoy sidecars* injected along side each service.
![Bookinfo Application](https://istio.io/docs/examples/bookinfo/withistio.svg)
所有的微服务之间的调用都是通过 Envoy sidecar，即图中小黑色长方形，微服务的 sidecar 组成了服务网格 Service Mesh。

### Running on Kubernetes

#### Create namespace `istio-example` for *Bookinfo*

Check if `istio-sidecar-injector` is running.
```bash
# kubectl get pod -n istio-system | grep  injector
istio-sidecar-injector-fc58d99f-vck25   1/1     Running     0          4h7m
```
- `istio-sidecar-injector` 可以自动将 *Envoy* 容器作为 sidecar 注入到我们的业务应用 Pod 中，只要业务应用 Pod 所在的 namespace 包含 `istio-injection=enabled` 的 Label。

In this note, we create a namespace `istio-example` for *Bookinfo* application.
```bash
# kubectl create namespace istio-example
```

Default *Istio* installation uses automatic sidecar injection. Label the namespace:
```bash
# kubectl label namespace istio-example istio-injection=enabled
```

#### Run the *Bookinfo* application

*Bookinfo* application was defined in `samples/bookinfo/platform/kube/bookinfo.yaml`.
```yaml=
# Copyright 2017 Istio Authors
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

##################################################################################################
# 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
---
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.15.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
##################################################################################################
# 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
---
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.15.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
##################################################################################################
# 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
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v1
  labels:
    app: reviews
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v1
  template:
    metadata:
      labels:
        app: reviews
        version: v1
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
      - name: reviews
        image: docker.io/istio/examples-bookinfo-reviews-v1:1.15.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v2
  labels:
    app: reviews
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v2
  template:
    metadata:
      labels:
        app: reviews
        version: v2
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
      - name: reviews
        image: docker.io/istio/examples-bookinfo-reviews-v2:1.15.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
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.15.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
##################################################################################################
# Productpage services
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: productpage
  labels:
    app: productpage
    service: productpage
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-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.15.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
```

Deploy the application:
```bash
# cd istio-<version>
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -n istio-example
```

### Confirm all services, pods & application
If thay are correctly defined and running:
```bash
# kubectl get services -n istio-example
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.233.55.254   <none>        9080/TCP   4h8m
productpage   ClusterIP   10.233.17.112   <none>        9080/TCP   4h8m
ratings       ClusterIP   10.233.28.165   <none>        9080/TCP   4h8m
reviews       ClusterIP   10.233.12.187   <none>        9080/TCP   4h8m

# kubectl get pods -n istio-example
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-6978996b-blfrn         2/2     Running   0          4h9m
productpage-v1-7658b8dcc6-9bbc5   2/2     Running   0          4h9m
ratings-v1-84975bc778-zspbs       2/2     Running   0          4h9m
reviews-v1-5787f7b87-5g6k4        2/2     Running   0          4h9m
reviews-v2-6d8b975647-t9t2m       2/2     Running   0          4h9m
reviews-v3-7d5549f9-sphc8         2/2     Running   0          4h9m
```

Send a request to it by a `curl` command from `ratings` for checking *BookInfo* is running:
```bash
# kubectl exec -it -n istio-example $(kubectl get pod -n istio-example -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
```

## Istio Gateway: Determining the ingress IP and port

Now that the `Bookinfo` services are up and running, you need to make the application accessible from outside of your Kubernetes cluster, e.g., from a browser.

An ==Istio Gateway== is used for this purpose.

1. Define the ingress gateway for the application:
```bash
# kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml -n istio-example
```

2. Confirm the gateway has been created:
```bash
# kubectl get gateway -n istio-example
NAME               AGE
bookinfo-gateway   4h
```

3. Set the `INGRESS_HOST` and `INGRESS_PORT` variables for accessing the gateway.

Check if our Kubernetes cluster is running in an environment that supports external load balancers:
```bash
# kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                                                                                                      AGE
istio-ingressgateway   LoadBalancer   10.233.12.169   <pending>     15020:32165/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:31238/TCP,15030:31865/TCP,15031:30552/TCP,15032:31756/TCP,15443:30065/TCP   4h38m
```

- If the `EXTERNAL-IP` value is set, our environment has an external load balancer that you can use for the ingress gateway. 
- If the `EXTERNAL-IP` value is `<none>` (or perpetually `<pending>`), our environment does not provide an external load balancer for the ingress gateway. 
    - In this case, you can access the gateway using the service’s node port.
    Set the ingress ports:
    ```bash
    export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
    export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
    ```
    Setting the ingress IP depends on the cluster provider:
    ```bash
    export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
    ```

4. Set `GATEWAY_URL`:
```bash
# export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
```

### Confirm the app is accessible from outside the cluster

Check from the CLI.
```bash
# curl -s http://${GATEWAY_URL}/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
```

Open browser to `http://$GATEWAY_URL/productpage` to view the Bookinfo web page.
![](https://i.imgur.com/WPBUKlO.png)


If you refresh the page several times (重新整理頁面多次時), you should see different versions of reviews shown in productpage, presented in a *round robin* style (red stars, black stars, no stars), since we haven’t yet used *Istio* to ++control the version routing++.

***

## Apply default destination rules

Before using *Istio* to ++control the Bookinfo version routing++, we need to define the available versions, called *subsets*, in destination rules.

Create default destination rules for the *Bookinfo* services.

Since we did not enable mutual TLS, apply  `samples/bookinfo/networking/destination-rule-all.yaml`.
```bash
# kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml -n istio-example
```

Display the destination rules.
```bash
# kubectl get destinationrules -n istio-example
NAME          HOST          AGE
details       details       1d
productpage   productpage   1d
ratings       ratings       1d
reviews       reviews       1d
```

***

## Clean Up Appication

Remove the application virtual services.
```bash
# kubectl delete -f samples/bookinfo/networking/virtual-service-all-v1.yaml -n istio-example
```

## Uninstall from Kubernetes environment
If we want to clear all the `Bookinfo` example, use the script.
```bash
# samples/bookinfo/platform/kube/cleanup.sh
```

Confirm shutdown.
```bash
# kubectl get virtualservices -n istio-example    #-- there should be no virtual services
# kubectl get destinationrules -n istio-example   #-- there should be no destination rules
# kubectl get gateway -n istio-example            #-- there should be no gateway
# kubectl get pods -n istio-example               #-- the Bookinfo pods should be deleted
```

***

<center>** End **</center>

***
***