Una de las primeras implementaciones de infraestructura que hice fue migrar la app principal de 3 servidores EC2 a ECS Fargate. Este fue el resultado de una conversación que tuve con el CTO cuando propuse ayudar con algunas tareas de DevOps.

Hubo varias razones que me impulsaron a comprometerme con esto. Primero, cuando comencé a trabajar para la compañía tuve acceso a AWS y descubrí que nuestros servidores estaban sobredimensionados y estábamos pagando demasiado por ellos. El uso de CPU del servidor principal estaba por debajo del 5%, este se encargaba de ejecutar un montón de trabajos cron, y los otros 2 servidores estaban por debajo del 2% en uso de CPU. La memoria RAM no era diferente.

Otra razón para migrar la app es que pasé casi 2 semanas para configurar el ambiente local y después de eso trabajé fuera de horario en una implementación de docker para ambientes locales. Después de esa implementación, hubo nuevos devs que configuraron su ambiente local en pocas horas, también con algunas mejoras adicionales al implementar el Make Pattern fui capaz de configurar un solo comando que configuraba todo el ambiente en pocos minutos. Esta estructura se convirtió en el estándar de facto para las nuevas apps y las que estaban planeadas para migrar.

La estandarización de los ambientes también es genial ya que ahora todos están usando exactamente el mismo ambiente y el “Funciona en mi local” se convirtió solo en una frase divertida sin impacto. Todos nuestros ambientes desde Local a Producción son los mismos, obviamente difieren en recursos pero aparte de eso tienen las mismas versiones de todo, haciendo más simple entender qué está realmente pasando porque las diferencias del servidor ya no son un problema, Si esto falla en local, fallará en producción y viceversa, más fácil de depurar cuando sea requerido.

Aunque teníamos 3 servidores EC2 sobredimensionados configurados con un load balancer en frente, la principal preocupación era la falta de estandarización y documentación sobre cómo esos servidores estaban configurados y también que en caso de falla, recuperar cualquiera de esos servidores o en el peor caso en el que todos pudieran fallar, tomaría mucho tiempo solo para desplegar y configurar los nuevos servidores. Después de la migración, los contenedores están distribuidos en diferentes AZ haciéndolo Altamente Disponible.

Una gran característica que vino con la implementación de contenedores es que no necesitamos preocuparnos por un servidor que se caiga, si por alguna razón un contenedor falla, automáticamente desplegará uno nuevo para cumplir con la capacidad mínima deseada, y ahora las reglas de autoscaling permiten que la aplicación escale cuando realmente se necesita.

Con la migración fuimos capaces de optimizar nuestro proceso de despliegue, pasamos de una especie de gitflow a despliegues basados en Trunk, la antigua implementación estaba usando Ansible y nadie estaba al tanto de lo que esto estaba haciendo, ahora incluso las variables de ambiente están encriptadas y seguras dentro de AWS. El mismo artifact que construimos en nuestro local, es el que construye el CI/CD y lo que desplegamos a nuestros diferentes ambientes (DEV, QA, PRE-PROD, AB-TESTING, PROD).

Otra ventaja agradable es que podemos hacer rollback con solo un click, en el momento en que detectamos que algo salió mal con algún despliegue, como todos los artifacts creados están guardados, desplegar un artifact antiguo puede tomar minutos. Incluso podemos hacer rollback a lo que desplegamos hace 2023 años, ¿puedes hacer eso?.

Finalmente la razón por la que viniste aquí, ¿cuánto se redujo la facturación? los antiguos servidores eran 3 x t2.2xlarge que costaban alrededor de $0,4416 por hora.

Tipo de instancia Costo por hora Horas por Mes Instancias Totales Total en USD
t2.2xlarge $0,4416 744 3 $985,65

Con nuestra configuración actual de contenedores estamos pagando menos de 300$ mensualmente, considerando todos los ambientes que tenemos. Esto representa alrededor de $685 en ahorros mensuales y el gran total es $8,220 anuales.

Aunque el título de este post se enfoca en ahorros de costos, la verdad es que la confiabilidad, escalabilidad, disponibilidad y otros aspectos importantes involucrados en el desarrollo de nuestro producto principal fueron mejorados mucho con solo implementar contenedores.

Algunos Devs están aterrados sobre crear o usar contenedores, algunos otros son solo perezosos y no quieren dejar atrás su ambiente local inestable, y hay otro grupo de devs a los que se les niega aprender un poco sobre esta tecnología porque no es su responsabilidad. Me alegra que también haya un grupo de devs de alta calidad que está comprometido con el aprendizaje continuo y siempre está buscando la excelencia.

Mi regla personal es tratar de no instalar ningún software directamente en el OS a menos que no haya una imagen disponible ya en docker o sea demasiado complejo crearla y no compense el tiempo.