Istio — Part 1: Discovering Services
As we start building applications with microservice architecture sooner or later we always find ourselves in a spot where we want to visualize and monitor our entire deployment in a single screen. Also debugging a bug in microservice is really complex and time consuming. To ease it up, everyone felt the need of observability and controllability of their distributed architecture. Istio is one of the tools that actually solves these problems.
So here I will try to discuss what is Istio and will take a use case based approach to see most of the features of Istio in here and upcoming blogs.
What is Istio?
Istio is a service-mesh.
I think this is most simplest and wholesome definition I have come through so far. Let me break this down. Istio gathers a set of tools like Envoy, Grafana, Prometheus and many others to enable developers to write code in for controlling distributed architecture in a simple manner. Why need Istio, when I have these tools to use independently. Yes, you can. But obviously you don’t want it. Istio abstracts all the inner-workings of those tools and made it easy for developers to work with.
Istio architecture consists of four components.
- Envoy: It’s the only part of the data plane in Istio. It will be injected as a sidecar proxy to each pod and now any request will be incoming to or outgoing from a pod will pass through Envoy Proxy. Envoy was built by Lyft. You can edit Envoy proxy and can build your own service mesh but I will highly discourage you to do so.
- Pilot: Responsible mostly service discovery and traffic management. It is a component of control plane.
- Citadel: Maintains service-to-service and end user authentication by built in authentication and credentials managements. Handles certificates to enable https connection throughout the service-mesh. It is also a part of control plane.
- Galley: Your Trusted Buddy !!! Does all the validation, parsing and ingestion of yaml configuration we write to make changes in Istio service mesh. It is also a part of control plane.
Istio is platform independent, can be deployed to Kubernetes, Nomad, Consul. But so far, Kubernetes is the most popular to use for distributed architecture application. Using Istio with Kubernetes is a powerful tool that is always gives edge of simplicity in system management and will ensure a good night sleep.
Endgoal
Let’s see the use case.
Let’s say we have this picture for our architecture. In today’s discussion we will use just only the traffic management portion of Istio.
Here at the very below we have our kubernetes deployment as usual. So what we want is this
- We have two types of multiple pods deployed for docker image
user
andproduct
- For
user
we have/
and/about
route and forproduct
we have/
and/latest
route - We also have our service in place one for catering all
user
pods and other forproduct
pods - What we want is when we request http://user.microservice.retailvoice.xyz then we should be redirected to the user pods
- when we request http://product.microservice.retailvoice.xyz then we should be redirected to the products pods
- Lastly we want to have path based routing so when we request http://microservice.retailvoice.xyz/user and http://microservice.retailvoice.xyz/product, we want to be redirected to
user
andproduct
pods respectively
Requirements
- We need to have
istioctl
installed in your pc. For mac, I usedbrew install istioctl
You can find the installation guide here - Check the version using
istioctl version --remote=false
- Connect your kubernetes cluster via your terminal. Use
kubectl config current-context
to see if you are in the current cluster - Let’s install Istio in our cluster. Run
istioctl manifest apply --set profile=demo
- If installed successfully, you can check the pods by
kubectl get pods -n istio-system
Steps to success
- I will be uploading all the codes in here. So I cloned it and go into the project directory via terminal.
- Now let’s build the docker image for
user
usingdocker build . -t your_image_name -f Dockerfile.user
& publish it to docker registry usingdocker push your_image_name
- Do the same for
product
usingdocker build . -t your_image_name -f Dockerfile.product
and publish it to docker registry usingdocker push your_image_name
- As we said, we need istio proxy per pod to track the requests and other istio functionality. So we need to enable
istio-injection
per namespace basis. As we will be working indefault
namespace so let us modify thelabels
of it viayaml
file and usekubectl apply -f k8s/1-discovering-services/1-namespace.yaml
(I am assuming we are in work directory)
- Now let’s run
kubectl apply -f k8s/1-discovering-services/2-user-microservice.yaml
which will createuser
pods anduser-service
that will handle requests touser
pods.
- Now let’s run
kubectl apply -f k8s/1-discovering-services/2-product-microservice.yaml
which will createproduct
pods andproduct-service
that will handle requests toproduct
pods.
- At this point you have a simple kubernetes deployment with proxy per pods basis and cluster ip services to the handle the request. You can simply connect to cluster ip service with port forwarding at point. But we will do better than that. Now we will make some Istio magic to expose our services to the world.
Gateway
A Gateway is a service that handles the incoming requests to a service mesh. When we installed Istio in our cluster, by default we have a ingressgateway
service in istio-system
namespace.
- Get the list of gateways by running
kubectl get gw -n istio-system
- Get the details by
kubectl get gw ingressgateway -n istio-system -o yaml
At this point we will be deleting the default ingressgateway
by running kubectl delete gw ingressgateway -n istio-system
Now let’s write our own gateway. What we will do is we will have a server configuration on port 80 which will accept HTTP request for 3 hosts named microservice.retailvoice.xyz, user.microservice.retailvoice.xyz and product.microservice.retailvoice.xyz.
Now create our gateway by running kubectl apply -f k8s/1-discovering-services/4-gateway.yaml
VirtualService
A virtualservice defines some rules that will be applied when the host is addressed. As we have three hosts, we will be writing 3 virtual services.
We will just forward all the traffic to our cluster ip service when user.microservice.retailvoice.xyz is requested.
I request to go through the code snippets. Most of the things are commented
- Create the virtual service using
kubectl apply -f k8s/1-discovering-services/5-user-virtual-service.yaml
Do the same for product virtual service
- Create the virtual service using
kubectl apply -f k8s/1-discovering-services/6-product-virtual-service.yaml
- You can list all the virtual services by using
kubectl get vs
At this point we need to sort out our dns records. By default with Istio installation we get a load balancer istio-system
namespace named istio-ingressgateway
We can run kubectl get svc istio-ingressgateway -n istio-system
to get the external address of the load balancer. Then change the dns record appropriately to point to external address.
I have forwarded my 3 domains to the external ip of the load balancer in my dns manager.
Now if you want to request the http://user.microservice.retailvoice.xyz, http://user.microservice.retailvoice.xyz/about, http://product.microservice.retailvoice.xyz and http://product.microservice.retailvoice.xyz/latest then we should get the responses. I will use curl for this.
Now let’s move on matched route handling. For this let’s write a virtual service for microservice.retailvoice.xyz
Now deploy the virtual service with matched routes to cluster by kubectl apply -f k8s/1-discovering-services/7-microservice-virtual-service.yaml
Visualization
It’s always better to visual how my distributed system works. Kiali is shipped with Istio just to do that. When you install Istio, you get Kiali by default.
- Start Kiali dasboard by running
istioctl dashboard kiali
- Login using username
admin
and passwordadmin
These are the default one. You can change it if you want.
Make some requests to the urls and in the graph section under Workload Graph you might follow something like this
Last Words
Looks like it’s all worked. Yay !!!
You can find all the code in the repo with tag 1-discovering-services
I am also adding quick link for the tag here. I am planning to write my next blog on weight routing, canary releases, consistent hashing and dark releases using Istio. Please subscribe to get latest updates.
Happy Coding !!!