Infraestructura como Código (III): Terraform y AWS

Publicado por SSCC el

DevOpsEntrega ContinuaCloudAmazon AWSTerraformInfraestructura como Código

En el artículo anterior estuvimos hablando acerca de Terraform y como describir infraestructura para su uso en Microsoft Azure.

En esta entrega nos vamos a centrar en cómo replicar la infraestructura que creamos en Azure, pero en esta ocasión la aprovisionaremos en AWS.

Antes de saltar a cómo vamos a implementar el ejemplo sobre AWS, vamos a repasar algunos conceptos básicos.

Prólogo de AWS

Conceptos de Networking de AWS EC2

El servicio gestionado de Amazon EC2 se puede hospedar en múltiples localizaciones distribuidas por el mundo, más conocidas como Region. A su vez dentro de cada Region existen zonas de disponibilidad, a partir de ahora AZ's (Availabily Zones). Amazon EC2 permite colocar recursos, por ejemplo instancias de EC2 y datos, dentro de múltiples AZ's.

Amazon Virtual Private Cloud (VPC) permite ejecutar recursos AWS en una red virtual, que por defecto se encuentra separada a nivel lógico de otras redes. Las VPC's dentro de AWS pueden ser configuradas con un rango de IP's, tablas de enrutado, subnets, network gateways y parámetros de seguridad como ACLs (access control lists)

Una Subnet agrupa un rango de IP's dentro de una VPC. Cada Subnet reside exclusivamente dentro de una AZ. A su vez una Subnet puede ser pública o privada. Una Subnet pública es accesible mediante internet, mientras que una Subnet privada se utiliza para aquellos recursos que no deberían estar directamente expuestos a Internet, como por ejemplo una base de datos.

Un grupo de seguridad (security group) representa un firewall virtual que controla el tráfico de una o más instancias de EC2. Cuando se lanza una instancia de EC2, es necesario asociar al menos un security group con dicha instancia. Para permitir el tráfico hacia/desde la instancia se requiere la creación de reglas (rules). Estas reglas se pueden modificar en cualquier momento y se aplican automáticamente a todas las instancias que están asociadas al security group.

Para más detalles acerca de estos conceptos, consultar la documentación oficial de AWS:

Creación de un nuevo usuario IAM

Para interactuar con el API de AWS, necesitamos crear un usuario y asignarle una policy que le permita crear recursos dentro de EC2. Este usuario será el que use internamente Terraform para comunicarse con la API de AWS.

Partiendo de que tenemos una cuenta creada en AWS, a continuación se muestra cómo crear un nuevo usuario IAM (Identity and Access Management).

Seleccionamos IAM:

alt

Creamos el usuario y seleccionamos acceso programático. Esto nos permitirá configurar las credenciales de acceso que utilizaremos con Terraform:

alt

Seleccionamos los permisos necesarios para poder recursos EC2. Debemos seleccionar el grupo ec2-FullAccess:

alt

Creamos el usuario:

alt

En el último paso debemos guardar las credenciales (Access key ID y Secret access key)

alt

En el post anterior se hace mención a cómo configurar las credenciales, pero en esta ocasión lo vamos a configurar mediante aws cli y ~/.aws/credentials. De esta forma cuando ejecutamos Terraform, se resuelven automáticamente nuestras credenciales.

Por último vamos a configurar la clave de acceso SSH que necesitamos para crear instancias EC2. Nótese que cada clave SSH es local a cada Region, con lo que tenemos que asegurarnos que cuando ejecutamos este ejemplo hemos creado la clave en la misma Region que se utiliza en variables.tf

En nuestro ejemplo, vamos a utilizar la Region London:

Seleccionamos Key Pairs:

Create Key Pair como enmilocalfunciona-terraform-key-eu-west-2

Como veremos más adelante, esta clave es la que utilizaremos cuando vayamos a utilizar el resource correspondiente de EC2.

Terraform y AWS

En el punto anterior hemos descrito y explicado una serie de elementos que son necesarios para entender la forma en la que se trabaja en AWS a nivel de networking.

Una vez configurado nuestro acceso a AWS, podemos pasar a describir nuestra infraestructura utilizando Terraform.

Todo el código está disponible en el repositorio de atSistemas.

Hemos de recordar que a nivel conceptual estamos describiendo la misma infraestructura que creamos para Azure, pero en el caso de AWS hay elementos que se llaman de forma distinta, pero que tienen la misma responsabilidad. Por ejemplo, en Azure tenemos un Availability Set mientras que en AWS se denomina Auto Scaling Group.

Crearemos un Auto Scaling Group (ASG), que es donde vamos a instanciar los servicios de EC2, para que puedan escalar de forma horizontal. Para garantizar la alta disponibilidad usaremos los AZ's de cada región detrás de un balanceador y mediante AWS Launch Configuration seremos capaces de forma automática de asignar nuevas instancias EC2 dentro del ASG.

Si nos fijamos, a diferencia del post anterior, no mencionamos ningún elemento de red. Para simplificar la solución hemos optado por utilizar todos los elementos por defecto dentro de una Region (VPC, Subnet, Router e IGW).

Recordemos que nuestro objetivo es describir esta infraestructura:

El fichero variables.tf contiene la definición de las variables que vamos a utilizar en el ejemplo.

Region, ami's y key names:

Variables usadas para configurar el ASG:

Variables de salida que utilizaremos para mostrar información en el fichero output.tf:

El fichero main.tf contiene la descripción de la infraestructura

Utilizamos el provider de AWS:

Creamos un Security Group que permita acceso al puerto de la aplicación (80):

Recuperamos la lista de AZ's disponibles para dicha Region:

Creamos un balanceador (ELB) configurando su Security Group y las AZ's sobre las cuales queremos balancear el tráfico. Nótese el puerto del balanceador (80), así como el puerto que utiliza la sonda (80) para saber el estado de salud de nuestra aplicación:

Creamos el Configuration Launcher, que es el template que utiliza el ASG para lanzar instancias de EC2:

  • image_id: Es la imagen que queremos aprovisionar dentro de la región que estamos utilizando.
  • instance_type: Tamaño de máquina EC2.
  • user_data: Script utilizado para configurar la instancia de EC2.
  • key_name: Es la clave SSH con la que se va a configurar el acceso SSH.

La última pieza que necesitamos configurar es el ASG:

  • availability_zones: Las AZ's donde queremos que se van crear las instancias de EC2.
  • min_ size y max_size: Representan el número mímimo y máximo de instancias EC2 que queremos aprovisionar.
  • desired_capacity: Representa el número actual de instancias EC2.
  • force_delete: Para forzar el borrado de instancias EC2.
  • launch_configuration: EL template que hemos definido antes.
  • load_balancers: El balanceador asociado.

Un aspecto importante a considerar es que en nuestro ejemplo hemos configurado el ASG de forma manual. En un escenario real deberíamos considerar situaciones de carga o demanda del servicio para que escalara de forma automática basándose por ejemplo en thresholds de CPU, memoria, etc.

Con este último paso ya tenemos preparado el ejemplo y podemos probarlo:

Inicializamos el directorio de trabajo con terraform init:

terraform plan analiza la descripción de la infraestructura que hemos creado y nos informa de los cambios que se van a realizar (este paso no efectúa ningún cambio en AWS):

El siguiente paso es la creación de nuestra infraestructura en AWS mediante terraform apply, obteniendo por pantalla los valores de las variables que hemos definido como output:

Tras un par de minutos (tiempo de creación de EC2, el aprovisionamiento del servicio de prueba que requiere instalar docker y descargar la imagen), la DNS de salida estará disponible y veremos como refrescando el navegador nos irá devolviendo distintos id's de servicio.

Lo que hemos conseguido con esta configuración inicial es el aprovisionar esta infraestructura y además crear un clúster de dos nodos en alta disponibilidad sobre las AZ's de la Region que hemos utilizado.

Lo podemos comprobar en la consola de AWS, en la sección de EC2 y dentro de load balancers:

Seleccionamos instances y vemos como hay creadas dos instancias de EC2 en cada AZ disponible.

Si queremos de forma programática crear más instancias y ver que el ASG funciona correctamente podemos volver a ejecutar terraform apply -var asg_desired=6 para confirmar como escala horizontalmente el ASG:

Conclusiones

Para ir cerrando vamos a repasar el contenido del post:

  • Hemos utilizado Terraform para describir un ejemplo de infraestructura pero en esta ocasión en AWS.
  • Antes de implementar el ejemplo hemos repasado algunos conceptos de networking en AWS.
  • Se han configurado los accesos a AWS y claves SSH.
  • Hemos explicado algunos elementos de AWS para conseguir el escalado horizontal y como utilizar Terraform para esta finalidad.
  • Y hemos ajustado el numero de instancias para comprobar que todo el ejemplo funcionaba correctamente.

Con esto cerramos el post, esperando que os haya gustado. No dudes en comentar cualquier duda o detalle por aquí, o a través de nuestra cuenta de Twitter.

Stay tunned!!