After some experimentation, ZoomInfo wound up using Istio for load balancing its first microservice. In addition to providing L7 load balancing, it gives us several extras for almost no additional work.
What Is Istio?
Istio bills itself as a service mesh that transparently layers on top of an existing distributed system to connect, secure, control, and observe services. It can provide features like service discovery, failure recovery, authentication, rate limiting, and A/B and canary testing in addition to the load balancing functionality ZoomInfo needs.
More information on Istio, its architecture, and the basic services it can provide is available here.
Things Istio Gave Us for Free
In addition to fixing the load balancing issues ZoomInfo saw with Kubernetes, Istio adds additional feature support for very little additional effort. ZoomInfo takes advantage of three of these:
- Authentication to verify incoming requests come from an allowed internal application
- REST API support accepting JSON payloads that get converted to the defined Protobuf format
- Routing to namespaces defined on the fly
Authentication of Consumer Applications
In theory anyone can send requests to the search microservice; ZoomInfo needed to implement some type of application-level authentication scheme to ensure that requests are coming from ZoomInfo applications. The search microservice has no concept of end users; this is strictly authenticating that the requests are coming from ZoomInfo applications and thus allowed to access the search service.
Setting this up was extremely easy; a short YAML configuration file indicates the expected JWT details for ZoomInfo applications as follows:
This includes a way to get the valid JSON web keys (jwksUri) and the required issuer (in this case a string indicating ZoomInfo). Incoming requests are matched against the issuer and the list of valid keys to make sure that they’re allowed to access the service. Requests that match are allowed through to the service proper; those that do not are rejected.
REST API support
The ZoomInfo search service is using remote procedure calls with protobuf data as its default transport mechanism and related data format. Using an Envoy proxy filter, we were able to define a mapping from JSON formats into the internally expected protobuf data format. This mapping is used to accept incoming individual requests with JSON payloads, transform the data into protobuf format for internal processing, transform the results back into JSON, then return the processed response via an individual response to each incoming API call. These transformations are processed automatically by the extended Envoy proxies incorporated into Istio and thus require much less effort than writing code to explicitly perform data transformations within either the search service or its consumers.
This allows portions of the monolith (or eventually other microservices) that use JSON data to send it to the search microservice as is. This was particularly helpful to the ZoomInfo Enterprise APIs, allowing the API processing code to forward search-related request data directly to the search microservice in JSON and get response data it understands in the reply sent back. It also made it very easy to test the service using tools like Postman and for code written in languages other than Java to directly interact with the search microservice.
Namespaces
As noted above, Istio provides a mechanism for defining traffic rules to route specific requests to specific microservice instances or groups of instances within a virtual namespace. This allows ZoomInfo to easily stand up instances specifically for testing particular pull requests (PRs) so the testing happens in isolation without any possibility of disturbing other requests or of having test results corrupted by unintended other traffic.
Setting this up was extremely easy; a short YAML configuration file indicates that traffic including a header specifying a PR identifier is sent to an instance including that same PR identifier in its address as follows:
Istio even allows you to set up these isolated namespaces but, if they are no longer available, to send the designated traffic back to the general production service pool (by defining a default virtual service without any header matching). This means that folks can start developing against functionality that’s still in the test or review phases and their code won’t automatically break if the related PR is merged and those test instances are taken down.
Downsides of Using Istio
While Istio has a lot of offer, it does have some drawbacks. The biggest is that it’s very new. This comes with the risk of more rapid future change than products that have already built up large user bases that typically lead to small, incremental changes to a product. It also means that it hasn’t been very widely adopted yet and there aren’t very many experts out there. With more popular tools that have been around for a long time, it’s often easy to get answers to questions just through a quick online search or by asking a question at Stack Overflow or similar community support sites. With Istio, figuring out solutions to issues and challenges that cropped up during the development process proved more difficult. ZoomInfo was on the leading edge of the technology and thus there wasn’t much general knowledge out in the wider world.
Because ZoomInfo uses a beta version included inside our cloud provider’s version of Kubernetes, we were able to leverage our cloud support contract to get help and advice on implementing Istio. If you have a support option of this sort, we recommend taking advantage of it if you plan to try Istio or any other new cloud tools or technology.
Final Thoughts on Istio
While there is some risk involved in using such a new product and it would be nice to have more pervasive support options, ZoomInfo has been very happy with its choice to use Istio. In addition to load balancing, it provided easy and fast mechanisms for adding application-to-application authentication and authorization, supporting REST API services and automatically converting them to and from the protobuf format actually expected by the microservice, and easily and automatically standing up isolated test environments for each pull request against the master code branch.
We definitely recommend using Istio as part of your microservice tool chain.