BKT en Producción: AWS y Otros Servicios Usados

En este segundo artículo de la nueva serie que estaré publicando presentaré una serie de servicios y herramientas que se usaron para dejar el software del que esta serie trata funcionando en producción.

Toda la infraestructura se montó en AWS. Fue una combinación de servicios estándar y uno que era relativamente nuevo y en ese entonces aún se actualizaba constantemente.

Los servicios en cuestión son:

  • EC2: Elastic Cloud Computing
  • S3: Simple Storage Service
  • SES: Simple Email Service
  • SNS: Simple Notification Service
  • Code Deploy
  • Lambda
  • AMI: Application Machine Images
  • IAM: Identity and Authorization Management
  • ELB: Elastic Load Balancer
  • RDS: Relational Database Service
  • Cloudfront
  • Auto Scaling

Entre los servicios y herramientas usados por fuera de AWS están:

  • Sentry
  • Papertrail
  • Logentries
  • Slack: para notificaciones de despliegues
  • Jenkins
  • Terraform
  • Packer
  • Skylight
  • New Relic

AWS, siglas para lo que te imagines

Antes de iniciar en este proyecto, la primera vez que vi la consola de AWS me dio pánico. Eran demasiadas opciones y no sabía por donde empezar. Una semana antes de empezar este nuevo software tuve la oportunidad de hacer un curso de AWS(en Platzi, gracias, Yohan Graterol) en el cual pude aprender a usar los servicios básicos de esta plataforma: EC2(con todo lo que tiene) y RDS.

Se podría considerar a EC2 como un mini mounstro dentro de AWS ya que se compone de ELB, Auto Scaling, Elastic IP, Security groups, AMI y todo el tema de instancias en subasta y/o dedicadas.

Bajo ciertos parámetros, se podía configurar una infraestructura web solo usando EC2.

Puede que de la lista de servicios no te suene mucho Code Deploy y tal vez te suene Lambda y por eso los describiré un poco ahora.

Code Deploy

Básicamente, Code Deploy es el servicio de AWS para implementar entrega y despliegue continuo. Tales mecanismos se pueden lograr por fuera de AWS con servicios como Travis, Circle CI, e incluso Heroku tiene capacidades para eso.

En el caso de este proyecto, convenía usar Code Deploy ya que el uso es gratuito y solo se cobra el uso de las instancias EC2 de la aplicación.

Usando este servicio, se puede hacer despliegue a una o varias máquinas dentro de una zona de disponibilidad(Avalaibility Zone) para los cuales disponemos de dos tipos grandes de despliegue: In-Place y Blue/Green.

In-Place o in situ

Hace referencia al tipo de despliegue donde cada máquina es detenida, actualizada y reiniciada durante el proceso. Puede ser una máquina a la vez o todas al mismo tiempo.

Esta forma permite definir unas reglas para indicar cuando el despliegue es exitoso: solo cuando todas las máquinas se actualizaron correctamente, si la mitad sí y la mitad no, dar por fallido el despliegue si alguna falla, etc.

Tiene unas configuraciones muy interesantes para lograr el resultado deseado.

Blue/Green

En este tipo el grupo de servidores actuales no se detiene ni actualiza, lo que ocurre es que se disparan nuevas instancias EC2, se provisionan(se les instala y configura lo necesario para que anden), se actualizan con el código de la aplicación y luego, mediante un balanceador de carga, se les envía, poco a poco, tráfico al mismo tiempo que se deja de enviar tráfico a las instancias iniciales o desactualizadas.

Las máquinas que dejan de recibir tráfico pueden eliminarse para no consumir horas de actividad(y que no llegue la factura alta).

Luego de estos dos tipos de despliegue, vienen más configuraciones para usar el servicio. Lo primero es que hay que instalar un agente(software) en cada instancia de EC2 el cual se va a comunicar con CodeDeploy y también hay que configurar un archivo appspec.yml el cual describe los pasos y la forma de desplegar el software en cada servidor.

Este es un ejemplo de un archivo appspec.yml

version: 0.0
os: linux
files:
  - source: ./
    destination: /home/ubuntu/avanzza/deployments/api-release
permissions:
  - object: /home/ubuntu/avanzza/deployments/api-release
    owner: ubuntu
    group: ubuntu
hooks:
  BeforeInstall:
    - location: scripts/before_install.sh
      timeout: 120
      runas: ubuntu
  AfterInstall:
    - location: scripts/after_install.sh
      timeout: 300
      runas: ubuntu
  ApplicationStart:
    - location: scripts/application_start.sh
      timeout: 120
      runas: ubuntu

Lo interesante acá es la sección de hooks que son las etapas del ciclo de despliegue donde se pueden ejecutar scripts para llevar a cabo este proceso.

Digo interesante también porque es acá donde se puede tener en cuenta configuraciones para balanceador de carga y grupos de auto escalado. Puedes ver en detalle cada etapa de tal ciclo y la explicación a cada hook en la documentación oficial.

Lambda

Este es el servicio de funciones en la nube que ofrece AWS. Para los no entendidos, esto de funciones en la nube o serverless hace referencia a la nueva tendencia de poder ejecutar código, en la nube, sin necesidad de configurar servidores, DNS, dominios, IPs, etc, etc. También les llaman unidades computacionales.

Varias lecturas sugieren que todo debería y podría pasarse a serverless pero la realidad es que el verdadero caso de uso de este tipo de servicios es para ejecuciones cortas e independientes.

Tener una API, donde cada endpoint corresponda a una unidad computacional es difícil de manejar y muy complejo para organizar. Lo ideal es que sea una ejecución única, independiente y concisa, que no lo tome mucho tiempo porque este servicio tiene costos elevados.

Que sea serverless no quiere decir que no haya servidor, quiere decir que no configurar el servidor.

En este proyecto se usó Lambda para poder enviar notificaciones de los despliegues desde CodeDeploy, pasando por SNS, a un canal en un espacio de trabajo en Slack.

SNS es el servicio de notificaciones de AWS, generalmente push pero hay de todo tipo.

Sobre este punto de enviar notificaciones a Slack via Lambda habrá un artículo más adelante.

Los Otros Servicios Usados de AWS

Bueno, ya otros servicios que tal vez no sean tan ignorados son IAM, AMI y ElastiCache.

IAM es el gestor de autorización y autenticación dentro de toda la plataforma, sea entre servicios, usuarios u otros software que intenten comunicarse con AWS mediante la API.

AMI es el servicio para crear, organizar y hasta comprar, imágenes virtualizadas de sistemas operativos que usan las instancias para, pues, tener un sistema operativo.

Verás, por si sola, una instancia es solo un servidor virtualizado que necesita un sistema operativo para arrancar. Mediante las AMI, se puede instalar un SO Linux, Windows o derivados de Linux creados por los usuarios.

De ese modo, se puede tomar la imagen base de Linux, lanzar una instancia, configurarla como se necesita, crear una AMI(la cual ya no será la imagen base inicial sino un derivado) y posteriormente usar esa AMI derivada para lanzar nuevas instancias.

Finalmente, ElastiCache es el servicio para lanzar instancias de servidores con Redis o Memcache.

Si bien se puede lanzar una instancia EC2, configurarla e instalar Redis en ella, con ElastiCache se ahorra mucho tiempo y esfuerzo en configuraciones aunque toca pagarlo en efectivo 🙂

Los Otros Servicios

Bueno, basta de AWS. Hay otros servicios muy interesantes que se usaron para lanzar y mantener esta aplicación en producción.

Lo primero es que antes de meterme en el rollo de crear las instancias y decidir los servicios a usar, diseñé la arquitectura que tendría la infraestructura.

Tal diseño lo hice en primera medida con Draw.io y luego encontré un servicio muy bueno llamado Cloudcraft.

Por mi inexperiencia y el bajo compromiso por parte de los interesados de proyectos anteriores a este, desconocía sobre ciertos procesos que había que tener en cuenta al momento de tener una aplicación web corriendo en ambiente producción. En realidad son varias pero en este caso me refiero a la captura de excepciones.

Sentry al rescate

Si bien ya lo hago desde el día 1 en cualquier proyecto en el que me involucro, antes permitía que los usuarios encontraran pantallas de errores 400 y 500, algo que no debe suceder. Ahí es donde entran a jugar los capturadores de excepciones como Sentry, Airbrake, entre otros.

La labor de esos servicios/herramientas es hacer algo útil con esa excepción que encuentra un usuario. En vez de quedar cómo un error y ya, Sentry, en este caso, lo captura y lo manda a una vista donde podemos ver el detalle de la excepción.

Entre los datos están el ambiente(producción, staging), la IP del servidor, el mensaje del error, la línea de código, el navegador en el que se disparó, la cantidad de veces, la hora, etc, etc.

Con herramientas de ese tipo, corregir tales errores se vuelve muchísimo menos complicado. En ese proyecto, usar servicios como Sentry fue una de las cosas que aprendí.

Desempeño

Otra de las cosas que aprendí fue configurar servicios que ayudan a medir el desempeño y consumo que tiene el software como tal y en los servidores donde está instalado(desplegado :D).

La importancia de medir tiene que ver con asuntos de escalibilidad y mejoras generales.

Muchos desarrolladores tienen la costumbre de obsesionarse con código que no sea lento solo con escribirlo o verlo y en realidad el ojo no es el mejor método para medir el desempeño de algo.

Puedes hacer benchmarks de una función pero eso es solo una realidad acotada a la prueba. Lo que en realidad determina si tu código es rápido o lento es el día en que cien usuarios hagan una misma petición desde diferentes navegadores, conexiones, lugares del mundo.

Por eso, herramientas para medir como New Relic o Skylight, son ideales para tener datos concretos y no suposiciones sobre la lentitud de una aplicación web.

Solo cuando esas herramientas indican que algo está lento es que se debe priorizar, crear tareas y mejorar tales funciones, endpoints o lo que sea.

Jenkins, Terraform

Ya para cerrar con esta introducción de varias herramientas comentaré un poco sobre unas muy específicas al mundo de DevOps.

En la sección de CodeDeploy comentaba como servicios permitían aplicar entrega y despliegue continuo, sin embargo, no se limitan solo a eso. Su labor primordial es correr suites de pruebas según el código que esté en algún sistema de control de versiones, por ejemplo, GitHub.

Jenkins también es una herramienta para ejecutar suites de pruebas, su diferencia con Circle CI es que es Open Source y aunque hay servicios que lo ofrecen en sus linea de productos, normalmente se usa en una instalación y configuración propia.

Por otro lado, una herramienta muy interesante que aprendí a usar es Terraform. Lo mejor de haber aprendido Terraform fue que comprendí un nuevo concepto llamado Infraestructure as Code.

Al haber usado por muchos meses la consola de AWS y en algunos el CLI de consola, se volvía evidente que era cansino tener que entrar a la web para levantar una instancia, reiniciarla, actualizar un security group pero cuando conocí Terraform, vi todo un mundo de potencial.

Terraform

La gracia de Terraform es poder definir la infraestructura a crear en proveedores como Heroku, Digital Ocean o AWS mediante código. De esa forma, mediante una sintaxis simple, se puede crear toda una infra para una aplicación web y lo mejor es poderla reutilizar y actualizar sin tener que entrar a la consola web y dar clic, clic, clic y clic.

Terraform no es la única. Existen varias:

  • Chef
  • Puppet
  • Saltstack
  • Ansible

Pero ocurre que muchas de esas también se dedican a otro concepto llamado Configuration Management, es decir, gestión de la configuración, el cual es la instalación y configuración de dependencias en servidores web. Y no está mal que lo hagan, solo que al Terraform enfocarse en una sola cosa, pues, lo hace mejor(desde mi punto de vista ya que en realidad no he probado las demás)

Un ejemplo de una configuración escrita en Terraform para crear un security group en AWS:

resource "aws_security_group" "server_access" {
  name = "server-access"

  ingress {
    from_port = "80"
    to_port = "80"
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port = "22"
    to_port = "22"
    protocol = "tcp"
    cidr_blocks = ["190.131.222.32/32"]
  }

  egress {
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port = "443"
    to_port = "443"
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Con dos comandos se puede proceder: terraform plan y terraform apply. Con el primero se ejecuta una prueba de qué ocurrirá y con el segundo se aplican los cambios en AWS.

Bacanísima.

Y así termina esta larga introducción de algunas herramientas descubiertas, algunos aprendizajes durante el camino.

En próximos días estaré adentrando más en conceptos o temas más concretos.

Autor: cesc1989

Ingeniero de Sistemas que le gusta escribir y compartir sobre recursos que considera útiles, además que le gusta leer manga y ver anime.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios .