Terraform e DigitalOcean: Infra as code nunca foi tão simples!

Terraform é uma ferramenta multiplataforma para construir, modificar e versionar uma infraestrutura com segurança.
Com ele você escreve um código, numa linguagem declarativa e de fácil compreensão tudo o que você precisa em sua infra.
A ferramenta suporta vários provedores como AWS, DigitalOcean, Google Cloud e etc.
Dependendo do provedor que você usar é possível definir desde as configurações mais low-level (rede, firewall) até as mais high-level (banco de dados, load balancer e etc).

Ao descrever sua infra como código você elimina a necessidade de configurar tudo na mão e documentar toda essa configuração, pois a documentação é o código que você escreve.
Para saber o que será feito, basta rodar “terraform plan”. Para aplicar, “terraform apply” é o caminho.
Isso sem falar sobre as vantagens de ter esse código versionado, e ainda automatizar a atualização da infra num processo de deploy.

Eu estou começando a brincar com Terraform agora, e nesse artigo vamos criar uma infra básica, com duas maquininhas e um load balancer para distribuir a carga entre elas.
Para testar se essa coisa funciona, vamos pedir para o Terraform provisionar essas máquinas com o Apache.

Instalando o Terraform

Antes de mais nada, vamos baixar a aplicação no site oficial. No momento da escrita deste texto a última versão é a 0.12. O programa é multiplataforma, então basta escolher na página de download a versão apropriada para seu sistema.
Depois de baixado basta descompactar o arquivo zip e mandá-lo para uma pasta que esteja em seu path:

$ sudo unzip -d /usr/local/bin terraform_0.12.7_linux_amd64.zip

Agora é só ser feliz!

Autenticar o Terraform com a DigitalOcean

Antes de começar a fazer qualquer coisa, você precisa de um token de API da DigitalOcean. Você pode gerar um personal accestoken aqui.
Depois de gerar esse token, guarde-o numa variável de ambiente de nome DIGITALOCEAN_TOKEN ou DIGITALOCEAN_ACCESS_TOKEN.
Você pode configurar esse token no arquivo Terraform, mas isso não é interessante se você for subir sua configuração para um repositório. Afinal você não quer que ninguém tenha acesso a seu personal access token, certo?

Algumas explicações

O Terraform usa uma linguagem de configuração chamada HCL.
Ela é uma linguagem muito simples. Trata-se de um conjunto de blocos, com alguns campos “chave=valor”.

Os arquivos devem conter a extensão .tf.
Você pode dividir sua configuração em vários arquivos, sem se preocupar em incluí-los um no outro pois o Terraform sabe exatamente a ordem dos recursos a serem executados quando você referencia alguma variável em algum arquivo. Isso é muito interessante, diga-se de passagem.

Mão na massa

Upload da sua public key para ser usada numa droplet

Para ter acesso a uma droplet você precisa ter uma public key ou então a DigitalOcean envia uma senha de root por email.
A segunda opção não é interessante quando estamos falando de automatização, então vamos criar um
arquivo de nome ssh.tf, que será o responsável por fazer o upload de sua chave pública para
a DigitalOcean:

resource "digitalocean_ssh_key" "default" {
  name       = "Terraform"
  public_key = file("~/.ssh/id_rsa.pub")
}

Na primeira linha informamos ao Terraform que vamos usar o provider “digitalocean”, e o recurso “ssh_key”. Depois damos um nome a esse recurso, para ser referenciado mais tarde, se for preciso (nesse caso é “default”).

Na segunda linha damos um nome a chave que iremos fazer o upload, só por questão de legibilidade no painel da DigitalOcean.

Na terceira linha usamos a função file, que lê o conteúdo de um arquivo. Nesse caso o arquivo da chave pública que fica dentro de “seu-usuario/.ssh/id_rsa.pub”.

Agora para não esquecer, rode terraform init, para o programa baixar o plugin do provider da DigitalOcean, no diretório .terraform dentro do mesmo diretório do seu arquivo .tf.

Você já pode rodar terraform plan para ver o que o programa irá fazer.
Se você quer ver logo essa chave criada, pode rodar terraform apply. Mas a parte legal ainda nem começou.

Criando uma droplet

A DigitalOcean dá o nome de “droplet” para as máquinas que você cria. Então uma droplet nada mais é do que o servidor da sua aplicação.
Vamos primeiro ver o conteúdo do arquivo droplet.tf, para depois vermos as explicações:

resource "digitalocean_droplet" "web" {
  count    = 2
  name     = "web-${count.index}"
  region   = "nyc1"
  size     = "s-1vcpu-1gb"
  image    = "ubuntu-18-04-x64"
  ssh_keys = [digitalocean_ssh_key.default.fingerprint]
}

A linha 2 é uma variável reservada do Terraform, que especifica quantas vezes essa configuração deve ser executada. É o jeito de fazer um loop básico.

Na linha 3 damos o nome as máquinas. Especial aí é o ${count.index}: Isso serve para sabermos onde está o nosso loop. Então uma máquina terá o nome de “web-0” e a outra “web-1”.

nas linhas 4 – 6 especificamos qual máquina queremos (a mais barata), a região e a imagem do sistema operacional.

Na linha 7 especificamos qual chave SSH nossa máquina irá usar. Podemos especificar mais de uma, por isso a lista ([...]).
Note que, referenciamos uma variável, “digitalocean_ssh_key.default.fingerprint”. Quando criamos um recurso são retornadas algumas informações, como por exemplo o IP da droplet.
Nesse caso estamos pegando o fingerprint da chave SSH que criamos no arquivo ssh.tf.

Tá começando a ficar bonito! 🙂

Loadbalancer

Está terminando. Vamos criar o arquivo loadbalancer.tf, para apontar para as duas maquininhas que criamos acima:

resource "digitalocean_loadbalancer" "public" {
  name        = "lb-public"
  region      = "nyc1"
  droplet_ids = digitalocean_droplet.web[*].id

  forwarding_rule {
    entry_port      = 80
    entry_protocol  = "http"
    target_port     = 80
    target_protocol = "http"
  }

  healthcheck {
    port     = 22
    protocol = "tcp"
  }
}

Quando criamos um loadbalancer significa que temos mais de uma máquina. Na linha 4 especificamos os ids das máquinas que criamos no passo anterior.
A expressão digitalocean_droplet.web[*].id expande para algo como [digitalocean_droplet.web[0].id, digitalocean_droplet.web[1].id].

Nas linhas 6 – 11 definimos que o loadbalancer irá escutar na porta 80 e redirecionar para a porta 80 das máquinas.

Já nas linhas 13 – 16 definimos uma regra de healthcheck. Se a máquina responder na porta 22 TCP então está tudo certo.

Provisionando as máquinas

Se até agora você já rodou terraform apply alguma vez, está na hora de ver a mágica.
O Terraform identifica mudanças em qualquer um dos recursos, então depois desse próximo passo ele não irá criar tudo de novo, irá apenas atualizar a droplet.
Vamos editar o arquivo droplet.tf, logo abaixo das informações da máquina, acima do “}”, para adicionar alguns comandos de provisionamento:


provisioner "remote-exec" { inline = [ "apt update", "apt install -y apache2", "echo server-${count.index}>/var/www/html/index.html", "chown www-data:www-data /var/www/html/index.html", ] connection { type = "ssh" host = self.ipv4_address user = "root" private_key = file("~/.ssh/id_rsa") timeout = "2m" } }

Acima usamos o provisionador “remote_exec” para executar alguns comandos na máquina via SSH.
O que fizemos foi instalar o Apache e criar um arquivo “index.html” em “/var/www/html” com a frase “web-numero-do-servidor”.

Como testar? Qual o IP do meu loadbalancer?

Calma! Criando o arquivo output.tf você pode saber tudo o que você deseja:

output "droplets_ipv4_addresses" {
  value = digitalocean_droplet.web[*].ipv4_address
}

output "loadbalancer_ip_address" {
  value = digitalocean_loadbalancer.public.ip
}

Agora sempre que você rodar terraform apply o programa irá mostrar o IP das suas duas droplets e do seu loadbalancer.
Para testar basta acessar o IP do loadbalancer. Hora ele vai cair no web-0, hora no web-1. Se isso acontecer, parabéns para nós!

Fim

Depois de testar, se tudo correu bem, é sempre bom rodar terraform destroy se você não for usar isso e não quiser ser cobrado.

Nessa introdução não fizemos praticamente nada.
A DigitalOcean permite criar bancos de dados na nuvem (digitalocean_database), apontar o domínio para o loadbalancer (digitalocean_domain), proteger as máquinas com um firewall (digitalocean_firewall), etc.
Você pode ir brincando e testando tudo isso. O céu é o limite.

Se você ficou com preguiça de acompanhar o texto, aqui está um repositório no GitHub com o código que eu coloquei aqui.
Não deixe de ler a documentação do provider DigitalOcean para Terraform.

Qualquer crítica, elogio, sugestão, comenta aí!
Até a próxima!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *