Logo que comecei meus primeiros passos com terraform, achei muito interessante a ideia de poder criar recursos escrevendo algumas linhas de códigos, porem na época a grande maioria dos tutorias explicava somente algumas partes de como usar, e até então, não tinha achado algum tutorial mostrando a criação de algum projeto, modulo, ou pipiline com o terraform, foi então que surgiu o propósito de escrever essa sequência de 6 posts mostrando a criação de uma aplicação, e como podemos aplicar no nosso dia a dia.

Outro ponto que me motivou a iniciar essa sequência de artigos, era que queria aprender algumas novas ferramentas e criar algum projeto de ponta a ponta que ajudasse quem está começando a se familiarizar com terraform, ci/cd, aws, docker, etc.

Esse primeiro post vai ser dedicado mais a configuração da nossa maquina e falar algumas coisas básicas que acho muito importante sobre como funciona e como vamos criar nosso projeto. Dividi a criação desse projeto em 6 partes que são:

  1. The Big Bang
  2. O Projeto Parte 1.
  3. O Projeto Parte 2.
  4. Boas práticas
  5. Deploy de aplicações.
  6. Automatizando o processo

Requisitos básicos

Bom, antes de começar cada artigo vou fazer um checklist dos requisitos básicos para conseguir concluir com sucesso o tutorial. Nesta primeira etapa vamos utilizar basicamente 3 recursos, que são:

  • Conta na aws
  • aws-cli
  • Terraform

Conta na AWS

Para criar a conta na AWS é simples, basta acessar esse link e seguir os passos descritos. Com sua conta criada, você poderá utilizar seus diversos recursos e “brincar” com os que existe na plataforma(cuidado com seus gastos). Para saber os recursos free que você tem, basta acessar esse outro link.

aws-cli

Outro recurso que precisamos é o aws-cli(command line interface), sua instalação é bem simples, basta seguir os seguintes passos:

$ pip install awscli --upgrade --user
$ aws --version

Para mais informações, basta acessas esse link.

Terraform

O último recurso que precisamos é o Terraform, que basicamente é uma ferramenta open-source que vai nos ajudar a provisionar e versionar nossa infraestrutura. Sua instalação é bem simples, e só vamos precisar seguir os passos descritos abaixo:

$ wget https://releases.hashicorp.com/terraform/1.0.0/terraform_1.0.0_linux_amd64.zip
$ unzip terraform_1.0.0_linux_amd64.zip
$ mv terraform /usr/local/bin
$ terraform version

*Esses passos foram testados no MacOs & Linux(ubuntu|Debian).

The Big Bang

Agora com nossos pré-requisitos feitos, vamos fazer uma validação para verificar se está tudo funcionando como esperávamos. A primeira coisa que vamos precisar fazer são criar o usuário que vamos utilizar no nosso projeto(Não recomendado utilizar o usuário root). Para criar um usuário basta para nosso projeto, basta seguir esse tutorial, nas ultimas etapas você precisara adicionar alguma policies, para que possamos ter permissão de criar nossa infraestrutura. Você tem algumas opções para esse passo, como adicionar uma policy de PowerUserAccess que le dara permissão para criar tudo na aws(grandes poderes, grandes responsabilidades). Outro passo é ir adicionando as policies existentes na aws conforme for precisando, assim você consegue segregar e dar permissão para o usuário criado, usar somente o que for liberado. Caso queira saber mais como o IAM funciona, esse tutorial pode lê ajudar.

Um terceiro modo(e é o que eu mais uso) é criar uma policy nova e ir adicionando as permissões que você precisa, assim você consegue segregar bastante as permissões que o usuário vai precisar. Abaixo segue JSON com todas as permissões que vamos precisar para provisionar nossa infraestrutura.

Essa policy contem as regras que vamos precisar para esse post, caso queira, você pode ir adicionando mais permissões assim que forem sendo necessitadas.

Após ter criado nosso usuário e ter atachado alguma policy e terminado o tutorial de criação de usuário, vamos fazer o download das credencias e configurar nosso cli para que possamos usar junto com o terraform. Para isso, basta ter em mãos os valores do Access Key ID e o Secret access Key e realizar a configuração do AWS cli, conforme descrito a seguir:

$ aws configure
AWS Access Key ID [None]: <valor_access_key>
AWS Secret Access Key [None]: <valor_secret_key>
Default region name [None]: us-east-1
Default output format [None]: json

Eu estou usando a região da Virgínia, mas você pode aplicar essas configurações em qualquer região.

First commit

Bom, se tudo foi instalado e configurado corretamente(espero que não tenha esquecido nada), vamos realizar nosso primeiro deploy(básico, mas honesto).

Antes de definir nosso escopo, de como vamos criar todo nosso código, vamos fazer pequeno teste e criar um ec2 na aws, e para isso vamos criar uma pasta e um arquivo chamado main.tf e abrir com seu editor preferido para adicionar nosso código.

$ mkdir homer
$ touch homer/maint.tf
$ cd homer
$ vi maint.tf

Com o arquivo aberto, vamos adicionar o seguinte trecho de código:

provider "aws" {
  region                  = "us-east-1"
  shared_credentials_file = "$HOME/.aws/credentials"
}

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" "first_commit" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"
  key_name      = "homer"
  tags = {
    Name = "teste-homer"
  }
}

O primeiro bloco de notas, faz referência a qual provider do terraform vamos utilizar, nesse caso a aws e passo algumas informações como a região que vou quer criar e também meu arquivo de credenciais, caso queira passar outras informações, nesse link você consegue ver mais detalhado o que é possível usar.

No segundo bloco utilizo um recurso chamado Data Source(nos próximos capítulos vou detalhar mais sobre isso), nele passo algumas informações, como qual tipo de ami vou utilizar, seu owner. Esse trecho nos ajuda a deixar nosso código mais dinâmico, e podemos usar ele em outras regiões.

No último bloco escrevemos a parte em que cria propriamente o nosso Ec2 na aws, nela passo informações como a ami que vou utilizar, tipo de instance_type, e a key_name que vou vincular a minha ec2(nesse caso é uma key já existente na aws), e por último passo um name para ela.

Feito toda essa configuração, e com o arquivo devidamente salvo, vamos inicializar o processo de criação utilizando o terraform. Esse processo é dividido em 3 etapas, que são, Init, Plan e Apply.

Init

Nesse passo o terraform faz a inicialização de seu backend e provider, para inicializar ele, digite:

$ terraform init

Ele pode levar alguns segundos, mas depois de inicializado, seu output será algo como:

Terraform has been successfully initialized!

Nesse passo o terraform foi inicializado com sucesso e podemos dar continuidade no nosso artigo.

Plan

Agora é a hora da verdade, nesse momento vamos verificar se escrevemos tudo de maneira correta, e passamos todas as informações que o terraform precisa, para isso basta digitar o seguinte comando:

$ terraform plan

Se tudo ocorreu conforma o planejado, seu output deve ser algo como:

Plan: 1 to add, 0 to change, 0 to destroy.

No output tem mais informações como block device, network, ebs, etc. Nesse momento não vamos entrar em detalhes sobre isso, mas como não estamos passando nenhuma informação extra, a instância ira ser criada com os recursos padrões da aws.

Apply

Agora que realizamos nosso plan com sucesso e conseguimos verificar tudo que vai ser adicionado, vamos executar e criar nosso recurso na aws, para isso, execute o seguinte comando:

$ terraform apply

Nesse comando, vamos precisar digitar “yes” quando for pedido, para confirmar que queremos criar nosso ec2. Ele demorara menos de 1 minuto para executar o apply, e seu output será algo como:

aws_instance.first_commit: Creating...
aws_instance.first_commit: Still creating... [10s elapsed]
aws_instance.first_commit: Creation complete after 19s [id=i-02afd14d353f7b912]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Para verificar o ec2 sendo inicializado, basta verificar no console da aws.

Destroy

Agora você precisa destruir seus recursos criados, para não ficar nada nos nossos providers que não estamos utilizando, para isso, basta digitar:

$ terraform destroy

Esse comando irar destruir com tudo que foi criado e está salvo no seu tfstate, seu output será algo como:

aws_instance.first_commit: Destroying... [id=i-06f567a96370f0aac]
aws_instance.first_commit: Still destroying... [id=i-06f567a96370f0aac, 10s elapsed]
aws_instance.first_commit: Still destroying... [id=i-06f567a96370f0aac, 20s elapsed]
aws_instance.first_commit: Still destroying... [id=i-06f567a96370f0aac, 30s elapsed]
aws_instance.first_commit: Destruction complete after 34s

Destroy complete! Resources: 1 destroyed.

No console da aws, você pode verificar que a ec2 está sendo finalizada.

Houston, We have a problem!!!

Antes de começar a falar do escopo do nosso projeto e como vamos trabalhar nele, vale a pena falar um pouco sobre como o terraform trabalha e alguns problemas que possamos ter no futuro e como evitar alguns(sempre vai ter uma nova forma de fazer).

tfsate

Toda vez que você executar os comandos plan, apply e destroy o terraform precisa verificar o seu tfstate, que basicamente serve para guardar informações do estado da sua infraestrutura, e com isso acaba se tornando um arquivo que requer um pouco mais de cuidado, visto que ele guarda todo a informação do estado atual dos nossos recursos.

Nesse momento nosso tfstate está local(na nossa maquina), o que é um pouco inseguro, visto que só você será o detentor dessa informação e com isso ninguém do seu time vai conseguir subir novas features, outro ponto e também é um local onde posso vir a perder ele(rm -rf). Para contornar esse problema, o terraform tem um recurso chamado beckend onde você consegue configurar aonde vai guardar seu tfstate, assim você consegue visionar com uma maior facilidade e os demais membros da equipe, vão conseguir usar o tfstate.

Um exemplo básico de beckend, seria:

terraform {
  backend "s3" {
    bucket = "homer"
    key    = "terraform/project/homer/terraform.tfstate"
    region = "us-east-1"
  }
}

Nesse caso, toda ver que for dar um plan, vou fazer uma consulta no meu tfstate e verificar o que tem de diferente, e após fazer o apply, vou atualizar meu tfstate com as novas informações.

provider

O terraform possui muitos providers que você pode utilizar no seu projeto, e os mesmo são atualizados frequentemente, com isso sempre é bom manter eles com a versão que é compataível, como no exemplo a seguir:

terraform {
  required_providers {
    cloudflare = {
      source = "cloudflare/cloudflare"
      version = "2.22.0"
    }
  }
}

Caso não tenha o provider para o que você precisa, poderemos criar o nosso propio provider.

Primeiro Escopo

Para finalizar essa primeira parte, vamos falar um pouco sobre como vai ser o escopo do nosso projeto, e como vamos trabalhar para que ele saia do papel.

Como comentei, a ideia dessa sequência de artigos é criar um projeto que ajude desde dev que não sabe nada de terraform, até aquele que já provisionou sua infraestrutura, e é por isso que essa primeira parte foi um pouco mais básica.

Nesse primeiro momento, a ideia desse projeto é criar um código que possamos utilizar para subir nossos recursos tanto na aws, quanto em outro provider que possamos vir a utilizar.

Nosso projeto utilizara recursos independentes, ou compartilhados, como RDS, S3, Cache, SQS, SNS, etc.

A ideia no geral é que quando um dev faça um commit no repositório do seu projeto XPTO( vou usar o github) o mesmo possua uma pipeline que possibilite a atualização automática dessa nova versão no nosso projeto, outra ideia é que possamos subir nossa infra utilizando uma pipeline padrão, sem precisar rodar nada local.

No próximo capítulo, vamos escrever, vamos escreve bem mais código e adentrar nesse fantástico mundo do terraform, e começar definitivamente a criar nosso projeto.

Até mais!!!