Deploy AWS ECS através do Terraform e Gitlab CI/CD

Iluiz Sousa
9 min readMay 24, 2021

--

Terraform e AWS ECS Service

Fala pessoal!!

No laboratório de hoje vou falar um pouco sobre o Amazon ECS.

Basicamente o Amazon ECS (Amazon Elastic Container Service) pode ser entendido como um serviço de gerenciamento de contêineres escalável que oferece suporte à Docker. Mas, como nesses posts falo muito sobre IaC, não seria diferente, irei fazer o provisionamento da infraestrutura via Terraform.

Você pode consultar mais detalhes sobre o Serviço AWS ECS neste clicando aqui.

Além disso, esse laboratório conta com outros elementos, pois procurei abranger alguns processos comuns para deploy de contêineres no dia a dia.

Então também preparei um Dockerfile para gerar uma imagem docker via CI/CD do Gitlab e posteriormente enviar essa imagem para o repositório ECR (Amazon Elastic Container Registry) na AWS. Abaixo você pode conferir a topologia completa do laboratório.

Topologia do laboratório

Requisitos de Infraestrutura para ECS:

Para utilizar o ECS, precisei criar os seguintes recursos:

  • Uma VPC (Virtual Private Cloud) e todos os componentes de conectividade: Subnet, Internet Gateway, Rotas, etc.
  • Auto Scaling Group para provisionamento das instancias EC2
  • Load Balance com interface para internet para acesso à aplicação no container
  • ECR
  • Grupos de Segurança

No decorrer do post irei detalhar o código para construção desses recursos.

Cada instancia EC2 trabalhará com um host para os containers que serão referenciados através das nossas definições de tarefas.

Abaixo a arquitetura para exemplificar o funcionamento de um cluster ECS:

ECS — Arquitetura

O Terraform

Como disse acima, utilizarei o terraform para o deploy da infraestrutura necessária do ECS. Primeiramente antes de começar a “codar” a infraestrutura é necessário se pensar sobre onde será armazenado o estado do Terraform.

O Estado Terraform é um dos componentes mais importantes desta fantástica ferramenta da Hashicorp. O Estado do Terraform (tfstate) é o arquivo que contêm toda a informação da infraestrutura que será provisionada e também o parâmetro de comparação entre o que se é planejado para deploy e o que já existe no mundo real.

Mãos a obra e bora terraformar!

Primeiramente é necessário definir o bloco de provider que é o responsável por dizer ao Terraform para qual API ele deve se conectar e baixar os plugins necessários e na sequencia será definido o bloco de backend que é responsável por informar onde será armazenado o estado terraform.

É uma boa prática manter o arquivo de estado do terraform remotamente por motivos de facilitar a colaboração e padronização do processo.

provider.tf

A autenticação com o provider AWS pode se dar através do AWS CLI via comando aws configure. Esse será o modelo que adotarei para assim não expor as minhas credenciais aqui.

Definindo a Rede

Eu normalmente gosto de segregar os arquivos do terraform por recurso, por exemplo, para o provisionamento da VPC criei um arquivo chamando vpc.tf, que pode ser visto abaixo:

vpc.tf

Utilizei o recurso locals do Terraform para facilitar o reaproveitamento das tags conforme for “codando” os outros recursos. Aqui vai uma dica: Utilize quantas tags for necessário em sua conta AWS, isso facilita demais troubleshootings e identificação de recursos.

Na sequência, preciso definir o recurso Internet Gateway para permitir a comunicação da minha VPC com o mundo externo, mais conhecido como a Internet.

igw.tf

O próximo passo é definir as subnets que é o segmento de rede pertencente a VPC que foi criada. A subnet comportará as instancias EC2 que serão definidas mais a frente.

subnet.tf

Agora que tenho VPC, Internet Gateway e Subnets, preciso criar uma rota para dizer por onde o tráfego da minha VPC deve ser direcionado. Para este laboratório irei definir a rota 0.0.0.0/0 apontando para o Internet Gateway.

route.tf

Tudo certo? Não!

De fato, os recursos de rede foram definidos mas ainda é preciso configurar o Grupo de segurança, que será responsável por permitir ou bloquear o acesso aos recursos.

sg.tf

Certo, agora que tenho definido as minhas regras de entrada e meu grupo de segurança, o próximo passo será definir os recursos relacionados ao serviço de Compute da AWS.

Autoscaling Group

O Autoscaling Group é o serviço responsável por gerenciar as instancias EC2. Utilizaremos essas instâncias para receber o agente ECS e também o serviço do Docker. Por essa razão antes de definir o Auto Scaling group, é necessário prover uma função IAM para essas instancias.

iam_role.tf

Agora sim o Auto Scaling Group:

asg.tf

Repare que destaquei 3 pontos nessa imagem:

  • Image ID: o AMI que foi fornecido para este laboratório trata-se de uma imagem “ECS-Optimized”. Você pode utilizar a AMI que desejar, no entanto, sugiro a preferencia por imagens “ECS-optimized”, pois estas já vem com agente ECS instalado e também com o Docker.
  • User Data: Esse parâmetro permite que comandos ou qualquer outra definição de usuário seja enviado a instância quando esta é provisionada. Nesse caso, o script em destaque informa para a instancia que será provisionada a qual cluster ECS ela pertence.
  • Key Name: Utilizei esse parâmetro para associar o par chaves existente na AWS a instancia que será provisionada. Lembrando que o cluster é formado a partir das instancias EC2 que são provisionadas a partir do Auto Scaling Group, num eventual troubleshooting, o acesso a essas instancias se faz necessário.

Agora preciso configurar o Load Balance que irá receber as requisições da internet via HTTP. Nas configurações do Load Balance preciso informar qual o listener e também qual o Target Group, ou seja para quem o Load Balance deverá encaminhar o tráfego.

lb.tf

Finalmente, o evento principal, senhores(as): O ECS!

Primeiramente irei definir o ECR:

ecr.tf

Na sequência, irei definir um output para o recurso ECR. Esse output terá a função de informar qual a URL do repositório para qual eu devo realizar o push das imagens dos meus containers.

output.tf

Agora irei definir as configurações do meu cluster ECS:

ecs.tf

Na sequencia a minha definição de Tarefa:

ecs.tf

A minha task definition, possui as informações para funcionamento do meu container, como utilização de cpu e memória, porta, volumes, etc. Aqui estou utilizando uma função do terraform jsonencode para converter o bloco de configuração em json. Você pode também definir as informações da sua definição de tarefa num arquivo json a parte e importar isso na configuração do terraform.

Por fim, a configuração do Service do ECS:

ecs.tf

Hora de iniciar, planejar e aplicar!

Primeiro comando que preciso aplicar é o terraform init:

terraform init

A saída do comando nos informa o sucesso em carregar as informações do tfstate armazenado no bucket S3, conforme fiz no inicio do post.

Agora, terraform plan:

Se o projeto não conter erros de sintaxe, na configuração dos blocos e declaração de variáveis o terraform através do plano, quantos recursos serão provisionados.

Por fim, vamos aplicar:

O recurso que levou mais tempo para a criação foi o Auto Scaling Group

Mesmo assim, foram menos de 6 minutos para criar toda a infraestrutura

Certo, a infraestrutura está pronta, acabou?

A infraestrutura está provisionada, no entanto, ainda é preciso realizar o push da imagem Docker para que o ECS instancia os meus containers.

Gitlab CI/CD

O Gitlab é uma plataforma que permite realizar gerenciamento de código dentre outras funções. É uma ferramenta poderosa, mas farei um post em outro momento para detalhar alguns aspectos dele.

Abaixo segue a configuração do pipeline no gitlab para realizar o build da imagem e na sequência o push para o ECR:

CI/CD Pipelines do GitLab

Basicamente aqui estou utilizando uma imagem Docker que possui o AWS CLI instalado para fazer todo o processo de push da imagem para a AWS.

Ao final do pipeline é possível ver a versão da imagem que foi enviada para o ECR:

Console da AWS

Nesse momento com a infraestrutura toda provisionada, vamos ver o resultado:

Primeiramente vou checar o status do meu Service:

Service ECS

É possível ver que existem duas Tarefas em execução, vamos ver mais detalhes disso:

Tasks ECS

Na guia das tarefas é possível identificar a partir de qual Definição de tarefa o container foi iniciado e quem foi o responsável. Além disso, é apresentado também as instancias que estão rodando os containers. Irei acessar uma dessas instâncias para verificar informações relacionadas aos containers.

E é isso! Nosso laboratório foi concluído.

Considerações Finais

Bem pessoal, esse laboratório foi bem abrangente, vou deixar algumas referencias abaixo caso se interessem por mais detalhes dos assuntos abordados aqui. Toda crítica, sugestão é bem-vinda, a ideia é compartilhar conhecimento e cada vez mais disseminar o DevOps. Isso é bom para todo mundo.

Ainda não acabamos…

Esse post é a primeira parte de duas. Existem vários gaps a serem cobertos aqui. Primeiramente nosso listener do load balance esá configurado apenas para requisições http. Precisamos configurar um certificado SSL. Irei abordar também a análise de segurança do front-end de uma aplicação, containers e código do terraform. Ou seja, no próximo post cobriremos vários aspectos de segurança negligenciados (propositalmente) nesse laboratório.

Até a próxima pessoal!

Referências e Indicações:

--

--

Iluiz Sousa

Tentando me tornar o que chamam de engenheiro DevOps.