Cada vez que ECR reciba una nueva imagen, se iniciará un pipeline que concluya con el despliegue de un servicio de ECS cuyas características particulares (puertos, volúmenes, nombre del servicio, cpu memoria etc.) son definidas en un template de cloudformation almacenado en un repositorio de codecommit.

Estrategia multi-cuenta

Es importante destacar que trabajamos con aplicaciones que tienen múltiples ambientes (desarrollo, calidad, producción etc.) es buena práctica aislar cada ambiente en una cuenta diferente de AWS. Esto no solo nos permite tener un mejor control y seguridad sobre cada ambiente/cuenta sino que también nos ayuda a disminuir el radio de los daños que nuestro mismo equipo pudiese ocasionar accidentalmente  durante la implementación de un cambio.

La Figura 1,  muestra un diagrama de un esquema multi-cuenta donde además de separar cada ambiente en una cuenta de AWS diferente,  se utiliza una cuenta adicional en donde se centralizan las herramientas de DevOps para realizar los despliegues a los diferentes ambientes.

Hoy en día, el tema contenedores es tan común que podría decirse sin que suene descabellado que todos en el mundo TI alguna vez hemos hablado sobre mover nuestras aplicaciones a contenedores y obviamente hemos discutido los beneficios y desventajas que esto conlleva.

Otra aseveración no menos importante es que si se habla de contenedores, es imposible no hablar de Docker, y es común pensar que Docker únicamente facilita la creación, distribución, ejecución y orquestación de contenedores con sistema operativo Linux.  

Lo anterior resulta entendible, debido a la abrumadora adopción de contenedores Linux lo que explica que la  gran cantidad de documentación existente se enfoque mayormente en el sistema operativo del pingüino.

Este post, pretende destacar, que incluso los que tenemos cargas de trabajo en Windows y queremos entrar al mundo de los contenedores podemos hacerlo,  mejor aún,  podemos hacerlo sobre la nube de AWS, utilizando Amazon Elastic Container Service (ECS), un servicio de orquestación de contenedores en AWS que  facilita en gran manera las tareas requeridas para la ejecución de cargas de trabajo en contenedores.


Antes de comenzar

Si bien es cierto que podemos llevar cargas de trabajo Windows a contenedores utilizando ECS, es importante destacar que existen algunas limitantes que debemos tomar en cuenta:

  • En primer lugar, ECS aún no soporta que los contenedores Windows hagan uso del modo de red awsvpc, el único modo soportado es WinNAT, lo que quiere decir que cada contenedor recibe una ip privada accesible únicamente desde las instancias del clúster, por lo que por ejemplo no puedes establecer un grupo de seguridad independiente para cada task y debes hacerlo a nivel de las instancias del clúster.
  • El único tipo de lanzamiento soportado para Contenedores Windows es EC2,  esto implica que lamentablemente, Fargate no está disponible aún.
  • Los contenedores Windows no soportan todos los parámetros de la definición de tareas que están disponibles para los contenedores Linux y las instancias de contenedores.
  • Los Roles IAM para tareas hacen uso de un proxy de credenciales que utiliza el puerto 80 de la instancia del contenedor, lo que implica que este puerto no está disponible para tareas.
  • La imágenes Docker de Windows Server son bastante más grandes (9 GB) que las imágenes Linux y como resultado las instancias requieren mucho más espacio de almacenamiento que las instancias Linux

Conociendo las limitantes anteriores y sus implicaciones, podemos reafirmar que ejecutar contenedores Windows sobre ECS es perfectamente factible y funcional.

Antes de continuar, vamos a plantear un escenario donde se contempla un caso particular de uso donde las imágenes de docker (imágenes Windows que exponen una aplicación Web) que serán utilizadas por los tareas de ECS no son creadas dentro de AWS, son construidas en un ambiente on-premise y cada nueva versión es depositada automáticamente en ECR (Elastic Container Registry).


Figura 1: Esquema multicuenta para el despliegue de un servicio ECS utilizando EC2


Esquema de la solución

Como mencionamos anteriormente, si queremos ejecutar contenedores Windows sobre ECS, debemos utilizar obligatoriamente EC2 como tipo de lanzamiento, por lo que nuestra infraestructura debe definir los recursos de cómputo que asignaremos a nuestra instancia, debemos seleccionar AMI que queremos utilizar en las instancias de nuestro clúster, definir un grupo de autoescalado para proveer de elasticidad a nuestra solución y por supuesto, debemos establecer el rol de IAM que utilizaran las instancias de nuestro cluster. Convenientemente, AWS nos proporciona AMIs de Windows optimizadas para ECS.La Tabla 1 muestra un segmento del template de cloudformation que servirá para la creación de la infraestructura se destacan 2 recursos fundamentales,  la configuración de lanzamiento que utilizara el grupo de autoescalado para inicializar las instancias del clúster (una agrupación lógica de tareas o servicios) y el Rol de IAM que asumirá cada instancia.


Tabla 1:  Segmento de template de infraestructura


Adicionalmente para este escenario particular, el servicio de ECS que pretendemos desplegar es un servicio web, por lo que también definiremos un balanceador de carga que nos ayudará a direccionar el tráfico hasta nuestro contenedor. La figura 2  nos muestra en términos generales el diagrama de los recursos que se desplegarán para un ambiente particular.

Como mencionamos al principio, no es posible usar el modo de red awsvpc y la única forma de acceder al contenedor es mediante las interfaces de red de las instancias del clúster, por lo que si se quiere exponer varios servicios en un mismo clúster no es posible establecer un grupo de seguridad independiente.


Figura 2: Recursos Cuenta de desarrollo
Pipelines de la solución

Como muestra la figura 2, en la solución hemos separado los componentes vinculados a la infraestructura, de los componentes de la aplicación, eso significa que deberíamos crear dos pipelines para cada ambiente es decir que si tenemos tres ambientes  (dev,qa,prod) deberíamos crear un total de seis pipelines, sin embargo, para este post nos enfocaremos únicamente en los pipelines un un solo ambiente. No vamos a ahondar en las razones de porque separamos los pipelines, porque no es el objeto de estas líneas,  pero en términos generales vamos a decir que es una buena práctica hacerlo y que si necesitas más información al respecto puedes  invertir unos minutos en leer este interesante post .

Pipeline de la infraestructura

El pipeline de la infraestructura tiene como origen un repositorio de Codecommit que debería contener un template de CloudFormation donde se definen los recursos vinculados a la infraestructura, el Cluster de ECS, el ELB, el grupo de autoescalado, la configuración que se utilizará para lanzar nuestra las instancias del clúster, grupos de seguridad, el Rol IAM.

Este template de CloudFormation será utilizado para crear un changeset en la cuenta correspondiente al ambiente que se desea desplegar y previa aprobación será  ejecutado, dejando como resultado la creación de los recursos de infraestructura.

Pipeline de la Aplicación

El pipeline de aplicación, a diferencia del de infraestructura, tiene dos orígenes que pueden iniciar el pipeline, el primero, el repositorio de ECR que iniciara el pipeline cada vez que reciba una nueva versión de la imagen de Docker creada en on-premise y depositada en el repositorio.

El segundo origen es el repositorio de Codecommit que debería contener un template de Cloudformation con la definición de los recursos propios de la aplicación,  es decir el Servicio de ECS, la definición de la tarea (Task Definition), el target group que facilitara la comunicación del ELB con el servicio.


Tabla 2:  Segmento del template para la creación del pipeline de aplicaciones

Durante la ejecución del pipeline se obtendrá tanto el template de Cloudformation como los datos de la imagen de más reciente, el templete de CloudFormation actualizará la definición de la tarea y actualizará el servicio de ECS para que utilice la nueva definición lo que originará un nuevo despliegue dando como resultado el inicio de una nueva tarea y la finalización de  las tareas que estén utilizando una definición obsoleta.


Figura 3: Pipelines de infraestructura y aplicaciones para Desarrollo


Figura 4: Consola de AWS - Pipelines de Infraestructura y aplicaciones


Resumen

Con este post se pretende destacar que podemos contenerizar cargas de trabajo Windows, utilizando ECS, pero  es importante tener en cuenta las implicaciones que conlleva antes de sumergirse en el mundo de los contenedores.