Si hace unos años me hubieran dicho que estaría comentando sobre lo que menciona el titulo, me hubiera puesto a reír, pero el contexto tecnológico cambia de manera constante y este es el escenario en que los desarrolladores debemos tener claras nuestras opciones a la hora de considerar Linux como plataforma.
De mas esta comentar sobre las oportunidades que nos ofrece .Net Core para poder llegar a escenarios en los que tradicionalmente Windows estaba vedado, pero también debemos tener en cuenta las perspectivas de poder integrarnos y trabajar con otros stacks, así que si… Linux nos va a rodear bastante a los que trabajamos con .Net.
Ahora bien, trabajar con Máquinas Virtuales Linux siempre ha sido posible desde que los proveedores de cloud empezaron a ofrecer IaaS, pero si uno basa su estrategia cloud en depender de máquinas virtuales que básicamente replican la arquitectura que se tenía on premise, no se está sacando partido de las potencialidades de la nube (optimización de costos y escalamiento) ni tampoco se esta asumiendo un enfoque pragmático frente a los retos (o limitaciones) inherentes a la nube, como pueden ser los niveles de servicio asegurados por el proveedor (SAL), lidiar con las latencias, etc, esto y la necesidad de brindar a nuestros equipos de desarrollo con plataformas que aceleren su productividad nos deben obligar a mirar la nube más allá del IaaS.
Es con esta mirada que debemos analizar la propuesta PaaS que nos da Azure en el entorno Linux; recordemos que tradicionalmente si queríamos implementar una Web App lo que estábamos provisionando “por detrás” era una MV Windows con un IIS especialmente configurado para permitir las ventajas como slots, escalamiento, kudu, etc… lo cual nos va bien para aplicaciones .Net pero por ejemplo no nos permite correr aplicaciones Ruby, aparte de que existen escenarios en que se requiere cierta librería PHP que ¡oh sorpresa! tiene una fuerte dependencia con el sistema operativo Linux, así que era natural que Microsoft Azure venga a ofrecer una solución de Web Apps basada en Linux como una opción para los desarrolladores, misma que en este momento esta en versión de prueba.
Ok, Web Apps en Linux… ¿y eso que tiene de novedoso? Pues lo interesante es el enfoque que ha decidido usar Microsoft para crear su solución, esencialmente en lugar de configurar un Apache o Nginx con todos los stacks de desarrollo ofrecidos ha optado por algo mas rompedor aun, depender totalmente de Docker para proveernos con el stack de desarrollo que necesite nuestra aplicación:
Como se puede ver se nos dice explícitamente que podemos hacer uso de contenedores especialmente configurados, lo cual nos da la flexibilidad de elegir versiones específicas del framework a usar (nótese la variedad de opciones para Node.js), y sobre el stack elegido montar nuestra aplicación respectiva.
Pero ojo… la ventaja no es solo en el caso de que queramos desarrollar una aplicación web en esos entornos, sino también para en el caso que hayamos creado un contenedor Docker completo (de una aplicación web, obviamente), y en este caso para recordar y contextualizar les comento la experiencia que tuve el año pasado cuando empecé a trastear con esto de Docker.
(Despliegue Docker, la manera IaaS)
El esquema en teoría es simple, compilar la aplicación .Net Core, empaquetarla como container, y publicarla en el Docker Hub:
Para luego recuperar el container desde Docker Hub y publicarla en una Máquina Virtual especialmente configurada para esto
De hecho este esquema lo tengo operativo, pero para llegar a el tuve que configurar correctamente la máquina virtual con Docker (gracias a las indicaciones de Donovan Brown) , asegurarme de enlazarla correctamente e ir validando las opciones correcta, y adicionalmente configurar un nginx en dicha máquina para que actuara como proxy inverso permitiendo acceder desde internet a la aplicación Web vía el puerto 80, ya que mi aplicación .Net Core solo expone directamente vía el puerto 5000.
Por si estos pasos no fueran ya complicados, sumemos el hecho de que siendo una aplicación web ligera, me obliga a provisionar una MV para efectuar el despliegue de una aplicación, lo cual me hará incurrir en los gastos de consumo de dicha MV ya sea que esta esté en uso o no.
Es así que toma su lugar la otra opción que nos brindan las Web Apps en Linux, poder exponer nuestros propios contenedores (web, claro esta) en tanto estos estén publicados ya sea en Docker Hub (de manera publica o privada)
O desde un Registro Docker personalizado (como el que Azure también nos ofrece):
Esta flexibilidad nos permite construir nuestras aplicaciones aun con stacks (o versiones de stacks) no ofrecidos de serie por la plataforma, en este caso el requisito obligatorio es que nuestro contenedor contenga todas las dependencias necesarias para correr, y exponer via el puerto 80 el puerto “interno” que este usando nuestro contenedor es muy simple, solo debemos agregar la variable PORT = puerto interno… y listo.
Claro está que si queremos escalar nuestra aplicación horizontalmente dependeremos de la infraestructura provista nativamente por Azure, así que está en nuestras manos desarrollar la aplicación de acuerdo a esa posibilidad.
Ok, esto nos simplifica las cosas si lo que queremos es desplegar UNA aplicación, pero ¿qué ocurre si nuestro sistema esta basado en un conjunto de aplicaciones implementadas bajo un modelo de Microservicios? ¿Cómo procedemos al despliegue de todas las aplicaciones involucradas?
Es en este caso que entran en juego los Orquestadores de Contenedores como Swarm, DC/OS (Mesos) y Kubernetes que nos permiten gestionar nuestras necesidades de balanceo de carga, escalabilidad y alta disponibilidad, mediante una gestión inteligente de los recursos disponibles al eliminar y crear instancias de nuestros contenedores desplegados según vayan aumentando nuestra demanda.
Nosotros podríamos efectuar la instalación y configuración de nuestro Orquestador y del cluster respectivo para lograr los objetivos mencionados, pero aquí entra en acción el Azure Container Service, un servicio agrupado que nos permite simplificar todos estos procesos:
- Instalación del Orquestador elegido, lo cual incluye ahora también a Kubernetes.
- Configuración de nuestro Registry privado
- Configuración del nodo Master
- Configuración del set de disponibilidad, ojo a esto, es un servicio de Azure que entre otras cosas permite el provisionamiento automático de maquinas virtuales según las necesidades de demanda o configuración, en este caso nuestra instalación del Orquestador trabajara de la mano con este set de disponibilidad para lograr el resultado deseado.
- Despliegue de las actualizaciones de nuestras aplicaciones, si aquí entra nuestro querido VSTS, y en esta ocasión Microsoft ha hecho un trabajo muy fino permitiendo la creación automática de todo el pipeline de construcción de nuestros contenedores así como la de del pipeline de construcción y despliegue creando los entornos intermedios deseados.
Si pues, yo no tuve que hacer eso, simplemente VS 2017 y VSTS hicieron la magia.
En el camino queda explorar con mas detalle las opciones de Orquestador disponibles, como testear en los entornos (Dev, Test y Prod por ejemplo) en nuestro cluster, jugar con las opciones de escalabilidad y destrucción de instancias, tunear nuestros Composer.yml etc. Pero ya podemos definir unas conclusiones preliminares de cara al futuro mediato:
- Tenemos un razonable set de frameworks de desarrollo PaaS tanto en Windows y ahora en Linux (¡Ruby!)
- Si nuestros requerimientos de dependencias de nuestra aplicación web no son proveídos de serie por Azure siempre podremos construir nuestros contenedores personalizados y desplegarlos en las Web Apps.
- Si el modelo de nuestro sistema es multi aplicaciones o tiene requerimientos especiales de escalabilidad la opción a considerar seriamente es configurar un Azure Container Services y elegir el orquestador que mas nos guste.
¡Ah empezar a probar! Espero sus comentarios.