Managing Large Microservices-style Applications using Nirmata
In this post I will discuss a powerful new feature in Nirmata, called Application Dependencies.
In Nirmata, an Application is composed of one or more services. A traditional application may have a few services, one for each tier, while a microservices-style applications may have dozens of services. Nirmata already has a rich application modeling capability where developers can specify everything needed to deploy the application in types of environments. However, as customers started modeling larger and more complex applications, we noticed that a single application could become cumbersome to manage. Application Dependencies allows users to decompose a large application into smaller inter-dependent applications. Beyond modeling, Application Dependencies also allow controlling traffic flows across application stacks.
Let’s discuss some use cases where this is helpful:
Enterprise DevOps pipelines are often composed of at least three environment types: development, staging and production. It is quite common for our customers to have many more, including environments dedicated for teams like security and performance tests and sometimes sandboxes per developer. The cost of deploying all the services of an application in several environments can quickly add-up.
Container technology inherently enables savings by allowing cloud infrastructure resources to be shared across multiple environments. With containers, you can now pack services from multiple environments on a shared pool of virtual machines. This may not be the case if your services require fixed ports. In any case, if you need to deploy ten instances of your application you will need ten times more memory, CPU and disk.
This start looking like a waste of resources, especially when you realize that most developers actively work on a handful of services, and yet they may require several services that they never touch for testing. Does each developer really need their own copy of the database? Do they really need their own Elasticsearch cluster? Probably not!
Larger applications may be composed of several separate application stacks that communicate with each other, and may have separate teams responsible for each stack. While some level of testing can be performed at the stack level, very often developers will need to test and troubleshoot the entire application.
To address these problems, Nirmata introduced the possibility of sharing application runtimes across multiple environments and users. Now your developers can share environments running common services such as a databases, a messaging bus, analytics cluster, or any part of the application they don’t touch.
It is also important for your team to define which environments are shared and who can access these shared environments. For instance, you don’t want your developers performing tests, to inadvertently access the production database.
Application Dependencies in Action
We are going to take the example of shopping a demo application called “shopme” which relies on a set of shared services made of Kafka, Zookeeper and MongoDB. We are going to deploy the shared services in only one environment and then shared these services between two other environments: dev-test and staging.
The blueprint of the shared services initially looks like this:
Note that initially, there is no application dependency defined. The shopme application is initially define as:
Now, let’s define that shopme depends on the shared services blueprint:
When going back to the shared services blueprint, we can verify that the two blueprints are now linked:
We can now deploy the shared services environment:
We see that our shared services are now running. We can then deploy the shopme staging environment:
In the next tab, we can specify the dependency with the shared-services environment:
The shopme application is now running in our staging environment and it can communicate with the shared services.
We can deploy the shopme application in a dev-test environment in the same manner. At this point we have two copies of the shopme application sharing the same backend services: Kafka, Zookeeper and MongoDB.
You can use Nirmata routing policy to define precisely the traffic flows across service instances within an environment or across environments. It is not very common for all services of an environment to communicate with all the other services in that environment. Similarly, it is not always the case that all services of an environment need to communicate with all the services of a shared environments.
You can edit the routing policy to control the traffic flows within an environment:
In this example, we specified that the payment service can communicate with the order service and that the wishlist service cannot communicate with the payment service. In the same manner, you can control traffic flows across environments:
In this example, we have specified that the orders service from the shopme-staging environment can communicate with the mongodb service from the shared-services environment. We also defined that the catalog service cannot communicate with the kafka service.
Application dependencies will help your team optimize cloud infrastructure usage. It will also increase the agility of your development teams by letting them share common services and by allowing them to focus their efforts on the services they actively develop. All these benefits are provided with the usual level of security, control, and ease of use that you are accustomed to with Nirmata!