Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 75

ECS Cluster and Networking with Terraform

Recommended resources

Olá! Bem-vindo à nossa décima terceira lição do curso.

Na lição anterior, estabelecemos a base teórica da Infraestrutura como Código (IaC), focando na abordagem declarativa do Terraform e no seu fluxo de trabalho plan/apply. Agora, é hora de transformar essa teoria em prática.

O nosso objetivo nesta lição é escrever uma configuração Terraform para definir um Cluster ECS e a sua rede subjacente (VPC e Sub-redes). Vamos construir a fundação na AWS onde nossos contêineres .NET serão executados. Você escreverá seu primeiro código HCL (HashiCorp Configuration Language) e usará os comandos do Terraform para provisionar recursos reais na nuvem.

1. Preparando o Ambiente Terraform

Antes de definirmos os recursos, precisamos configurar nosso projeto Terraform e dizer a ele como se autenticar na AWS. Como você é um desenvolvedor experiente, a prática de separar a configuração da lógica será familiar.

Estrutura do Projeto e Configuração do Provider

Vamos criar um diretório para nosso projeto e, dentro dele, três arquivos iniciais:

  1. provider.tf: Declara os provedores que o Terraform usará (neste caso, o provedor AWS).
  2. variables.tf: Define as variáveis de entrada para nossa configuração, tornando-a reutilizável.
  3. terraform.tfvars: Atribui valores a essas variáveis. Este arquivo geralmente contém informações sensíveis ou específicas do ambiente e não deve ser versionado no Git.

O artigo a seguir demonstra exatamente essa estrutura.

Streamlining AWS ECS Infrastructure with Terraform

Vamos usar a seção "Configure Provider & Input Variables" do artigo "Streamlining AWS ECS Infrastructure with Terraform" do AWS in Plain English como nosso guia.

Leia a seção "Step 3: Configure Provider & Input Variables". Siga as instruções para criar os três arquivos: provider.tf, variables.tf, e terraform.tfvars. Por enquanto, defina apenas as variáveis aws_region e profile em variables.tf e seus respectivos valores em terraform.tfvars. Usaremos as outras variáveis mais tarde.

Seu provider.tf deve se parecer com:

provider "aws" {
  region  = var.aws_region
  profile = var.profile
}

Seu variables.tf:

variable "aws_region" {
  description = "Região da AWS para provisionar os recursos"
  type        = string
}

variable "profile" {
  description = "Perfil da AWS CLI para usar para autenticação"
  type        = string
}

E seu terraform.tfvars:

aws_region = "us-east-1" // ou a região de sua preferência
profile    = "default"   // ou o nome do seu perfil AWS configurado

Inicializando o Terraform

Com os arquivos no lugar, abra seu terminal no diretório do projeto e execute:

terraform init

Este comando, como vimos na lição anterior, lê seu código, identifica os provedores necessários (neste caso, aws) e baixa os plugins correspondentes para o subdiretório .terraform. Você só precisa executar init quando adiciona um novo provedor ou módulo.


2. Definindo a Rede: VPC e Sub-redes

A base de qualquer infraestrutura na AWS é a rede. Para o ECS, precisamos de uma Virtual Private Cloud (VPC), que é sua rede privada e isolada na nuvem. Dentro da VPC, criaremos sub-redes:

  • Sub-redes Públicas: Têm acesso direto à internet através de um Internet Gateway. Usaremos estas para o nosso Balanceador de Carga (Application Load Balancer) em uma lição futura, pois ele precisa ser acessível publicamente.
  • Sub-redes Privadas: Não têm acesso direto à internet. Nossos contêineres rodarão aqui por segurança. Elas podem acessar a internet para tarefas como baixar imagens do ECR através de um NAT Gateway, que atua como um intermediário.
AWS VPC Resource Map Overview
Esta imagem do console da AWS mostra uma representação visual dos componentes que vamos criar: uma VPC contendo sub-redes, tabelas de rotas e um internet gateway.

Escrevendo o network.tf

Vamos criar um novo arquivo, network.tf, para definir todos os nossos recursos de rede. O vídeo a seguir oferece um excelente passo a passo visual da criação de cada um desses recursos.

How to create AWS VPC with Subnets using Terraform

O vídeo "How to create AWS VPC with Subnets using Terraform" do canal Cloud Champ explica claramente como definir cada recurso de rede. Assista para entender o propósito de cada bloco de código que vamos escrever.

Assista dos timestamps 00:57 a 07:23. Foque em entender: 1) A sintaxe de um bloco resource. 2) Como o ID de um recurso (ex: aws_vpc.myvpc.id) é usado para conectar outros recursos a ele. 3) O propósito do aws_internet_gateway e do aws_route_table.

Agora, vamos escrever o código. Usaremos o código do artigo Streamlining AWS ECS Infrastructure with Terraform porque ele cria uma arquitetura robusta com sub-redes públicas e privadas em múltiplas zonas de disponibilidade, o que é uma prática recomendada para alta disponibilidade.

Adicione o seguinte conteúdo ao seu arquivo network.tf. Dividimos em partes com explicações.

Parte 1: VPC e Sub-redes

// network.tf

data "aws_availability_zones" "available" {}

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "ecs-app-vpc"
  }
}

resource "aws_subnet" "public" {
  count                   = 2 // Criar 2 sub-redes públicas
  vpc_id                  = aws_vpc.main.id
  cidr_block              = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index + 2)
  availability_zone       = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true // Atribui IP público automaticamente

  tags = {
    Name = "ecs-app-public-subnet-${count.index}"
  }
}

resource "aws_subnet" "private" {
  count             = 2 // Criar 2 sub-redes privadas
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]

  tags = {
    Name = "ecs-app-private-subnet-${count.index}"
  }
}
  • data "aws_availability_zones": Obtém a lista de Zonas de Disponibilidade (AZs) na sua região.
  • resource "aws_vpc" "main": Define nossa VPC com um bloco de IPs 10.0.0.0/16.
  • resource "aws_subnet": Usamos count = 2 para criar duas sub-redes de cada tipo (pública e privada), uma em cada uma das duas primeiras AZs disponíveis, garantindo alta disponibilidade.
  • Referência de Recurso: Note como usamos aws_vpc.main.id para associar as sub-redes à nossa VPC. Esta é a sintaxe declarativa do Terraform para criar dependências.

Parte 2: Conectividade com a Internet

// network.tf (continuação)

resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "ecs-app-igw"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0" // Para todo o tráfego
    gateway_id = aws_internet_gateway.gw.id // Enviar para o Internet Gateway
  }

  tags = {
    Name = "ecs-app-public-rt"
  }
}

resource "aws_route_table_association" "public" {
  count          = 2
  subnet_id      = aws_subnet.public[count.index].id
  route_table_id = aws_route_table.public.id
}
  • aws_internet_gateway: Cria o gateway que permite a comunicação entre a VPC e a internet.
  • aws_route_table: Define uma tabela de rotas que direciona todo o tráfego de saída (0.0.0.0/0) para o Internet Gateway.
  • aws_route_table_association: Associa esta tabela de rotas às nossas sub-redes públicas.
Teste seu entendimento!

No bloco resource "aws_route_table_association" "public", estamos usando a expressão aws_subnet.public[count.index].id. Por que usamos [count.index] aqui, mas em resource "aws_internet_gateway" "gw" usamos aws_vpc.main.id diretamente?

Show answer

Usamos [count.index] porque o recurso aws_subnet.public foi definido com count = 2. Isso significa que o Terraform cria uma lista de duas sub-redes. aws_subnet.public refere-se a essa lista, e aws_subnet.public[0] e aws_subnet.public[1] referem-se aos elementos individuais. O count.index no recurso de associação itera sobre essa lista, criando uma associação para cada sub-rede.

Já o recurso aws_vpc.main foi definido sem count, então aws_vpc.main refere-se a um único objeto, e podemos acessar seus atributos (como .id) diretamente.

Neste ponto, você já tem uma rede funcional! Você pode validar seu trabalho executando terraform plan. Este comando deve mostrar que o Terraform planeja criar todos esses recursos de rede.


3. Definindo o Cluster ECS

Com a rede pronta, definir o cluster ECS é surpreendentemente simples. Um cluster ECS é um agrupamento lógico para seus serviços e tarefas. Com o Fargate, o cluster em si não tem custo nem provisiona servidores; ele atua como um namespace para organizar seus recursos de computação.

Vamos criar um novo arquivo, ecs.tf, para os recursos do ECS.

// ecs.tf

resource "aws_ecs_cluster" "main" {
  name = "my-app-cluster" // Dê um nome ao seu cluster

  tags = {
    Name = "my-app-cluster"
  }
}

Isso é tudo! Este simples bloco de código instrui o Terraform a criar um cluster ECS.

Para visualizar, o vídeo a seguir mostra a criação do cluster.

Take full control of ecs fargate using terraform

Esta seção do vídeo "Take full control of ecs fargate using terraform" demonstra a simplicidade de criar o recurso aws_ecs_cluster.

Assista do timestamp 03:55 a 04:30. Observe como o recurso aws_ecs_cluster é definido com apenas um nome.


4. Provisionando a Infraestrutura

Agora que todo o nosso código está escrito, vamos usar o fluxo de trabalho do Terraform para criar os recursos na AWS.

  1. Planejar: Execute terraform plan novamente. A saída agora deve incluir não apenas os recursos de rede, mas também o aws_ecs_cluster. Revise o plano para garantir que ele corresponde ao que você espera.

  2. Aplicar: Se o plano estiver correto, execute:

    terraform apply
    

    O Terraform mostrará o plano novamente e pedirá sua confirmação. Digite yes e pressione Enter.

O processo pode levar alguns minutos. O Terraform provisionará a VPC, sub-redes, gateways, tabelas de rotas e o cluster ECS na sua conta AWS. Após a conclusão, você pode navegar pelo console da AWS para os serviços de VPC e ECS para ver seus novos recursos criados por código!


Conclusão

Parabéns! Você passou da teoria à prática e escreveu sua primeira configuração Terraform para provisionar uma infraestrutura de nuvem significativa.

Principais Pontos:

  • Aprendemos a estruturar um projeto Terraform com provider.tf, variables.tf, e arquivos de recursos como network.tf.
  • Você escreveu código HCL para definir recursos da AWS, incluindo aws_vpc, aws_subnet, aws_internet_gateway, aws_route_table, e aws_ecs_cluster.
  • Entendemos como referenciar atributos de um recurso para criar dependências, como usar aws_vpc.main.id ao criar uma sub-rede.
  • Utilizamos o fluxo de trabalho terraform init, plan, e apply para inicializar, visualizar e provisionar a infraestrutura.

Próxima Lição:

Nós construímos a fundação: a rede e o cluster. No entanto, ainda não há nada sendo executado. Na próxima lição, vamos definir o "o quê" e o "como" da nossa aplicação. Você aprenderá a usar o Terraform para definir uma Definição de Tarefa ECS (ECS Task Definition), que é o blueprint para nosso contêiner .NET, e um Serviço ECS (ECS Service), que é responsável por executar e manter o número desejado de instâncias da nossa tarefa no cluster.