Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Refatorando Terraform do jeito certo

By Ami MahloofJan 14, 20204 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

1 dxvu13kechn6hcxbcico0w

Infraestrutura como código (IaC) não é fácil. Volta e meia, você precisa provisionar uma infraestrutura (hoje em dia quase sempre com Terraform) e acaba escrevendo um código sob medida para o seu caso de uso.

Em geral, o tempo é curto e você acaba deixando todos os valores padrão hardcoded, ainda por cima em um ou dois arquivões que concentram todo o trabalho. Muita gente pensa: "Agora eu faço funcionar e depois, quando sobrar um tempinho, vejo como melhorar".

1 dxvu13kechn6hcxbcico0wProvisionando a infraestrutura com Terraform, do jeito certo desta vez.

O tempo passa e aparece outra demanda. Quando você se dá conta, já esqueceu o que exatamente fez para "funcionar agora". Ou então outra pessoa precisa entrar no seu código para entender o que ele faz, de modo que ele atenda tanto à tarefa antiga quanto à nova.

E ainda tem aquele medo enorme de quebrar o que está funcionando só porque você resolveu "deixar melhor".

Já passei por isso várias vezes e nunca tinha encontrado um jeito de tornar o Terraform mais amigável e fácil de depurar. Até cair neste post do Yevgeniy Birkman: " 5 lessons learned from writing over 300,000 lines of infrastructure code".

Ele me abriu os olhos sobre como deixar o Terraform mais robusto, mais limpo, mais amigável e, principalmente, como ganhar a confiança necessária para fazer as mudanças e melhorias que precisam ser feitas.

Agora quero compartilhar algumas dicas e experiências sobre refatoração de Terraform. O que vem a seguir é um resumo dos slides que você encontra no fim do artigo.

Terraform monolítico

Quando você trabalha em um arquivo TF gigante, qualquer deslize derruba tudo. Além disso, o Terraform fica muito mais difícil de depurar e achar o trecho certo para mexer vira uma garimpagem demorada. Esse padrão acaba gerando código duplicado e ciclos de desenvolvimento mais lentos.

Visão a 10.000 pés

Conseguir achar rapidamente o que você procura no meio do desenvolvimento ou ao depurar um problema crítico é essencial quando se trabalha com Terraform.

O plano do Terraform consolida todos os arquivos em uma única execução, e dá para tirar bom proveito disso criando arquivos menores e com muito mais visibilidade. Em geral, esses arquivos menores acabam se transformando em um módulo mais reutilizável e combinável.

Anatomia de um módulo

As "300.000 linhas de código de infraestrutura" foram um ótimo ponto de partida, e eu fui um passo além: criei um scaffold que uso em todo módulo novo. Esse scaffold dá mais visibilidade e serve de guia no desenvolvimento.

Não existem valores hardcoded; cada valor que seria fixo vira uma variável padrão, e todo atributo do módulo é uma variável (algumas obrigatórias, outras com valor default). Todo módulo deve ter a seguinte estrutura:

0 hqwcsuil1hqfzc1f

A ideia é colocar cada coisa no seu lugar. Se o arquivo main.tf principal passar de 30 linhas, divida-o em arquivos lógicos: ec2.tf, autoscaling.tf, e por aí vai.

Uma boa prática é manter uma pasta 'examples' tanto para apoiar o desenvolvimento do módulo quanto para servir de exemplo de uso no futuro. Quando começo um módulo novo, uso o seguinte snippet para criar esse scaffold:

➜ export module_name="sample"
➜ mkdir -p $module_name/examples $module_name/test
➜ cd $module_name && touch \
main.tf \
versions.tf \
default-variables.tf \
required-variables.tf \
outputs.tf \
data.tf

Estrutura de módulos em 3 camadas

Crie e expanda sua própria biblioteca de blocos primitivos (terraform-resources)

0 rr9b5ti9vog4nfxp

Depois, monte serviços a partir desses blocos primitivos (terraform-services)

1 dw9tl65whd7uojj0amevha

Implante ambientes ponta a ponta a partir dos serviços (terraform-live-envs)

0 jg6ofalx cyd1mzc

O objetivo é isolar cada ambiente (live) — dev, staging, production — e então pegar cada componente desse ambiente e dividi-lo em módulos de serviço genéricos. Quebre cada módulo de serviço genérico em módulos de recurso, porque cada módulo deve fazer apenas uma coisa e ser o mais desacoplado possível.

Vamos passar por um exemplo:

Você tem uma instância mySQL rodando no Google Cloud SQL (terraform-live-envs), construída em cima de um serviço genérico chamado "sql", que contém dois módulos de recurso (instance e user).

1 80e5j4obfcfqsoql1nacbg

Refatorando o código Terraform

Crie um novo bucket para guardar o novo state do Terraform. Em seguida, reescreva seu código nos módulos em 3 camadas (como mostrado acima e detalhado nos slides). Importe cada recurso para o seu código Terraform de live-envs.

O Terraform vai então exibir o plano de execução da operação de importação:

[1] valores que existem na versão implantada, mas não no seu código, recebem um sinal de menos, indicando remoção.

[2] valores que não existem na versão implantada, mas estão no seu código, recebem um sinal de mais, indicando adição.

O objetivo é chegar a um ponto em que o plano não acuse nenhuma mudança.

Slides

Os slides a seguir trazem uma breve introdução ao Terraform e minhas sugestões para refatorar módulos Terraform existentes: terraform modules restructured 1 638