Ribbon Integration with Kubernetes

As a local balancer, Ribbon allows you to invoke services in the CaaS infrastructure transparently regardless of the number of Pods behind the service. In infrastructures with Kubernetes, you can also do without a discovery service (such as Eureka, Consul ...) since Ribbon uses the Kubernetes API to discover the Pods.

To integrate Ribbon, you must add the Ribbon dependence to your Maven project:

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>

Add the @LoadBalanced annotation to the RestTemplate:

@LoadBalanced @Bean public RestTemplate restTemplate() { return new RestTemplate(factory()); }

Each Ribbon client is associated with a service name, so in your application, you must declare as many Ribbon customers (No RestTemplate, these only need to be @LoadBalanced) as balanced destinations you have. This can be done in the SpringBootApplication class itself to which you also need to add the @EnableDiscoveryClient annotation.

@RibbonClients(value = { @RibbonClient(name = "${connection-protocol-redsys.protocolredsys.service}", configuration = RibbonConfiguration.class), @RibbonClient(name = "${connection-protocol-sat.protocolsat.service}", configuration = RibbonConfiguration.class), }) @EnableDiscoveryClient public class BackendBusinessAuthorizationApplication { public static void main(String[] args) { SpringApplication.run(BackendBusinessAuthorizationApplication.class, args); } }

As you can see, you have the @RibbonClient name parameterized and you indicate a Configuration class for each client: RibbonConfiguration.class

In this class, a basic configuration would be:

  • The declaration of a Bean that declares the rule to follow to choose a destination (specific Pod) behind a service. In this case it is based on response time, although there are many others, and they can even be programmed ad-hoc, such as RoundRobin, Geographical affinity...

  • The declaration of a Bean that will periodically ping the Pods behind the service to identify which ones are "alive".

The Ping's previous configuration forces each destination to implement a controller that responds to the Ping url:

Once you have all this programmatic configuration, the application is ready to use Ribbon locally balancing for the services indicated in the declared RibbonClients. The following is to configure the services:

  • Local Development. You do not need to have any discovery service, you can declare the service in the application.yml:

As you can see, this is done to declare two services with Ribbon: protocolredsys and protocolsat, which are those indicated in the url as a service name and those that were included parameterized for the name attribute in the @RibbonClient in the SpringBootApplication class. Thus, protocolredsys points to localhost:9866 and protocolsat to localhost:9890

  • Deployment in Kubernetes. In this case, the application-docker.yml is configured so that the name of the services can be passed as an environment variable:

To use Ribbon in Kubernetes, add the dependency through a specific profile, so that it is added only if the destination of the compile is a CaaS kubernetes:

 

 

In the latest versions of Spring Cloud, this dependency is already included in the starter itself, so you don’t need to indicate version. If you are using an old version of Spring cloud, please check consult the version of this library to use, since not all of them are valid.

 

The next thing is to enable the service in Kubernetes. By default, a service is created for each workload, but this service points to port 42. Therefore, you need to create a service that points to the correct port exposed by your pods:

Once the service is created, you can configure the environment variables indicated in your application’s application-docker.yml:

And the integration of Spring Cloud and Kubernetes will be in charge of balancing between the different Pods behind each service.

Important note:

It is very likely that, when starting the application for the first time, you will have a permission error like this one:

This is because the Ribbon library for Kubernetes invokes the Kubernetes API and does not have permission. To give it permission, you need to enter the kubernetes console and create a role that allows the user account that runs your workload to consult the Kubernetes API with:

 

 

Where:

  • testloadbalancing:default --> Is the role’s name.

  • -clusterrole=cluster-admin --> Are the role’s permissions.

  • -serviceaccount=testloadbalancing:default --> Is the user’s account.

 

The three parameters can be identified in the error message itself.