Deploy de uma AWS EC2 com Airflow usando Terraform e Ansible

Gabriel Luz
Gabriel Luz
Published in
8 min readDec 16, 2021

Olá, pessoal! Bem vindos a mais um post do blog.

Esse post será um tutorial de como fazer o deploy de uma instância EC2 na AWS contendo a aplicação Airflow dockerizada. Esse deploy será feito usando as ferramentas de Infra as Code, Terraform e Ansible.

Desde já adianto que essa não é a melhor forma de usar o Airflow na AWS. Tomei esse caminho pois estou estudando Infra as Code e queria subir uma aplicação dessa forma. Abordagens usando o ECS, o EKS ou o próprio serviço de Airflow da AWS podem ser melhores.

Antes de prosseguir, caso voce nao esteja familiarizado com o conceito de Infra as Code, sugiro a leitura deste artigo antes. Neste post faço uma breve introdução ao Terraform e como usá-lo para fazer deploy de uma EC2 na AWS. Como ainda não tratei do Airflow aqui no blog, vou fazer uma breve explicação sobre essa ferramenta. No futuro, dedicarei um artigo inteiro sobre ela.

Pessoal, para seguir este tutorial, será necessário a instalação na máquina local o Terraform, o Ansible e a AWS CLI.

Apache Airflow

Segundo a definição do site oficial da ferramenta:

“Airflow é uma plataforma desenvolvida pela comunidade para criar, programar e monitorar workflows de maneira programática.”

Criada em 2015 pelo Airbnb e posteriormente disponibilizada de forma open-source, o Airflow é um sistema de gerenciamento de fluxo de trabalho (WMS — Workflow Management System) usado para gerir pipelines de processamento de dados. Ele pode criar, programar e monitorar tarefas de maneira programática.

É importante destacar que o Airflow em si não é uma ferramenta de processamento de dados, ou seja, não há fluxo de dados entre as diferentes etapas. Em vez disso, o Airflow é usado para coordenar a movimentação de dados entre outras ferramentas de armazenamento e processamento.

No Airflow existe um conceito denominado DAG (Directed Acyclic Graph), que consiste em um grupo de tarefas que dependem umas das outras e são executadas de acordo com um código. Cada DAG é equivalente a um workflow lógico e seus itens são executados em determinada ordem e como o próprio nome diz, Acyclic, não podem ser realizados em loop. Cada DAG, por sua vez, é formada por diferentes Operators, que se trata da definição das tarefas (tasks) a serem executadas no workflow. Ou seja, enquanto que uma DAG define o que será feito, um Operator consiste no que será feito. Existem diversos tipos de Operators disponíveis e são passíveis de customização. Alguns exemplos são:

  • BashOperator: executa comandos em bash.
  • PythonOperator: executa uma função em python.
  • SimpleHttpOperator: envia um request HTTP.
  • MySqlOperator, MsSqlOperator, JdbcOperator etc: executa um comando SQL.

O Airflow possibilita que uma única DAG use até mesmo máquinas separadas, portanto, os operadores devem ser independentes. Na imagem abaixo é possível ver o exemplo gráfico de uma DAG.

Hands On

Antes de mais nada, coloquei todo o código do projeto neste repositório no meu github.

Neste projeto, existem duas fases. A primeira é o provisionamento da infraestrutura em si, ou seja, a EC2 e suas dependências. Essa etapa é responsabilidade do Terraform. A segunda etapa, por sua vez, responsabilidade do Ansible, é onde iremos realizar a configuração do Airflow na instância criada.

Como primeiro passo, iremos criar um arquivo chamado main.tf, onde iremos descrever via HCL (Hashicorp Configuration Language) toda a infra que desejamos criar. Os primeiros itens a serem adicionados serão o terraform e provider, conforme mostra o código abaixo. O bloco terraform é usado para configurar alguns comportamentos do próprio Terraform, como exigir uma versão mínima para aplicar sua configuração. Neste exemplo, fizemos uso de uma boa prática, que é adicionar o arquivo de estado do Terraform em um bucket S3 (não público, obviamente) na AWS. Isso é aconselhável pois o .tfstate pode conter informações sensíveis como credenciais de acesso. Então essa é uma medida de segurança bastante recomendada. O bloco provider por sua vez, é onde configuramos o provedor que será usado para o deploy da infra, no nosso caso, a AWS. Perceba que nessa parte do código especifiquei a região onde quero que os recurso estejam disponíveis e a conta que será usada. Realizei este último passo pois possuo mais de uma conta AWS na minha CLI local, portanto foi necessário dizer qual delas o Terraform deveria usar. Para mais detalhes sobre esse passo, é válido olhar este link da documentação oficial.

A etapa seguinte é realizar as configurações de tráfego e acesso na instância criada. Isso é feito através dos security groups da AWS e suas regras de entrada e saída (ingress e egress). O código abaixo mostra a criação dos grupos de segurança para a nossa EC2. Para este projeto, usaremos basicamente os protocolos SSH (porta 22) para conectar na instância e o HTTPS (porta 443) para realizar o download das imagens docker. De forma ideal, seria mais seguro especificar as portas, protocolos e somente o meu IP dentro do CIDR block. Para fins de simplicidade deixei bastante aberto mas que fique claro que não é a prática recomendada. Assim que terminar este projeto irei destruir os recursos. Para cenários de deploy em produção, recomendo especificar todos esses parâmetros que citei.

Em seguida, iremos instanciar no código do Terraform o startup script (user data) da EC2, que é essencialmente o que a máquina irá executar assim que for criada. No nosso caso, será feita a instalação do docker e docker compose.

E o arquivo sh que armazenará o user data fica como o código abaixo:

Posteriormente, iremos criar um ip elástico. Isso quer dizer, um endereço IP que não mude. Independente se a EC2 é ligada e desligada, o endereço IP não será modificado.

A próxima etapa é o bloco de criação da instância em si. O nome da instância será airflow-iac. Nas duas primeiras linhas definimos a imagem linux que será usada (ami), escolhi a Amazon Linux (baseada na distro Red Hat) por questões de familiaridade, bem como o modelo da máquina, no caso a t3.medium. Não selecionei um modelo mais simples pois o Airflow é uma aplicação mais pesada e que requer mais recursos. Em seguida, especifique a key_name, que é chave de segurança da EC2, que permitirá o acesso via SSH. Este recurso em particular precisa ser criado primeiro no console da AWS (seção Key Pairs) e então referenciado no código do Terraform. Depois, referenciamos os grupos de segurança criados anteriormente e o IP elástico que criamos no último passo. Logo após, referenciamos o arquivo de startup da máquina e por último, criamos a tag para instância. A criação de tags é uma boa prática na AWS pois permite o melhor rastreio de recursos.

Com o código pronto, iremos começar a fazer o deploy da instância. O primeiro passo é executar o comando terraform init. Ele irá iniciar o Terraform. A mensagem que você irá receber será como a imagem abaixo.

Em seguida, iremos executar o comando terraform plan. Esse comando irá fazer com que o Terraform mostre para você todos os recursos que serão criados ou alterados. Por último, iremos executar o terraform apply, que faz o papel de deploy em si. Quando o apply finalizar, você poderá ver no console da AWS a EC2 criada e pronta para uso.

Com a infraestrutura pronta, iremos para a parte de configuração da aplicação em si. O primeiro passo será criar um arquivo chamado hosts.yml, que irá dizer onde o Ansible deverá realizar a configuração. Neste arquivo, precisamos de um nome para o host e seu IP, no caso, o IP da EC2 que acabamos de criar. A seguir mostro como ficou o meu:

A seguir, iremos criar o arquivo que o Ansible usará como base para configuração, o playbook.yml. Neste arquivo, colocamos basicamente todos os comandos que o Ansible irá executar na EC2. Para realizar a instalação do Airflow, usaremos o docker, que possui o processo de configuração e comandos explicados neste link no site oficial.

Com os arquivos hosts.yml e playbook.yml prontos, o Ansible está pronto para ser executado. Para isso, usaremos o comando abaixo. Nele passamos o playbook que será executado, o user da máquina (ec2-user), a chave de acesso (airflow-iac2.pem) e o arquivo de hosts.

>> ansible-playbook playbook.yml -u ec2-user — private-key airflow-iac2.pem -i hosts.yml

O output do Ansible será algo parecido com isso aqui:

Quando todas as etapas forem executadas com sucesso, poderemos entrar no Airflow da nossa EC2 pelo seguinte link: IP_maquina:8080

Para acessar a aplicação basta digitar o login airflow e a senha também airflow.

Com isso, temos a aplicação Airflow rodando na nossa EC2 e deployada usando as ferramentas de Infra as Code, Terraform e Ansible 😄

Para destruir os recursos criados, basta executar o comando terraform destroy.

Conclusão

Muito bom! Agora já fizemos um projeto bem básico de Infra as Code na AWS. O objetivo deste artigo era somente ensinar como subir a aplicação na instância EC2 na AWS. Como sugestão de trabalhos futuros para esse projeto, seria muito válido adicionar um pipeline de CI/CD para que o deploy seja realmente automatizado.

Em posts futuros irei abordar o uso do Airflow em maiores detalhes. Espero que tenha curtido o tutorial e estou disponível para tirar quaisquer dúvidas ou trocar uma ideia. Feedbacks são sempre bem vindos!

--

--

Gabriel Luz
Gabriel Luz

Estudante de engenharia eletrônica, aspirante a cientista de dados e apaixonado por tecnologia.