Jugando con Istio: ‘The next big thing’ en microservicios (1/2)

En artículos anteriores hablamos de cómo service-mesh será el nuevo paradigma para la gestión de las funcionalidades estructurales de red en las nuevas arquitecturas de microservicios.

También hablamos de Istio, la solución de service-mesh creada en conjunto por Google, IBM y Lyft basada en la experiencia de Google ejecutando aplicaciones de gran tamaño durante años en producción.

Ahora que sabemos de la importancia de Istio, nos preguntamos ¿cómo es su arquitectura? ¿Cuáles son sus funcionalidades más importantes? ¿Cómo podemos llevar a cabo su configuración? Vamos a responder a estas y otras muchas preguntas más.

Arquitectura

Istio funciona utilizando el patrón sidecar que, como su nombre indica, es similar al concepto de un sidecar en una motocicleta.

En este patrón una parte de las funcionalidades/necesidades de la aplicación son trasladadas a un segundo componente desacoplándolas así de la aplicación original proporcionando aislamiento y encapsulación.

Esto nos permite proporcionar una funcionalidad adicional (llevar otro pasajero) desacoplada de la aplicación y que acompaña al elemento primario a lo largo de su ciclo de vida.

De forma similar, en el caso concreto del patrón sidecar-proxy, el sidecar, la pieza que acompañará a nuestra aplicación, será un proxy que intercepte todas las comunicaciones de red.

En el caso concreto de Kubernetes esto se traduce en que dentro del pod se ejecutarán, además del contenedor de nuestra aplicación, otro contenedor que será dicho proxy. Yendo al detalle, este es un proxy Envoy.

Las piezas que componen la arquitectura de Istio se pueden categorizar en dos grupos diferentes conocidos como planos:

  • Plano de datos: es la parte que corresponde a los sidecar-proxies que se ejecutarán en conjunto con cada pieza de la aplicación interceptando su tráfico de entrada y salida.
  • Plano de control: es la parte encargada de gestionar y configurar en los proxies las reglas de enrutado, políticas de seguridad… A esta parte corresponden piezas como Pilot, Mixer…

La siguiente imagen muestra la arquitectura general de Istio con sus diferentes piezas. En ella podemos ver cómo un proxy Envoy acompaña a cada servicio svcA y svcB y que son los que realizan las comunicaciones entre los mismos además de recibir las llamadas entrantes al sistema (ingress) y realizan las salientes (egress).

Así mismo también se comunican con Mixer para la comunicación de métricas y la gestión de acceso. Mientras, Pilot nutre de información a los proxies Envoy sobre el registro y configuraciones, e Istio-Auth será el encargado de la generación de certificados para las llamadas con TLS.

A continuación vamos a ver las diferentes piezas que componen la arquitectura en mayor detalle.

Proxy Envoy

Es la pieza encargada de interceptar todo el tráfico de entrada y salida al contenedor de la aplicación.

Se comunica con el resto de piezas para llevar a cabo funcionalidades como son el balanceo, circuit breaking, gestión de timeouts… que más adelante analizamos en detalle.

Envoy es un proyecto separado de Istio como tal, podés encontrar su site aquí.

Mixer

Se encarga del control de acceso y de recibir las métricas generadas por las llamadas en los proxy Envoy.

Su finalidad es mover la integración con el control de acceso, gestión de cuota, logging y similares fuera del propio servicio (aplicación) como tal y convertirlas en simple configuración evitando así el acoplamiento entre el mismo y la infraestructura destinada a tal fin.

Para ello, Mixer actuará como intermediario de forma que el servicio interactuará con él, no estando acoplada a la infraestructura subyacente.

Además, el nivel de acoplamiento con Mixer será inferior al que se tendría con la infraestructura.

Para ello Mixer dispone de diferentes abstracciones en forma de adaptadores o plugins para interactuar con los diferentes sistemas (Prometheus, AWS, GCP…) ya sean de telemetría, control de acceso… proporcionando así un API unificada independiente de la herramienta utilizada por debajo.

Las funcionalidades principales proporcionadas por Mixer se podrían agrupar como:

  • Verificación de precondiciones: se comprueba que se pueden realizar las llamadas. Dichas precondiciones pueden incluir autenticación, comprobar que el servicio que realiza la petición no esté en una lista negra…
  • Gestión de cuota: administración para que cuando un servicio destino dispone de recursos limitados se pueda garantizar una distribución justa entre los llamantes.
  • Informe de telemetría: permite la centralización de logs y monitorización.

Pilot

Es la pieza encargada de gestionar todo lo referente a registro de servicios, enrutado y resiliencia (circuit breaking, timeouts, reintentos…)

Es el punto central donde registraremos dichas configuraciones y que serán trasladadas en tiempo real a los diferentes proxies Envoy.

Además, proporciona abstracción sobre la infraestructura existente de forma que los proxies Envoy no necesitan saber si se están ejecutando sobre Kubernetes, CloudFoundry, Mesos…

Istio-Auth

Es la pieza encargada de securizar la comunicación entre servicios y usuario final con los servicios utilizando TLS.

De esta forma todo el tráfico de red en el service mesh estará identificado por quién ha invocado a quién, de manera que se podrán utilizar políticas de acceso en base a identidad en lugar de control de red.

Para ello se encarga de la generación, distribución, rotación y revocación de claves y certificados.

La siguiente imagen muestra la gestión de certificados para una comunicación entre dos servicios, uno desplegado en Kubernetes y el otro en máquinas virtuales/físicas (en el caso de este último es necesario el uso de un agente).

Las características principales de la arquitectura de seguridad son las siguientes:

  • Identidad: Istio utiliza las service accounts de Kubernetes para identificar quién ejecuta un servicio. Típicamente el identificador de una serviceaccount será de la siguiente forma “spiffe://<domain>/ns/<namespace>/sa/<serviceaccount>”, siendo el dominio típicamente constante para todo el cluster (cluster.local). El namespace será el proyecto/namespace en el que se ejecutan los servicios y la propia serviceaccount. El uso de serviceaccounts nos da mucha potencia por su gran flexibilidad para identificar máquinas, usuarios, procesamientos o grupos de procesamiento.
  • Comunicación segura: en última instancia son los proxies Envoy los que realizan las comunicaciones, estos son securizados en base a 3 características:
    • Los servicios solo se comunican con su proxy Envoy a través de conexiones locales TCP.
    • Los proxies se comunican de forma segura utilizando TLS mutuo.
    • Durante el proceso de handshake se comprueba que la serviceaccount identificada en el certificado del servidor tiene permisos para ejecutar dicho servicio.
  • Gestión de claves: como hemos comentado previamente se encarga de todas las labores correspondientes a la gestión de claves y certificados

Instalación

Istio dispone de una muy buena documentación en su sitio web e incluye un montón de ejemplos de las diversas funcionalidades y sus configuraciones necesarias.

Os recomiendo que le echéis un ojo y que hagáis alguno de ellos, son sencillos y demuestran muy bien toda la potencia de Istio.

De cara a la instalación, en mi caso, la plataforma con la que estoy más familiarizado es Openshift, la solución de Red Hat para orquestación de contenedores basado en Kubernetes, así que instalaré Istio en Openshift.

Aunque está basado en Kubernetes, las diferencias entre desplegar Istio en Openshift o en el propio Kubernetes son mínimas (básicamente la herramienta de línea de comandos de cada una: ‘oc’ para Openshift y ‘kubectl’ para Kubernetes; y poco más).

En este caso la solución que hemos escogido es utilizar un Openshift instalado en mi máquina local, para ello utilizaremos MiniShift, que nos permite levantar un cluster de un solo nodo sobre una máquina virtual.

Aquí podéis encontrar toda la documentación necesaria sobre el mismo y las instrucciones para arrancarlo. Está inspirado en minikube, la solución para ejecutar Kubernetes de forma local.

Para la instalación de Istio hemos utilizado la versión 0.4.0 y hemos seguido los pasos indicados en el siguiente artículo del blog de Openshift.

Las instrucciones de instalación también se pueden encontrar en la propia documentación de Istio, que puede instalarse sobre diversas plataformas, desde el propio Kubernetes pasando por entornos basados en Consul o Eureka, hasta en CloudFoundry o Mesos.

Istio incluye una aplicación de ejemplo que nos permite probar la funcionalidad del mismo, así como realizar los diversos ejemplos incluidos en su web. La arquitectura de la aplicación es la siguiente:

Si nos fijamos en la misma, podemos ver que se trata de varios microservicios, cada uno desarrollado en un lenguaje diferente y en el caso concreto de ‘reviews’ con tres versiones del mismo desplegadas. Si queréis conocer más en detalle la aplicación de ejemplo podéis encontrar información aquí.

El proceso de instalación, tanto de Minishift como de Istio y la aplicación de ejemplo, es realmente rápido, en menos de 15 minutos podemos tenerlo todo funcionando.

No voy a entrar en detalle, simplemente quiero remarcar los siguientes puntos relevantes:

  • Istio se instalará en un namespace (o proyecto) separado ‘istio-system’ en el que se ejecutarán los pods necesarios (mixer, pilot…). Desde ahí se gestionarán los sidecars que se ejecuten en los diferentes namespaces. Es decir, tendremos un proyecto concreto para Istio y este nos servirá para operar los proxys envoy en todos los demás proyectos, siendo necesaria una única instalación de Istio para todo el PaaS y no una por proyecto.
  • Serán necesarios permisos de administrador tanto para la instalación como para crear las serviceaccounts necesarias
  • La instalación básica de Istio está compuesta de los siguientes pods:

  • Adicionalmente, como parte de los ejemplos, se incluyen ficheros para instalar Prometheus, Grafana, Servicegraph y Zipkin (más adelante profundizaremos en dichas herramientas). Si bien son parte de los ejemplos creo que es interesante instalarlas porque vienen integradas para funcionar directamente con la instalación de Istio y nos proporcionan utilidades relacionadas con una parte tan importante como es la monitorización. Tras incluirlas nuestro proyecto quedará así:

  • Finalmente, dependiendo de la versión de Kubernetes que tengamos, podremos utilizar la inyección automática del sidecar o tendremos que hacerlo manualmente. Si tenemos una versión 1.9 o superior podremos realizarla de forma automática. En nuestro caso estamos utilizando un Openshift 3.7.1 basado en Kubernetes 1.7.6, por lo que lo realizamos de forma manual. Para ello Istio nos proporciona una herramienta de línea de comandos: istiocl que nos permite inyectar los sidecar-proxys en nuestras definiciones de Deployments, por ejemplo para la creación de la aplicación BookInfo utilizamos el siguiente comando:
oc apply -f <(istioctl kube-inject --debug -f samples/bookinfo/kube/bookinfo.yaml)

Una vez lo hayamos ejecutado tendremos los siguientes pods:

Hasta aquí hemos analizado la arquitectura interna de Istio con las diversas piezas que la componen y la responsabilidad de cada una.

Hemos visto el patrón de diseño que implementa y hemos realizado una instalación sobre minisfhit, tanto del propio Istio como del ejemplo de código que incorpora, lo que nos deja nuestro entorno listo para jugar; pero eso ya es para nuestro segundo post ;)

Abraham Rodríguez actualmente desarrolla funciones de ingeniero backend J2EE en Paradigma donde ya ha realizado diversos proyectos enfocados a arquitecturas de microservicios. Especializado en sistemas Cloud, ha trabajado con AWS y Openshift y es Certified Google Cloud Platform Developer. Cuenta con experiencia en diversos sectores como banca, telefonía, puntocom... Y es un gran defensor de las metodologías ágiles y el software libre."

Ver toda la actividad de Abraham Rodríguez

Escribe un comentario