Integración de Ribbon con Kubernetes

Como balanceador local, Ribbon te permite invocar servicios en la infraestructura de CaaS de forma transparente, no importa la cantidad de Pods detrás del servicio. En infraestructuras con Kubernetes, también se puede prescindir de un servicio de descubrimiento (como Eureka, Consul, etc.) ya que Ribbon utiliza la API de Kubernetes para descubrir los Pods.

Para integrar Ribbon, debes agregar la dependencia de Ribbon a tu proyecto Maven:

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

Añade la anotación @LoadBalanced a RestTemplate:

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

Cada cliente Ribbon está asociado con un nombre de servicio, por lo que en tu aplicación debes declarar tantos clientes Ribbon (sin RestTemplate, éstos solo deben ser @LoadBalanced) como destinos balanceados tengas. Esto se puede hacer en la propia clase SpringBootApplication, a la que también debes agregar la anotación @EnableDiscoveryClient

@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); } }

Como ves, tienes parametrizado el nombre @RibbonClient y le indicas una clase Configuration a cada cliente: RibbonConfiguration.class

En esta clase, una configuración básica sería:

  • La declaración de un Bean que declara la regla a seguir para elegir un destino (Pod específico) detrás de un servicio. En este caso, se basa en el tiempo de respuesta, aunque hay muchos otros, e incluso se pueden programar ad-hoc, como RoundRobin, afinidad geográfica…

  • La declaración de un Bean que hará ping periódicamente a los Pods detrás del servicio para identificar cuáles están "vivos".

La configuración anterior de Ping obliga a cada destino a implementar un controlador que responda a la URL de Ping:

 

Una vez que tengas toda esta configuración programática, la aplicación está lista para usar Ribbon balanceando localmente para los servicios indicados en los RibbonClients declarados. Lo siguiente es configurar los servicios:

  • Desarrollo Local. No necesitas tener ningún servicio de descubrimiento, puedes declarar el servicio en application.yml:

Como ves, esto se hace para declarar dos servicios con Ribbon: protocolredsys y protocolsat, que son los indicados en la url como nombre de servicio y los que se incluyeron parametrizados para el atributo name en el @RibbonClient en la clase SpringBootApplication. Por lo tanto, protocolredsys apunta a localhost:9866 y protocolsat a localhost:9890

  • Despliegue en Kubernetes. En este caso, application-docker.yml está configurado para que el nombre de los servicios se pueda pasar como una variable de entorno:

Para usar Ribbon en Kubernetes, agrega la dependencia a través de un perfil específico, de modo que se agregue sólo si el destino de la compilación es un kubernetes de CaaS:

 

En las últimas versiones de Spring Cloud, esta dependencia ya viene incluida en el propio starter, por lo que no hace falta indicar versión. Si estás utilizando una versión antigua de Spring cloud, consulta la versión de esta biblioteca a utilizar, ya que no todas son válidas.

 

Lo siguiente es habilitar el servicio en Kubernetes. De forma predeterminada, se crea un servicio para cada carga de trabajo, pero este servicio apunta al puerto 42. Por lo tanto, debes crear un servicio que apunte al puerto correcto expuesto por tus pods:

Una vez creado el servicio, puedes configurar las variables de entorno indicadas en el archivo application-docker.yml de tu aplicación:

Y la integración de Spring Cloud y Kubernetes se encargará de balancear los distintos Pods que hay detrás de cada servicio.

Nota importante:

Es muy probable que, al iniciar la aplicación por primera vez, te encuentres con un error de permisos como éste:

Esto es porque la biblioteca Ribbon para Kubernetes invoca la API de Kubernetes, y no tiene permisos. Para darle permisos, debes ingresar a la consola de kubernetes y crear un rol que permita que la cuenta de usuario que ejecuta tu carga de trabajo, consulte la API de Kubernetes con:

 kubectl create clusterrolebinding testloadbalancing:default --clusterrole=cluster-admin --serviceaccount=testloadbalancing:default

 

Donde:

  • testloadbalancing:default --> Es el nombre del rol.

  • -clusterrole=cluster-admin --> Son los permisos del rol.

  • -serviceaccount=testloadbalancing:default --> Es la cuenta del usuario.

 Los tres parámetros se pueden identificar en el propio mensaje de error.