Brothers in arms.
We all are aware of what Spring Boot, Spring Cloud, and Kubernetes are and why they are used. They are popular these days and can be plugged and used for many different use cases. This article is specially focused on Spring Cloud Kubernetes. This article is written with the assumption that you are aware of these technologies and have some experience with it, especially Spring Cloud and Kubernetes.
I am writing this article to share my experience in integrating Spring Cloud with Kubernetes. Spring Cloud Kubernetes is a new project from Pivotal, and I faced many challenges running even the simplest programs flawlessly at first. Therefore, my intent here is to start with an example of decomposed and isolated Spring Boot component running with Spring Cloud Kubernetes and then transition it from a desktop application to a mature state. If you are a veteran in this area, then this article is not for you. However, if you are new and eager to learn something exciting then please join the ride.
Here is the breakdown of pre Spring Cloud Kubernetes project architecture:
Spring Boot :- It’s a Java based Open source framework for writing microservices based application.
Spring Cloud :- Helps you build some of the common patterns of distributed systems, for example:
- Configuration Management
- Service Discovery
- Circuit Breaker
- Control Bus
This Integration leads to boiler plate patterns and you can quickly stand up a service using these patterns. In the beginning, Spring Cloud was built around Netflix OSS components like Zuul, Hystrix, Ribbon, Eureka etc. Today Spring Cloud project has its own components for Netflix replacement that plug very well along with Kubernetes, for example :-
- Spring Cloud Gateway :- Replacement for Zuul
- Spring Cloud Circuit Breaker :- Replacement for Hystrix
- Spring Cloud Load Balancer :- Replacement for Ribbon
Kubernetes :- It’s an Orchestration engine that helps running and managing your containerized applications. I will not go into details on this here as that would warrant an article on its own.
So, why Spring Cloud Kubernetes? Why build another framework if you already have all of the required parts in place? Well, we know Kubernetes can :-
- Run a discovery across all namespaces
- Provides Config and Secret Stores
- Provide more granular control over access of containers
- Can Load balance calls between containers
- And the list goes on…
These features are managed and accessed via Kubernetes Master API. However, what If you could have a framework that can directly coordinate with Kubernetes API and help your application achieve all boiler plate patterns without deploying any separate dedicated application? Does that sound exciting? If you are not convinced, then let’s start with an example.
I am demonstrating this example as a starting point. I will add more elements to it as I go and will try to make it more robust with all bells and whistles.
You can find the code at my Git Hub Repo :-
Scenario we are representing through this example:
We are representing an online shopping process where a Shopping cart service is communicating with the Item service to get the list of items added to the cart.
Here is the deployment architecture of the application we are trying to build:
The above is the visualization of the online shopping process where a Shopping cart service is communicating with the Item service to get the list of added Items. While it may not be the best distributed design example, it will help us understand the integration. As I mentioned above, my intent is to start here and then make it more logical and robust.
Alright, now that we have the basic visualization in mind, let’s get to the turf and see how these components can communicate with each other from an operation perspective.
STEP 1: THE DEPENDENCIES
Here, I have included all dependencies from kubernetes starter package, but you have the option to trim it down to what you want specifically for your project.
STEP 2: THE DISCOVERY PLUGIN
We need Cart Service to make a REST call to Item Service and for that, Item Service has to be discovered. So the magic begins here.
Let’s give a name, assign a port to your service, and make it discoverable across the cluster in different namespaces. Add the following to your application.yaml of your boot app.
STEP 3: SET UP PROXY
Since our components will be communicating with each other, we need a proxy that can do lookup for the service and make a call at the exposed endpoint. The Feign Client name should match exactly with the kubernetes service name.
STEP 4: WHERE RUBBER MEETS THE ROAD
To make a feign call where Spring Cloud Kubernetes has to do a lookup for the Proxy Service, it will communicate with Kubernetes API so that it can retrieve the list of Pods’ addresses exposed to the mapped service. This is where we need to provide access to our component services by providing permissions. This is done by setting the Cluster Roles and Binding it via Cluster Binding.
Create a namespace:
Create Cluster Role and Binding:
I have used cluster-admin role as an example so when you try this project you will not get in to any sort of permission issues. Cluster-admin will let you perform any action on any resources. Of course, this is not how you will assign permissions to your real kubernetes objects. You definitely will set the permissions at a very granular level.
STEP 5: So, what will your component deployment look like?
Services exposed are of node port type. Each of the service is deployed in its own namespace.
Our Deployment looks like this:
One last piece of the puzzle is the RibbonConfiguration Class. Unfortunately, the discovery process for Ribbon Client does not work and It can not communicate with services deployed to other namespaces. However, we have DiscoveryClient at our rescue. Logically, Ribbon auto-config for Spring Cloud kubernetes [spring.cloud.kubernetes.discovery.all-namespaces ]should work, but it doesn’t and so a workaround needs to be adopted. The workaround basically consists of overriding the Ribbon auto configuration and use Discovery client instead.
This also needs to be set at your main class.
That’s it! Deploy your config to create namespace, permissions and deploy your application components and access the service deployed to the cluster at Node Port.
In this example, it’s the Shopping cart making Feign call to Item Service. You will get the Shopping Cart service Node Port IP and access the service to validate.
One may argue about drawing the line between the concerns by separating the Infrastructure and application code. Spring cloud Kubernetes is a very popular project today and at this date I don’t see its replacement (*My opinion). In the upcoming article, I will plug the application containers to a Mysql database, introduce gateway and bring in Config Map and Secrets which this application will use for config store related to application and DB.