En el primer post analizamos la arquitectura de OSE, sus recursos y los comandos más habituales. Ahora que ya conocemos sus posibilidades, en esta segunda entrega vamos a enfocarnos en un caso de uso real: el despliegue de una arquitectura de microservicios.

Analizaremos la problemática técnica que ha surgido y las situaciones a las que nos hemos tenido que enfrentar, así como la duplicidad de responsabilidad que existe entre OSE y dicha arquitectura software. Finalmente se incluye una sección final para que os podáis descargar una versión de OSE y “jugar” vosotros con ella.

Caso de uso: arquitectura de microservicios

En este caso la arquitectura de software desplegada es la de microservicios construida con spring-cloud-netflix compuesta por los microservicios estructurales ya conocidos como eureka, cloud-config…

En esta sección pretendemos analizar la integración de esta arquitectura de software con Openshift y las problemáticas surgidas durante dicho proceso.

Spring-cloud-netflix vs Openshift

Si repasamos detalladamente las ventajas que nos aportan la arquitectura de spring-cloud-netflix y Openshift encontramos que algunas de ellas se solapan.

En este sentido es labor del arquitecto decidir si desea, por ejemplo, no utilizar dichas características de spring-cloud-netflix o sí, incluso siendo algunas proporcionadas por Openshift, desea mantenerlas.

La realidad es que ambas soluciones pueden coexistir. Así tenemos los dos siguientes casos:

Esta situación es en la que un microservicio deberá invocar a los demás. Para ello deberá conocer sus IPs o hostnames para poder invocarlos y éstas no deberán ser incluidas en código, ya que si una instancia se cae puede levantarse con otra IP o hostname, además de que no conocemos el número de instancias que se encontrará disponibles en un determinado momento.

En la arquitectura spring-cloud-netflix esta funcionalidad es proporcionada por Eureka, de forma que un microservicio conocerá en todo momento que otros microservicios existen en el ecosistema y sus direcciones para así poder invocarlos.

En Openshift cada microservicio se ejecutará en un pod, detrás de un servicio compuesto por un balanceador. De esta forma da igual el número de instancias que tengamos o cuáles sean sus direcciones, ya que se utilizará el nombre del servicio como dirección a invocar. El número de instancias existentes o sus IPs nos dan igual, ya que en código el nombre del servicio será el referenciado.

Así esta característica de Eureka está ya incluida en OSE, por lo que no nos sería necesario disponer de un Eureka. Eso sí, si utilizamos otras funcionalidades de Eureka, como por ejemplo la integración con spring-boot-admin para la monitorización de nuestro ecosistema de microservicios, entonces deberemos mantenerlo.

En esta situación disponemos de varias instancias de un microservicio y debemos decidir a cuál invocar.

En spring-cloud-netflix esta situación es gestionada por Ribbon que, integrado con Eureka, decidirá en el lado cliente en base a varios criterios qué instancia invocar.

En Openshift el propio servicio incluye un balanceador, de forma que si realizamos una petición al mismo, éste se encargará de balancear la carga entre las diversas instancias disponibles.

De la misma forma que en el caso anterior, la inclusión o no de Ribbon dependerá de cómo de complejo será nuestro balanceo, si vamos a utilizar un balanceo estándar o con Openshift será suficiente. Pero si queremos utilizar diferentes reglas de balanceo, o incluso crear las nuestras propias, o gestionar zonas… optaremos por incluir Ribbon.

Al final todo dependerá de las funcionalidades que aprovechemos de Eureka o de Ribbon. Si vamos a realizar un uso simple de los mismos podemos obviarlos y utilizar las funcionalidades proporcionadas por OSE, pero si vamos a aprovechar parte de su potencial no dudaremos en incluirlos.

Si se tiene un buen conocimiento de la arquitectura de microservicios y de spring-cloud-netflix, personalmente, recomiendo incluirlos ya que hacerlo no supone mucho tiempo y tendremos siempre disponibles todas sus funcionalidades.

Uso de IP en vez de hostname

Esta situación afecta al uso de Eureka y cómo los microservicios invocan a los otros. Por defecto cuando un microservicio se registra en Eureka utiliza como dirección su hostname, y es este hostname que utilizará Ribbon a la hora de invocarlo. Y aquí surge el problema. En Openshift los pods no resuelven el hostname de los demás pods, por lo que resulta imposible realizar una petición entre los mismos.

En este caso la solución pasa por utilizar la dirección IP en lugar del hostname, ya que en OSE un pod puede resolver correctamente la IP de otro.

Esta funcionalidad está actualmente soportada por Eureka. De esta forma si definimos la propiedad eureka.instance.prefer-ip-address=true y nuestros microservicios se registrarán en Eureka con su IP y así Ribbon podrá resolver la URL cuando la genere. La siguiente imagen muestra una sección del dashboard Eureka con microservicios registrados con IP.

1

Escalado de instancias de Eureka

En caso de que tengamos un entorno no productivo para nuestro trabajo del día a día con una única instancia de Eureka será suficiente. Pero si nuestra aplicación va a estar en producción deberemos configurar un cluster de Eureka para que en caso de que se caiga una instancia, nuestro ecosistema de aplicaciones pueda seguir funcionando. En artículos anteriores ya se explicó cómo configurar un cluster de Eureka.

Y aquí surge el problema. Es necesario conocer la IP en la que se encuentran las diferentes instancias de Eureka para incluirlo en la configuración de los microservicios (en la propiedad eureka.client.serviceUrl.defaultZone). Pero no podemos incluir la IP ya que no sabemos cuál se le asignará durante el despliegue. Es más, si nuestra instancia se cae y OSE levanta una nueva, ésta tendrá una IP diferente.

Una solución que se nos podría ocurrir es utilizar el nombre del servicio (incluyéndolo una o dos veces en la propiedad), pero esto tampoco funcionaría. En la configuración del cluster Eureka cada instancia que se levanta intenta comunicarse con sus hermanos para registrarse y sincronizar el registro de microservicios.

Si incluimos la URL del balanceador, éste podría derivarle la petición a la misma instancia que la ha realizado, por lo que el registro nunca estaría sincronizado. Esto provocaría que pudiese haber microservicios o instancias de microservicios registrados en una instancia de Eureka y no en otra.

Así, cuando un microservicio recuperase el registro de una instancia de Eureka, éste no estaría completo y, por tanto, no podría realizarse la petición a pesar de que el microservicio destino puede estar perfectamente disponible.

La solución a esta situación, aunque fea, es válida. Consiste en registrar un servicio por cada instancia de Eureka que deseemos tener. Así, detrás de cada servicio, habrá un único pod y no nos encontraremos con el problema asociado a que se balanceen las peticiones.

En esta situación utilizaremos el nombre de los servicios para configurar la propiedad eureka.client.serviceUrl.defaultZone, de forma que las instancias de Eureka podrán sincronizar su registro y los demás microservicios recuperarlo de forma correcta.

En la siguiente imagen se puede ver dicha situación en la consola de Openshift, con dos servicios creados eureka y eureka-replica, cada uno con un pod ejecutando el servidor.

2

Lógicamente, esto presenta otras dificultades, como el hecho de que nuestro número de instancias estará limitado. Es decir, podemos eliminar una instancia simplemente escalando su número de pods a 0, pero nunca podremos pasar de los dos servicios cada uno con una instancia (a menos que creemos otro servicio).

Es cierto que Eureka tampoco está pensado para escalar en tiempo de ejecución, ya que la propiedad eureka.client.serviceUrl.defaultZone deberá estar definida durante el arranque, no estando enfocado por lo tanto a cambios en el número de instancias del cluster (si bien es cierto que existe la posibilidad de cambiar este valor en tiempo real a través de las funcionalidades que nos proporciona spring-cloud-config).

Ahora prueba tú

Si queréis realizar vuestra propias pruebas con Openshift en la siguiente URL podéis encontrar un pequeño tutorial de varios comandos de Openshift, así como una imagen Vagrant para ejecutar Openshift Origin 3.0.

La variante ‘Origin’ no es exactamente igual que la versión ‘Enterprise’, pero para realizar vuestras pruebas y, como toma de contacto, os puede servir perfectamente.

Puede que cuando lo arranquéis el Panel de Control no sea igual a las imágenes mostradas en este post, eso es debido a que las imágenes de este post corresponden a la versión 3.1 y la imagen de Vagrant es de la 3.0. De todas formas ambos son fácilmente usables.

A continuación os presento una captura de dicho Dashboard para la versión 3.0:

3

Conclusión

Openshift es un PaaS que ofrece una amplia variedad de posibilidades, convirtiéndolo en una opción muy potente. Basado en tecnologías abiertas, nos permite una gran personalización gracias a la utilización de contenedores. Ofrece todas las posibilidades y ventajas que esperas encontrar en una plataforma cloud como recolección de métricas, autoescalado, alta disponibilidad…

Sus diferentes versiones permiten que desde un particular (versión 3 todavía no disponible para Openshift Online), empresas que no dispongan de infraestructura o empresas que quieran reutilizar la existente puedan migrar sus aplicaciones de forma sencilla a la nube.

Nuevo llamado a la acción

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.