Hace ya casi tres años que comenzó el boom de las arquitecturas de microservicios. Todavía recuerdo, allá por 2015, cuando redacté el que fue mi primer post sobre los componentes de la arquitectura de microservicios de Spring Cloud Netflix.

Con el paso del tiempo, la arquitectura ha ido madurando y se han ido incorporando por parte de Spring Cloud a la misma nuevas soluciones que solventan problemáticas típicamente cloud. Es el caso, por ejemplo, de Sleuth, Zipkin, Contract

Pero hoy en día la arquitectura está tendiendo a evolucionar hacia algo diferente. En este post vamos a analizar cuál ha sido el recorrido de la arquitectura de microservicios hasta ahora y cuáles son las herramientas y tecnologías que nos acompañarán en el futuro.

Episodio 1: el nacimiento de los microservicios

Para ir a los orígenes, debemos remontarnos a principios de 2015 cuando el concepto ‘microservicio’ comenzó a sonar con fuerza en España.

Aunque a nivel global empezó a tomar relevancia meses antes, como podemos ver en esta gráfica que representa el número de búsquedas en Google de ‘microservice’:

A día de hoy, está en su punto más álgido, aunque todavía tiene recorrido ya que aún hay muchas empresas que, no solo no han implantado microservicios, sino que incluso no saben qué son.

El primer stack de microservicios que se dio a conocer, o que alcanzó una relativa popularidad, fue el stack de Netflix, que fue adoptado por Spring como su principal solución para Cloud bautizándolo como spring-cloud-netflix y que vio la luz en su primera release en Marzo de 2015.

A día de hoy sigue siendo, de todas las soluciones para cloud que incorpora Spring, el más seguido y el más popular:

Además, las otras dos soluciones (Consul y Zookeeper) utilizan a su vez diversas piezas del stack de Netflix como Zuul, Ribbon e Hystrix. Inicialmente la arquitectura estaba compuesta por las siguientes piezas:

Para quien todavía no las conozca, puede encontrarlas con más en detalle en este artículo sobre Microservicios Spring Cloud, los principales componentes en arquitectura.

Este conjunto de piezas, si bien parece grande, comparado con lo que estábamos acostumbrados a ver en arquitecturas monolíticas, nos resolvía las principales necesidades de una arquitectura distribuida: registro, configuración centralizada, balanceo, resiliencia ante el fallo…

Eso sí, lo hacía en la capa software, incorporando servidores dedicados para tales funciones (Eureka, Config-server y Zuul) y librerías que incorporábamos en nuestra aplicación (Hystrix y Ribbon).

Lógicamente, asociado a la utilización de microservicios, utilizábamos para el despliegue una solución de contenedores, en este caso, la que ya todos conocemos y la más popular del mercado: Docker.

Otro tema aparte es ya la solución de orquestación de contenedores. Nosotros fuimos unos early-adopters de Openshift 3, la solución de Red Hat basada en Kubernetes, que salió al mercado en Junio de 2015.

Pero la realidad es que, por aquel entonces, existían ya diversas soluciones para la orquestación de contenedores. Eso sí, ninguna estaba muy establecida y tampoco llevaban mucho en el mercado.

Episodio 2: establecimiento

Desde su surgimiento en 2015 las arquitecturas de microservicios enseguida alcanzaron gran relevancia, que ha ido incrementando a lo largo del tiempo.

Espoleadas por el éxito de las soluciones Cloud, como la principal solución arquitectónica para las mismas, ambas han recorrido de la mano el camino hasta aquí.

Como toda arquitectura o herramienta que alcanza el éxito, enseguida surgen en torno a la misma una serie de aplicaciones y librerías adicionales que cubren áreas de funcionalidad que inicialmente no se habían considerado.

Es el caso de la trazabilidad de peticiones, una necesidad habitual en sistemas distribuidos, que inicialmente no tenía solución más allá de una implementación manual.

Estas y otras necesidades se fueron plasmando en nuevas librerías que completaban nuestro ecosistema, estas son algunas de ellas:

Además la evolución también siguió, no solo por la parte de las librerías. Se empezaban a definir stacks estándar para otras funcionalidades tan cruciales como logging y monitorización.

Es el caso del stack EL(F)K (ElasticSearch - Logstash o FluentD - Kibana) para logging, que si bien son herramientas que ya existían en el mercado y se utilizaban para tales usos, se convirtieron en parte indispensable de estas nuevas arquitecturas aumentando también su popularidad.

Con todas estas nuevas herramientas/librerías gozábamos de un ecosistema mucho más completo y a la vez mucho más complejo que, ahora sí, cubría prácticamente todas las necesidades que teníamos.

A su vez empiezan a surgir necesidades de comunicación asíncrona no bloqueante en las arquitecturas de microservicios, situaciones que a falta de una solución pura reactiva en Spring se suelen abordar con Vert.x.

De hecho, esta ausencia de solución ha sido la que ha provocado que recientemente se haya incluido soporte para reactividad en Spring 5.

Episodio 3: the rise of Kubernetes

Como comentamos previamente cuando surgieron estas nuevas arquitecturas realmente no había muchas soluciones de orquestación de contenedores establecidas en el mercado.

Kubernetes, Openshift, Docker Swarm, todas vieron la luz en su versión 1.0.0 durante 2015, Mesos en 2016… No existía una solución dominante en el mercado.

El paso del tiempo nos ha ido dejando el que parece un claro dominador, y ese es Kubernetes, o las soluciones basadas en Kubernetes como el propio Openshift.

Tanto es así, que ya podemos encontrar soluciones gestionadas de Kubernetes en diferentes plataformas: en Google como es lógico (ya que fueron los creadores de Kubernetes) con Kubernetes Engine, pero también en Amazon con AWS EKS como en Azure con AKS.

Así mismo algunas de las funcionalidades que comentamos al principio del post como balanceo de carga, registro, configuración centralizada llevadas a cabo por Ribbon, Eureka y Config Server son también proporcionadas por los PaaS. Entonces ¿Por qué utilizar las proporcionadas por Spring Cloud Netflix?

Esta es una pregunta con la que nos han asaltado diversos clientes. La solución es sencilla: en las etapas iniciales de esta arquitectura no existía una solución de orquestación establecida en el mercado.

El incluir dichas piezas (Eureka, Ribbon...) en la arquitectura software hacía que esta fuese mucho más portable. Al estar estos servicios incluidos en los propios artefactos, la aplicación podía ser movida entre diferentes soluciones Cloud sin preocupación de quedarnos sin estos servicios transversales.

Así mismo las soluciones proporcionadas por Spring Cloud Netflix tienen mucha más potencia que las típicamente ofertadas por las soluciones Cloud. Estas son algunas características adicionales que proporcionan:

Pero, obviamente, les sacaremos partido en la medida en las que las utilicemos. Es como el que compra un Ferrari de 670 CV para no pasar de 120km/h en la autovía, podría utilizar tranquilamente un utilitario.

De forma similar, tenemos una arquitectura con todas esas posibilidades, pero no les sacamos partido, que es lo que suele ocurrir en la mayoría de los clientes: no necesitan unas funcionalidades tan avanzadas de la arquitectura.

En la actualidad, ante esta perspectiva en la que Kubernetes parece ser la solución Cloud dominante en el mercado, y donde muchas de las necesidades inherentes a sistemas distribuidos están cubiertas por el propio PaaS, tiene sentido que este asuma esa responsabilidad.

De hecho, si pensamos en la filosofía PaaS esa es su finalidad: abstraernos de funcionalidades/recursos de más bajo nivel para que la aplicación pueda centrarse en la lógica de negocio. Y todas estas funcionalidades está claro que no son del ámbito del negocio.

Esto nos permite desacoplar nuestra aplicación, es decir, nuestra lógica de negocio, de la gestión de las necesidades estructurales inherentes a la naturaleza distribuida de la misma haciendo así más explícita la separación entre las diversas capas del sistema.

Estos son las funcionalidades estructurales de Spring Cloud Netflix que Kubernetes puede absorber:

Registro, balanceo y healthcheck (Eureka y Ribbon)

Kubernetes tiene constancia de cada nuevo Pod que se levanta en el sistema. Pero a diferencia de la combinación Eureka + Ribbon, el balanceo no se hace en cliente por lo que no es necesario que la aplicación conozca todas las instancias existentes de un servicio (esto lo hace a través del cliente Eureka).

Lo que la aplicación conoce es la capa Service de Kubernetes que será una abstracción que aglutine las instancias de un servicio. De esta forma el cliente invoca dicha capa de servicio, que mantendrá una dirección constante y que será la que realice el balanceo a la instancia destino concreta.

Kubernetes también se encargará de realizar healthchecks de forma periódica para comprobar la salud de las instancias. En el caso de Eureka era a la inversa, las instancias eran las que notificaban su correcta disponibilidad al servidor.

Configuración centralizada (Config-server)

Desde las últimas versiones de Kubernetes tenemos disponibles los configmaps. Estos nos permiten tanto almacenar propiedades individualmente, como variables de entorno, como ficheros de propiedades (ya sean locales o remotos).

Estas propiedades pueden ser utilizadas desde en la definición de los pods hasta en un volumen incorporado al contenedor, de forma similar a los secrets.

Incluso ante la situación de tener que migrar a una solución no basada en Kubernetes, la realidad es que hoy en día la mayoría de los PaaS proporcionan servicios similares.

No obstante, siguen existiendo varias funcionalidades que hoy en día no puede cubrir Kubernetes al nivel que lo hace Spring Cloud Netflix, lo que no nos permitirá hacer una separación completa.

Tales funcionalidades son la gestión del error en cascada, el API Gateway, trazabilidad de peticiones… y ahí es donde entramos en el que será el siguiente gran paso en arquitecturas de microservicios.

Episodio 4: the new kid on the block

Si pensamos cuál es la parte de las arquitecturas de microservicios que más problemas nos da, estoy seguro de que todos los que hayamos trabajado con ellas coincideremos en que es todo lo referente a la red. En concreto todo lo referente a latencias, gestión de fallos en llamadas remotas, balanceo, trazabilidad de peticiones, llamadas a instancias inexistentes o caídas…

La responsabilidad ante estas situaciones está dividida entre las diferentes capas. Por ejemplo, el PaaS (o servicio de registro) es responsable de proporcionarnos una lista de instancias saludables. Hystrix es responsable de gestionar las llamadas externas para controlar timeouts y gestionar situaciones de fallo...

Y aquí, en esta zona gris, anidado entre la capa de aplicación y el PaaS, en el punto donde más problemas surgen, es donde encontramos la que será la nueva revolución en arquitecturas de microservicios.

Entra Istio

Istio es una solución de service-mesh basada en la experiencia y buenas prácticas de Google en la ejecución de servicios a gran escala. Desarrollada en conjunto con IBM y Lift, fue liberada como Opensource en Mayo de 2017 y actualmente va por la versión 0.7.1 correspondiente a Marzo de este año. Desde la versión 0.3.0 planean liberar una versión cada mes.

Para los que no estáis familiarizados con el concepto de service-mesh aquí os dejo una definición que me parece de las mejores:

"A service mesh is a dedicated infrastructure layer for making service-to-service communication safe, fast, and reliable. If you’re building a cloud native application, you need a service mesh”, Blog Buoyant.

Service Mesh es un concepto que ha empezado a pegar mucho en el último año. Prueba de ello es que grandes compañías como Paypal o Ticketmaster, con gran cantidad de tráfico, ya lo están utilizando y que Envoy y Linkerd ya forman parte de la Cloud Native Computing Foundation.

Pero antes de entrar en por que va a cambiar el mundo de los microservicios, veamos cómo lo va a conseguir.

Istio es una herramienta que recoge funcionalidades que hemos situado tanto en su capa inmediatamente inferior (PaaS) como en la inmediatamente superior (aplicación) para responsabilizarse de la gestión de todo lo referente a las comunicaciones de red.

En realidad Istio no introduce nuevas funcionalidades, sino que mueve las ya existentes a una capa intermedia en la que se situará.

Para ello, lo que hace es colocar un proxy al lado de nuestra aplicación que interceptará todas las comunicaciones de red de la misma gestionándolas para proporcionarnos fiabilidad, resiliencia y seguridad sobre las mismas.

La colocación de este proxy al lado de nuestra aplicación es conocido como el patrón sidecar-proxy. Esto, bajado a tierra, consiste en, por ejemplo en Kubernetes, dentro del pod en el que se despliega el contenedor de nuestra aplicación, desplegar un contenedor adicional con dicho proxy como se puede ver en la siguiente imagen:

Istio utiliza Envoy por defecto como sidecar-proxy, que acompañará a todos nuestros microservicios. Existe también la posibilidad de utilizar Linkerd para el plano de datos.

El hecho de que Istio se ejecute en un contenedor separado de nuestra aplicación hace que exista un desacople mayor entre el propio service-mesh y la aplicación.

Además, al recoger funcionalidades de librerías como Ribbon e Hystrix, libera a la aplicación completamente de la gestión de las complejidades estructurales.

Al encargarse de todo lo referente a comunicaciones de red, Istio nos proporciona una gran cantidad de funcionalidades, entre las que se encuentran las siguientes:

Puede desplegarse sobre diferentes infraestructuras: Kubernetes, entornos basados en registro en Eureka o Consul y próximamente en CloudFoundry y Mesos.

Si observamos al detalle sus funcionalidades, vemos que recoge muchas de las responsabilidades de la suite de Netflix: gestión de circuit breaking y timeouts de Hystrix, balanceo de peticiones de Ribbon...

Si queréis profundizar más en el tema recomiendo este artículo que incluye una muy buena comparativa entre Hystrix y Envoy/Istio.

Además, Istio se integra con algunas soluciones ya utilizadas por Spring Cloud como es el caso de Zipkin y el hecho de que puede funcionar en entornos que utilicen Eureka como registro.

También se integra con otras soluciones existentes en el mercado para almacenamiento de métricas, logging, gestión de cuota… como Prometheus, FluentD, Redis...

El hecho de que justamente cubra la funcionalidad de proxy inverso, circuit breaking y gestión de timeout que realizan Zuul e Hystrix, que son las dos herramientas que comentamos que no podía reemplazar Kubernetes lo hace un candidato para terminar de jubilar a la suite de Netflix.

¿Por qué es el siguiente paso en arquitecturas de microservicios?

Hemos comentado (por encima) qué funcionalidades nos aporta Istio y un poco su situación general: origen, política de versiones…

Pero lo realmente interesante es analizar por qué creemos que se convertirá en una de las mejores soluciones del mercado, si no quizá la más importante. Recopilamos algunos factores:

Service-mesh está abriéndose paso en el mercado

Existen ya soluciones de service-mesh en el mercado, como Linkerd, que cada vez se están estableciendo más (ya comentamos su inclusión bajo el paraguas de la Cloud Native Computing Foundation). Además, están saliendo también más soluciones nuevas como Conduit.

Envoy forma parte de CNCF

Remarcamos una vez más la importancia de Cloud Native Computing Foundation como aglutinador de los proyectos más relevantes en el entorno Cloud (solo hay que ver los proyectos bajo su paraguas).

Y Envoy, el proxy utilizado por Istio para su sidecar es uno de ellos. Envoy fue liberado Open Source por Lyft después de tenerlo en producción más de un año gestionando más de 100 servicios en más de 10000 VM procesando 2M de peticiones por segundo.

Esto no hace más que enfatizar los sólidos pilares que están utilizando en Istio para su construcción.

Funcionalidades complejas y cruciales a un mayor nivel de abstracción

Todo lo que rodea la gestión de red suele ser uno de los mayores quebraderos de cabeza de los ecosistemas de microservicios.

Se trata de funcionalidades que son cruciales para el buen funcionamiento del sistema como conjunto, pero que muchas veces son complejas de configurar y gestionar.

Istio nos proporciona una herramienta de gran potencia que encapsula todas estas problemáticas y su gestión, permitiendo además abstraer tanto a las aplicaciones como al propio PaaS de estas complejidades.

Muy buena integración con Kubernetes

Las soluciones basadas en Kubernetes son las que están tomando más relevancia en el mercado. Istio, además de ser desarrollado inicialmente por Google (al igual que Kubernetes), utiliza una sintaxis muy similar.

Extiende el API de Kubernetes para añadir nuevos tipos de recursos y atributos, pero sigue manteniendo su misma esencia.

Todo esto hace que, a pesar de los nuevos recursos y conceptos, para alguien que haya trabajado previamente con Kubernetes el API y las interacciones con Istio sean fácilmente reconocibles y que inmediatamente tenga una sensación de familiaridad con el mismo.

En el RoadMap de Openshift

Como comentamos Openshift está basado en Kubernetes, e Istio tiene muy buena integración con el mismo además de provenir de Google, todo ello parece indicar que Istio será una solución también ofrecida en Openshift.

Ya existen posts y tutoriales en los propios sites de Openshift sobre cómo integrarse con Istio.

Ecosistema de microservicios políglota

Una de las características de las arquitecturas de microservicios es que deben ser políglotas. Sin embargo, en la actualidad, la suite de Netflix solo está disponible para Java, por tanto si tenemos un microservicio en cualquier otro lenguaje y queremos registrarnos en Eureka, tendremos que picarnos nosotros mismos la integración.

De forma similar no podremos utilizar librerías como Hystrix y a falta de una librería similar en el lenguaje que utilicemos, tendremos que picarnos nuestro propio circuit breaker.

Por el contrario Istio al utilizar el patrón sidecar es completamente independiente del lenguaje en el que esté escrito la aplicación. Istio simplemente interceptará las llamadas independientemente del lenguaje que las haya generado.

Existen muchos motivos por los que Istio será el siguiente gran movimiento en las arquitecturas de microservicios y por los cuales debemos empezar a implantarlo.

Existe al mismo tiempo un motivo que frena su avance y es que, a pesar de ser un producto robusto y estable, casi todas sus funcionalidades e integraciones se encuentran actualmente en fase alpha o beta.

Puede que actualmente sea un poco temprano para adoptar Istio, pero desde luego apunta maneras, con un roadmap muy ambicioso y ha llegado para quedarse.

Conclusión

Hemos recorrido el pasado reciente de las arquitecturas de microservicios y hemos apuntado a su futuro. Sea Istio, Linkerd, o incluso Conduit quien domine el mercado, lo que está claro es que los service-mesh están pegando fuerte.

Hoy en día no hay muchas empresas que los hayan incluido dentro de su stack, algunas ni siquiera dentro de su roadmap. Pero no tenemos más que echar la vista atrás y recordar lo que ocurrió con Docker, siendo una tecnología relativamente joven llegó al mercado y en pocos años lo copó convirtiéndose hoy en día en una herramienta indispensable.

Con el creciente interés por los service-mesh, el número de nuevas soluciones que están surgiendo y la potencia y flexibilidad de las mismas, parece lógico pensar que dentro de un par de años todo aquel que esté desplegando una aplicación distribuida en Cloud lo estará haciendo con un service-mesh de por medio.

Fuentes

  1. Google Cloud Platform Blog: Istio: a modern approach to developing and managing microservices.
  2. Blog de Istio: Introducing Istio.
  3. Documentación de Istio.
  4. Blog de Buoyant.
  5. Blog de Christian Posta: Comparing Envoy and Istio Circuit Breaking With Netflix OSS Hystrix.
  6. Documentación Kubernetes: Configure a Pod to use a ConfigMap.

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.