In this blog, we will try to understand Istio and its YAML configurations. You will also learn why Istio is great for managing traffic and how to set it up using Google Kubernetes Engine (GKE). I’ve also shed some light on deploying Istio in various environments and applications like intelligent routing, traffic shifting, injecting delays, and testing the resiliency of your application.
What is Istio?
The Istio’s website says it is “An open platform to connect, manage, and secure microservices”.
As a network of microservices known as 'Service Mesh' grows in size and complexity, it can become tougher to understand and manage. Its requirements can include discovery, load balancing, failure recovery, metrics, and monitoring, and often more complex operational requirements such as A/B testing, canary releases, rate limiting, access control, and end-to-end authentication. Istio claims that it provides complete end to end solution to these problems.
- Provides automatic load balancing for various protocols like HTTP, gRPC, WebSocket, and TCP traffic. It means you can cater to the needs of web services and also frameworks like Tensorflow (it uses gRPC).
- To control the flow of traffic and API calls between services, make calls more reliable, and make the network more robust in the face of adverse conditions.
- To gain understanding of the dependencies between services and the nature and flow of traffic between them, providing the ability to quickly identify issues etc.
Let’s explore the architecture of Istio.
Istio’s service mesh is split logically into two components:
- Data plane - set of intelligent proxies (Envoy) deployed as sidecars to the microservice they control communications between microservices.
- Control plane - manages and configures proxies to route traffic. It also enforces policies.
Envoy - Istio uses an extended version of envoy (L7 proxy and communication bus designed for large modern service-oriented architectures) written in C++. It manages inbound and outbound traffic for service mesh.
Enough of theory, now let us setup Istio to see things in action. A notable point is that Istio is pretty fast. It’s written in Go and adds a very tiny overhead to your system.
Setup Istio on GKE
Sample Book Review Application
Following this link, you can easily
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.
The end-to-end architecture of the application is shown below.
If everything goes well, You will have a web app like this (served at http://GATEWAY_URL/productpage)
Let’s take a case where 50% of traffic is routed to v1 and the remaining 50% to v3.
This is how the config file looks like (/path/to/istio-0.2.12/samples/bookinfo/kube/route-rule-reviews-50-v3.yaml)
Let’s try to understand the config file above.
Istio provides a simple Domain-specific language (DSL) to control how API calls and layer-4 traffic flow across various services in the application deployment.
In the above configuration, we are trying to Add a “Route Rule”. It means we will be routing the traffic coming to destinations. The destination is the name of the service to which the traffic is being routed. The route labels identify the specific service instances that will receive traffic.
In this Kubernetes deployment of Istio, the route label “version: v1” and “version: v3” indicates that only pods containing the label “version: v1” and “version: v3” will receive 50% traffic each.
Now multiple route rules could be applied to the same destination. The order of evaluation of rules corresponding to a given destination, when there is more than one, can be specified by setting the precedence field of the rule.
The precedence field is an optional integer value, 0 by default. Rules with higher precedence values are evaluated first. If there is more than one rule with the same precedence value the order of evaluation is undefined.
When is precedence useful? Whenever the routing story for a particular service is purely weight based, it can be specified in a single rule.
Once a rule is found that applies to the incoming request, it will be executed and the rule-evaluation process will terminate. That’s why it’s very important to carefully consider the priorities of each rule when there is more than one.
In short, it means route label “version: v1” is given preference over route label “version: v3”.
Intelligent Routing Using Istio
We will demonstrate an example in which we will be aiming to get more control over routing the traffic coming to our app. Before reading ahead, make sure that you have installed Istio and book review application.
First, we will set a default version for all microservices.
> kubectl create -f samples/bookinfo/kube/route-rule-all-v1.yaml
Then wait a few seconds for the rules to propagate to all pods before attempting to access the application. This will set the default route to v1 version (which doesn’t call rating service). Now we want a specific user, say Velotio, to see v2 version. We write a yaml (test-velotio.yaml) file.
We then set this rule
> kubectl create -f path/to/test-velotio.yml
Now if any other user logs in it won’t see any ratings (it will see v1 version) but when “velotio” user logs in it will see v2 version!
This is how we can intelligently do content-based routing. We used Istio to send 100% of the traffic to the v1 version of each of the Bookinfo services. You then set a rule to selectively send traffic to version v2 of the reviews service based on a header (i.e., a user cookie) in a request.
Now Let's take a case in which we have to shift traffic from an old service to a new service.
We can use Istio to gradually transfer traffic from one microservice to another one. For example, we can move 10, 20, 25..100% of traffic. Here for simplicity of the blog, we will move traffic from reviews:v1 to reviews:v3 in two steps 40% to 100%.
First, we set the default version v1.
> kubectl create -f samples/bookinfo/kube/route-rule-all-v1.yaml
We write a yaml file route-rule-reviews-40-v3.yaml
Then we apply a new rule.
> kubectl create -f path/to/route-rule-reviews-40-v3.yaml
Now, Refresh the productpage in your browser and you should now see red colored star ratings approximately 40% of the time. Once that is stable, we transfer all the traffic to v3.
> istioctl replace -f samples/bookinfo/kube/route-rule-reviews-v3.yaml
Inject Delays and Test the Resiliency of Your Application
Here we will check fault injection using HTTP delay. To test our Bookinfo application microservices for resiliency, we will inject a 7s delay between the reviews:v2 and ratings microservices, for user “Jason”. Since the reviews:v2 service has a 10s timeout for its calls to the ratings service, we expect the end-to-end flow to continue without any errors.
> istioctl create -f samples/bookinfo/kube/route-rule-ratings-test-delay.yaml
Now we check if the rule was applied correctly,
> istioctl get routerule ratings-test-delay -o yaml
Now we allow several seconds to account for rule propagation delay to all pods. Log in as user “Jason”. If the application’s front page was set to correctly handle delays, we expect it to load within approximately 7 seconds.
In this blog we only explored the routing capabilities of Istio. We found Istio to give us good amount of control over routing, fault injection etc in microservices. Istio has a lot more to offer like load balancing and security. We encourage you guys to toy around with Istio and tell us about your experiences.