Infraestructura: Uso de Terraform: Nginx en una VPS en AWS EC2, Key Pair, ESB y EIP

Dentro del mundo de los servidores está habiendo una revolución en la automatización del despliegue de servidores. Proyectos como Ansible, Chef o Puppet se han convertido en herramientas fundamentales a la hora de gestionar servidores en masa de una manera eficiente. Pero con la llegada del mundo de la cloud se ha visto necesario automatizar la creación de los servidores y las herramientas que debemos instalar. En esta ocasión cómo crear una máquina en AWS con EC2 con un dispositivo de bloques EBS y una Elastic IP con  Terraform.

Recuerda que esta guía es una continuación de la primera parte para instalar y configurar terraform con AWS y DigitalOcean.  Ahora iremos viendo los recursos que son necesarios para el despliegue de la VPS en AWS.

Variables

Definir las variables nos permitirá que nuestro código de despliegue sea mucho más reutilizable, ya que cambiando estas variables podremos desplegar distintas máquinas con distintas configuraciones.

Las variables mínimas de funcionamiento que necesitamos para gestionar esta VPS son las siguientes, por ejemplo en el main.tf:

variable "project_name" {}
variable "region_name" {}
variable "availability_zone" {}
variable "vpc_id"{}

    • Project name: sería como el nombre del proyecto, esto nos va a permitir que los nombres de los distintos recursos que tenemos que crear se relacionen entre sí editando los nombres o etiquetas de cada componente a desplegar.
    • Region name: es el nombre de la región donde queremos hacer el despliegue: en nuestro caso será eu-west-3 el data center de París. Es muy importante que revises usar l aregión correcta porque dependiendo de la región puedes disponer de recursos desplegados distintos.
    • Availability zone: dentro de las regiones suelen haber distintas zonas normlamente nombradas por a, b, y c. En nuestro ejemplo por simplicidad elegiremos eu-west-3a
    • vpc_id: es el identificativo de la red VPC, de nuestra cuenta.Si quieres averiguar su valor simplemente vete a la página de manejo de VPC dentro de AWS y coge el dato del id de la tuya

Provider

Como siempre elegiremos el proveedor que necesitamos, en este caso aws:

provider "aws" {
region = var.region_name
}

Como se puede ver, usamos la variable definida var.region_name para rellenar el provider.  Recuerda que puedes definir esta variable en el fichero terraform.tfvars


region_name="eu-west-3"

Al igual que peudes definir todas las variables que necesites.

Key Pair

Los pares de claves permiten la gestión de claves ssh para el acceso a las máquinas vps. En AWS es otro recurso que podemos añadir con Terraform. veamos un ejemplo:


variable "ssh_key" {}

resource “aws_key_pair” “deployer” {
key_name = “${var.project_name}-deployer-key”
public_key = var.ssh_key
}

Como puede verse se define el recurso mediante una variable que debe contener la clave SSH y que se asocia con el parámetro public key. Además modificamos el nombre de la clave, teniendo en cuenta el nombre del proyecto definido como variable. Es una buena práctica que todos los recursos definidos en el despliegue tengan algún tipo de referencia al proyecto o aplicación que queremos desplegar. Para que los usuarios de aws puedan localizar fácilmente los recursos desde la consola de AWS.
Veamos un ejemplo de definición de la clave como variable:

ssh_key="ssh-rsa AAAAB3BLABLABLABLAESTACADENAESSUPERLARGAQUELOSEPAS9Tw== correo@ejemplo.com"

Si no sabes generar estas claves, mira esta guía para ubuntu.

EBS, dispositivos de bloques

Aunque el sistema operativo no suele ocupar mucho espacio en disco, a no ser que uses windows claro, normalmente es una buena práctica, que los datos de las aplicaciones que necesitamos desplegar en las VPS’s, vayan alojados en una unidad de disco distinta del sistema, de esta manera si el disco del servidor se destruye, o si destruimos la máquina y la volvemos a crear, así no se perderían los datos que ya tuviésemos en ese dispositivo de bloques. Veamos ahora cómo definimos el recurso.


resource "aws_ebs_volume" "web" {
availability_zone = var.availability_zone
size = 4
tags = {
Name = "${var.project_name}-web-ebs"
}
}

En este caso estamos definiendo un volumen de 4GB de capacidad y como puede verse se ha de elegir el nombre de la zona donde se puede desplegar, eu-west-3a en este ejemplo, y el tag con el nombre del recurso teniendo en cuenta el nombre del proyecto.

Security Groups

Los segurity group son reglas de firewall para la red donde nos encontremos, que luego podremos aplicar a nuestras VPS de EC2. Vemos un ejemplo para aplicar acceso ssh y http:


resource "aws_security_group" "allow_ssh" {
name = "allow_ssh"
description = "Allow SSH inbound traffic"
vpc_id = var.vpc_id

ingress {
description = “SSH from VPC”
from_port = 22
to_port = 22
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”]
}

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

tags = {
Name = “allow_ssh”
}
}

resource “aws_security_group” “allow_http” {
name = “allow_http”
description = “Allow http inbound traffic”
vpc_id = var.vpc_id

ingress {
description = “http from VPC”
from_port = 80
to_port = 80
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”]
}

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

tags = {
Name = “allow_http”
}
}

En este caso estamos definiendo una regla que permite el tráfico al puerto SSH (22) y el HTTP (80) desde cualquier parte del mundo. para que podamos conectarnos a nivel de red con la VPS desde donde queramos. Luego deberemos asociar esto a la VPS.

EIP, Elastic IP

Una cosa curiosa en AWS con las VPS de EC2 es que la ip pública que genera para acceder a la VPS desde internet cambia cada vez que reinicias la máquina, para resolver este problema, AWS tiene las Elastic IP, que se pueden asociar a una máquina y nos da un IP que no va a cambiar independientemente de las veces que reiniciemos la máquina.  Veamos cómo definirla:


resource "aws_eip" "eip" {
instance = aws_instance.web.id
vpc = true
tags = {
Name = "${var.project_name}-web-epi"
}
}

Después para acceder a este valor necesitaremos saber cual es esa IP que nos han asignado a la VPS. Para ello generaremos un Output de Terraform:

output "eip_ip" {
description = "The eip ip for ssh access"
value = aws_eip.eip.public_ip
}

User Data

user_data en un parámetro de la creación de una instancia que permite la ejecución de código mediante un script, veamos el ejemplo del fichero userdata.sh:


#!/usr/bin/env bash
set -x
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
export PATH="$PATH:/usr/bin"
sudo apt-get update
sudo apt-get -y install nginx
sudo mkfs -t xfs /dev/nvme1n1
sudo mkdir /mnt/demo_web_volume
sudo mount /dev/nvme1n1 /mnt/demo_web_volume
sudo rm -rf /var/www/html
sudo mkdir /mnt/demo_web_volume/html
sudo ln -s /mnt/demo_web_volume/html /var/www/html
sudo echo "

Hola Terraform

" >> /var/www/html/index.html
sudo chown -R www-data:www-data /var/www/html/index.html
sudo chmod -R 755 /var/www/html/index.html

Si queremos ejecutar este script debemos crear una plantilla que cargue este script:

data "template_file" "userdata" {
template = "${file("${path.module}/userdata.sh")}"
}

Desde la definición del recurso de la instancia le diremos que use esta plantilla para ejecutarla.

Instancia EC2

Ahora ya podemos definir la VPS en EC2.


data "aws_ami" "ubuntu" {
most_recent = true

filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}

filter {
name = "virtualization-type"
values = ["hvm"]
}

owners = ["099720109477"] # Canonical
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
availability_zone = var.availability_zone
instance_type = var.instance_type
vpc_security_group_ids = [
aws_security_group.allow_ssh.id,
aws_security_group.allow_http.id
]
user_data = "${data.template_file.userdata.rendered}"
key_name = aws_key_pair.deployer.key_name
tags = {
Name = "${var.project_name}-web-instance"
}
}

En este recurso estamos asociando casi todos lo demás, además de definir el tipo de instancia, esta vez por variable. El ami tal como definimos anteriormente, buscaremos la última imagen de ubuntu 20.04, necesitamos también definir la zona disponible, asociarle el key pair, los security groups como array, el user_data a ejecutar en el arranque y el nombre como tag de la VPS asociado al nombre del proyecto.

Volume Attachment

En este caso es cómo asociamos el volumen a la VPS a través de un nombre de dispositivo /dev/sdh en este caso. Aunque luego lo veremos con el nombre /dev/nvmen1, tal como definimos en el script userdata.sh


resource "aws_volume_attachment" "web" {
device_name = "/dev/sdh"
volume_id = aws_ebs_volume.web.id
instance_id = aws_instance.web.id
}

Ouputs/Salidas

En este caso definiremos las variables necesarias para interactuar con la máquina:

output "ssh" {
value = "ssh -l ubuntu ${aws_eip.eip.public_ip}"
}
output "url" {
value = "http://${aws_eip.eip.public_ip}/"
}

Despliegue

Ahora ya sólo nos faltaría hacer los pasos de siempre:

  • $ terraform validate
  • $ terraform plan
  • $ terraform apply
  • y para borrar la infraestrcutura $ terraform destroy

 

Comments

Leave a Reply

*

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

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

Suscríbete al Boletín

Si quieres estar al tanto de las novedades del blog, ya sabes :)
* = campo obligatorio

powered by MailChimp!

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información. ACEPTAR

Aviso de cookies