Desplegamos una App en Amazon ECS Usando Terraform y CodePipeline

Desplegamos una App en Amazon ECS Usando Terraform y CodePipeline

En este artículo, voy a mostrar cómo configurar un pipeline en AWS para desplegar una aplicación web de Python en un clúster de Amazon ECS (Elastic Container Service). Para esto, vamos a usar Terraform para definir la infraestructura como código y CodePipeline para gestionar la automatización del flujo de despliegue. Por último, haremos la aplicación accesible a través de un Application Load Balancer (ALB).

¿Qué cubriremos en este artículo?

  1. Configuración del pipeline de despliegue con AWS CodePipeline: Tomaremos el código de un repositorio de GitHub, lo construiremos en una imagen Docker y lo subiremos a Amazon ECR.

  2. Despliegue en ECS: Implementaremos el servicio de ECS utilizando Fargate y desplegaremos nuestra imagen Docker.

  3. Exponer la aplicación con un ALB: Configuraremos un ALB para que la aplicación sea accesible desde Internet.

  4. Automatización con Terraform: Veremos cómo orquestar todo el proceso utilizando Terraform.

¡Arrancamos!

1. Preparación del entorno

Requisitos previos:

  • Cuenta de AWS: Tenes que tener una cuenta de AWS configurada.

  • Repositorio en GitHub: Asegúrate de tener un repositorio con una aplicación simple en Python.

  • Conocimientos básicos de Terraform: Si no estás familiarizado con Terraform, revisa su documentación oficial para entender lo basico.

Nuestra aplicación Python será una simple impresión de "Hello World". El código estará en un archivo llamado app.py dentro del repositorio de GitHub.

Código Python:

print("Hello World!")

2. Configuración de la Infraestructura con Terraform

Proveedor de AWS

Empezamos definiendo el proveedor de AWS en el archivo main.tf para que Terraform sepa dónde desplegar la infraestructura.

provider "aws" {
  region = "us-east-1"
}

Configuración de CodePipeline

AWS CodePipeline es el servicio que automatiza el flujo de despliegue. El pipeline tendrá tres fases:

  1. Source: Descarga el código de tu repositorio en GitHub.

  2. Build: CodeBuild toma el código, lo empaqueta en una imagen Docker y lo sube a Amazon ECR.

  3. Deploy: Deploy a ECS Fargate, que ejecutará la imagen Docker.

Definición de la fase de Source

El siguiente bloque de código en Terraform define cómo se configurará la fase de Source para obtener el código desde GitHub:

stage {
  name = "Source"

  action {
    name             = "GitHub_Source"
    category         = "Source"
    owner            = "ThirdParty"
    provider         = "GitHub"
    version          = "1"
    output_artifacts = ["source_output"]

    configuration = {
      Owner      = "<YOUR_GITHUB_USERNAME>"
      Repo       = "<YOUR_GITHUB_REPOSITORY>"
      Branch     = "main"
      OAuthToken = var.github_token
    }
  }
}

Código para la fase de Build

En la fase de Build, vamos a usar AWS CodeBuild para crear una imagen Docker a partir del código fuente. Aquí está la configuración de la fase de Build:

stage {
  name = "Build"

  action {
    name             = "CodeBuild"
    category         = "Build"
    owner            = "AWS"
    provider         = "CodeBuild"
    version          = "1"
    input_artifacts  = ["source_output"]
    output_artifacts = ["build_output"]

    configuration = {
      ProjectName = aws_codebuild_project.codebuild_project.name
    }
  }
}

CodeBuild usa un archivo buildspec.yml dentro del repositorio para definir los comandos de construcción. Aquí está el contenido del archivo buildspec.yml:

version: 0.2

phases:
  build:
    commands:
      - echo "Building Docker image"
      - docker build -t hello-world-app .
      - $(aws ecr get-login --no-include-email --region us-east-1)
      - docker tag hello-world-app:latest <YOUR_ECR_IMAGE_URL>:latest
      - docker push <YOUR_ECR_IMAGE_URL>:latest

artifacts:
  files:
    - imagedefinitions.json

3. Despliegue en ECS con Fargate

Amazon ECS es un servicio de orquestación de contenedores que te permite ejecutar aplicaciones Docker a escala. Para este ejemplo, usaremos AWS Fargate, una modalidad de ECS sin necesidad de gestionar servidores.

Crear un clúster de ECS

El siguiente bloque en main.tf crea un clúster de ECS:

resource "aws_ecs_cluster" "ecs_cluster" {
  name = "ecs-cluster"
}

Crear la tarea de ECS

Una tarea de ECS define cómo se ejecutará tu contenedor. En este caso, queremos que nuestro contenedor exponga el puerto 80 para servir nuestra aplicación web.

resource "aws_ecs_task_definition" "ecs_task" {
  family                   = "hello-world-task"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "256"
  memory                   = "512"

  container_definitions = jsonencode([
    {
      name  = "hello-world-container",
      image = "<YOUR_ECR_IMAGE_URL>:latest",
      essential = true,
      portMappings = [
        {
          containerPort = 80,
          hostPort      = 80
        }
      ]
    }
  ])
}

4. Exponer la Aplicación con un Application Load Balancer (ALB)

Para que nuestra aplicación sea accesible desde Internet, necesitamos un Application Load Balancer (ALB). El ALB distribuirá el tráfico entrante a nuestras tareas ECS.

Crear el ALB

resource "aws_lb" "app_load_balancer" {
  name               = "ecs-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = ["<YOUR_SECURITY_GROUP_ID>"]
  subnets            = ["<YOUR_SUBNET_ID>"]
}

Target Group y Listener

El Target Group define las tareas ECS que recibirán el tráfico, y el Listener define el puerto en el que el ALB recibirá las solicitudes (en este caso, el puerto 80):

resource "aws_lb_target_group" "ecs_target_group" {
  name     = "ecs-target-group"
  port     = 80
  protocol = "HTTP"
  vpc_id   = "<YOUR_VPC_ID>"
}

resource "aws_lb_listener" "app_lb_listener" {
  load_balancer_arn = aws_lb.app_load_balancer.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.ecs_target_group.arn
  }
}

5. Cómo ejecutar el código y acceder a la aplicación

Después de configurar todo el código de Terraform, ejecuta los siguientes comandos:

1- Inicializa Terraform:

terraform init

2- Aplica la configuración para desplegar toda la infraestructura:

terraform apply

Una vez que la infraestructura esté lista, podrás acceder a la URL pública del ALB (que puedes obtener desde la consola de AWS bajo la sección de Load Balancers). La URL será algo como:

http://<ALB-DNS-NAME>

Al abrir esta URL en tu navegador, deberías ver el mensaje "Hello World!".

En este articulo vimos cómo construir un pipeline de despliegue automatizado utilizando AWS CodePipeline, ECS y un Application Load Balancer.

Este flujo nos permite tomar código desde GitHub, empaquetarlo en una imagen Docker, subirlo a Amazon ECR y desplegarlo automáticamente en ECS.

Por ultimo, exponemos nuestra aplicación con un ALB para hacerla accesible desde cualquier lugar.

Este enfoque basado en infraestructura como código (IaC) con Terraform permite que todo el proceso sea repetible y escalable.