- This 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 v1 doesn’t call the ratings service.
- Version v2 calls the ratings service, and displays each rating as 1 to 5 black stars.
- Version v3 calls the ratings service, and displays each rating as 1 to 5 red stars.
This application is polyglot, i.e., the microservices are written in different languages. It’s worth noting that these services have no dependencies on Istio, but make an interesting service mesh example, particularly because of the multitude of services, languages and versions for the reviews service.
Please refer to the following github repo for setting up a local kubernetes environment using KinD and LoadBalancer using Metallb.
Create Multi-Node Local Kubernetes Cluster (KinD) with LoadBalancer (Metallb)
k create namespace argocd
k apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
k get all -n argocd
For the argocd to utilize Metallb, we have to change the service type of "argocd-server" service from "ClusterIP" to "LoadBalancer"
k edit service argocd-server -n argocd
k get all -n argocd
Now we see that the service type of "argocd-server" service has been changed from "ClusterIP" to "LoadBalancer".
- ArgoCD UI admin username: admin
- ArgoCD UI admin password: xxxxxxxxxxxx
k -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
brew install istioctl
For this application, we use the demo configuration profile. It’s selected to have a good set of defaults for testing, but there are other profiles for production or performance testing.
istioctl install --set profile=demo -y
To run the sample with Istio requires no changes to the application itself. Instead, you simply need to configure and run the services in an Istio-enabled environment, with Envoy sidecars injected along side each service. The resulting deployment will look like this:
All of the microservices will be packaged with an Envoy sidecar that intercepts incoming and outgoing calls for the services, providing the hooks needed to externally control, via the Istio control plane, routing, telemetry collection, and policy enforcement for the application as a whole.
The default Istio installation uses automatic sidecar injection. Label the namespace that will host the application with istio-injection=enabled.
Add a namespace label to instruct Istio to automatically inject Envoy sidecar proxies when you deploy your application later.
k label namespace default istio-injection=enabled
We will deploy our application in ArgoCD
k apply -f https://raw.githubusercontent.com/istio/istio/release-1.18/samples/bookinfo/platform/kube/bookinfo.yaml
k get all
To confirm that the Bookinfo application is running, send a request to it by a curl command from some pod, for example from ratings:
k exec "$(k get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"
The Bookinfo application is deployed but not accessible from the outside. To make it accessible, you need to create an Istio Ingress Gateway, which maps a path to a route at the edge of your mesh.
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.18/samples/bookinfo/networking/bookinfo-gateway.yaml
istioctl analyze
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
echo "$INGRESS_HOST"
echo "$INGRESS_PORT"
echo "$SECURE_INGRESS_PORT"
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
echo "$GATEWAY_URL"
Confirm that the Bookinfo application is accessible from outside by viewing the Bookinfo product page using a browser.
Run the following command to retrieve the external address of the Bookinfo application
echo "http://$GATEWAY_URL/productpage"
Paste the output from the previous command into your web browser and confirm that the Bookinfo product page is displayed.
Istio integrates with several different telemetry applications. These can help you gain an understanding of the structure of your service mesh, display the topology of the mesh, and analyze the health of your mesh.
Use the following instructions to deploy the Kiali dashboard, along with Prometheus, Grafana, and Jaeger.
kubectl apply -f istio-sample-addons/
kubectl rollout status deployment/kiali -n istio-system
istioctl dashboard kiali
Grafana k6 is an open-source load testing tool that makes performance testing easy and productive for engineering teams. k6 is free, developer-centric, and extensible.
Using k6, you can test the reliability and performance of your systems and catch performance regressions and problems earlier. k6 will help you to build resilient and performant applications that scale.
import http from 'k6/http';
export const options = {
stages: [
{ duration: '2m', target: 100 }, // traffic ramp-up from 1 to 100 users over 5 minutes.
{ duration: '5m', target: 200 }, // stay at 200 users for 5 minutes
{ duration: '2m', target: 100 }, // ramp-down to 100 users
],
};
export default () => {
const urlRes = http.get('http://172.19.255.201/productpage');
};
k6 run average-load.js