Você está na página 1de 29

Português (Brazilian Portuguese)

Seja Bem-Vindo(a)
Este documento é uma tentativa de descrever sistematicamente as melhores
práticas usando o Terraform, e, fornecer recomendações para os problemas mais
frequentes de seus usuários.

O Terraform é um projeto relativamente novo (como a maioria das ferramentas de DevOps, na verdade) que
foi iniciado em 2014.

O Terraform é poderoso (se não o mais poderoso que existe atualmente) e uma das ferramentas mais
utilizadas que permitem o gerenciamento de infraestrutura como código (IaC). Ele permite que os
desenvolvedores realizem uma grande variedade de coisas e não os restringe de fazê-las de forma com
que sejam difíceis de integrar ou suportar à longo prazo.

Algumas informações descritas neste livro podem não parecer as melhores práticas. Sei disso, e, para
ajudar os leitores a separar as melhores práticas estabelecidas e do que apenas mais uma maneira
opinativa, às vezes, dou dicas para fornecer algum contexto e ícones para especificar o nível de maturidade
em cada subseção relacionada às melhores práticas.

Este livro começou na ensolarada Madri em 2018 e está disponível gratuitamente aqui -
https://www.terraform-best-practices.com/

Alguns anos depois, ele foi atualizado com mais práticas atuais recomendadas disponíveis com o Terraform
1.0. Eventualmente, este livro deve conter a maioria das melhores práticas e recomendações
incontestáveis para usuários do Terraform.

Traduções

English

Español (Spanish)

Bahasa Indonesia (Indonesian)

Bosanski (Bosnian)
Français (French)

Deutsch (German)

)Hebrew( ‫עברית‬

Italiano (Italian)

ಕನ್ನಡ (Kannada)

हिंदी (Hindi)

Polski (Polish)

Română (Romanian)

Türkçe (Turkish)

Українська (Ukrainian)

Entre em contato se você quer ajudar a traduzir este livro para outros idiomas.

Contribuições
Continuarei atualizando este livro conforme a comunidade amadurece e novas ideias são implementadas e
verificadas. Por favor, deixe seu comentário ou crítica construtiva para que o livro esteja sempre em boa
qualidade.
Se você tem interesse em determinados tópicos, abra um problema no Github, ou curta um já aberto que
você julga ser importante e deva ter prioridade.

Autores
Este livro é mantido por Anton Babenko com a ajuda de diversos colaboradores e tradutores.

Patrocinadores

​Cluster.dev — o único gerenciador de


infraestruturas nativas da núvem.

​Coder.com — create remote development


machines for your team, powered by Terraform.

Licença
Este trabalho está licenciado sob a Licença Apache 2. Veja LICENSE para maiores detalhes.

Os autores e colaboradores deste conteúdo não podem garantir a validade das informações aqui
encontradas. Certifique-se de que entende que as informações aqui contidas estão sendo fornecidas
livremente, e que, nenhum acordo ou contrato é criado entre você e quaisquer pessoas associadas a este
conteúdo ou projeto. Os autores e colaboradores não assumem e, por meio deste, se isentam de qualquer
responsabilidade perante qualquer parte, por qualquer perda, dano ou interrupção causada por erros, ou
omissões nas informações contidas, associadas ou vinculadas a este conteúdo, sejam tais erros ou
omissões resultantes de negligência, acidente ou qualquer outra causa.

Direito autoral © 2018-2022 Anton Babenko.


Conceitos chave

A documentação oficial do Terraform descreve todos os aspectos da configuração em detalhes. Leia-o com
atenção para entender o restante desta seção.

Recursos
Um recurso é aws_vpc , aws_db_instance , etc. Um recurso pertence a um provedor, aceita
argumentos, produz atributos e tem ciclos de vida. Um recurso pode ser criado, recuperado, atualizado e
excluído.

Módulo de Recursos
O módulo de recursos é uma coleção de recursos conectados, que juntos, executam a ação comum (por
exemplo, o módulo AWS VPC Terraform cria VPC, sub-redes, gateway NAT, etc.). Depende da
configuração do provedor, que pode ser definida nele, ou em estruturas de nível superior (por exemplo, no
módulo de infraestrutura).

Módulo de infraestrutura
Um módulo de infraestrutura é uma coleção de módulos de recursos, que podem ser logicamente não
conectados, mas na situação/projeto/configuração atual servem ao mesmo propósito. Ele define a
configuração para provedores, passada para os módulos de recursos downstream e para os recursos.
Normalmente é limitado a trabalhar em uma entidade por separar lógico (por exemplo, região da AWS,
projeto do Google).

Por exemplo, o módulo terraform-aws-atlantis utiliza módulo de recursos tais como o terraform-aws-vpc e
terraform-aws-security-group para gerenciar infraestrutura necessária para executar o Atlantis no AWS
Fargate.

Outro exemplo é o módulo terraform-aws-cloudquery, onde vários módulos do terraform-aws-modules estão


sendo utilizados juntos para gerenciar a infraestrutura, assim como utilizar recursos do Docker para criar,
enviar e implantar imagens Docker. Tudo em um conjunto.

Composição
Composição é uma coleção de módulos de infraestrutura, que podem abranger várias áreas separadas
logicamente (por exemplo, regiões da AWS, várias contas da AWS). A composição é usada para descrever
a infraestrutura completa necessária para toda a organização ou projeto.

Uma composição consiste em módulos de infraestrutura, que consistem em módulos de recursos, que
implementam recursos individuais.
Composição de infraestrutura simples

Fonte de Dados
A fonte de dados executa uma operação somente leitura e é dependente da configuração do provedor, é
também usada em um módulo de recursos e em um módulo de infraestrutura.

A fonte de dados terraform_remote_state atua como uma “cola” para módulos e composições de
nível superior.

Já uma fonte de dados externa, permite que um programa externo atue como fonte de dados, expondo
informações arbitrários para uso em outro lugar na configuração do Terraform. Aqui está um exemplo do
módulo terraform-aws-lambda, onde o nome do arquivo é calculado chamando um script Python externo.

A fonte de dados http realiza uma solicitação HTTP GET para o URL fornecido e exporta informações
sobre a resposta, o que geralmente é útil para obter informações de terminais onde um provedor Terraform
nativo não existe.

Estado Remoto
Módulos de infraestrutura e composições devem manter seu estado Terraform em um local remoto, onde
possam ser recuperados por outros de maneira controlável (por exemplo, especificar ACL, versionamento,
logging).

Provedor, Aprovisionador, etc


Provedores, provisionadores e alguns outros termos estão muito bem descritos na documentação oficial e
não vale a pena repetir aqui. Na minha opinião, eles têm pouco a ver com escrever bons módulos
Terraform.

Por que é tão difícil?


Enquanto os recursos individuais são como átomos na infraestrutura, os módulos de recursos são
moléculas. Um módulo é a menor unidade com versão e compartilhável. Possui uma lista exata de
argumentos, implementa lógica básica para que tal unidade realize a função necessária. Por exemplo, o
módulo terraform-aws-security-group cria recursos aws_security_group e
aws_security_group_rule com base no input. Este módulo de recursos por si só pode ser usado em
conjunto com outros módulos para criar o módulo de infraestrutura.

O acesso aos dados entre moléculas (módulos de recursos e módulos de infraestrutura) é realizado
utilizando saídas e fontes de dados dos módulos.

O acesso entre composições geralmente é realizado usando fontes de dados de estado remoto. Existem
várias maneiras de compartilhar dados entre as configurações.

Ao colocar os conceitos descritos acima em pseudo-relações, pode-se ficar assim:

composition-1 {
infrastructure-module-1 {
data-source-1 => d1

resource-module-1 {
data-source-2 => d2
resource-1 (d1, d2)
resource-2 (d2)
}

resource-module-2 {
data-source-3 => d3
resource-3 (d1, d3)
resource-4 (d3)
}
}

}
Estrutura do código

As perguntas relacionadas à estrutura de código do Terraform sào de longe as mais frequentes na


comunidade. Todos pensaram na melhor estrutura de código para o projeto em algum momento também.

Como devo estruturar minhas configurações do Terraform?


Esta é uma das questões em que existem muitas soluções e é muito difícil dar conselhos dinâmicos, então
vamos começar entendendo com o que estamos lidando.

Qual é a complexidade do seu projeto?

Número de recursos relacionados.


Número de provedores Terraform (veja a nota abaixo sobre “provedores lógicos”).

Com que frequência sua infraestrutura muda?


A partir de uma vez por mês/semana/dia.

Continuamente (toda vez que houver um novo commit).


Iniciadores de mudança de código? Você permite que o servidor CI atualize o repositório quando um
novo artefato é criado?
Somente desenvolvedores podem realizar o push para o repositório de infraestrutura.
Todos podem propor uma mudança em qualquer coisa abrindo um PR (incluindo tarefas
automatizadas em execução no servidor CI).
Qual plataforma de implementação ou serviço de implementação você utiliza?

AWS CodeDeploy, Kubernetes, ou OpenShift exigem uma abordagem um pouco diferente.


Como os ambientes são agrupados?

Por ambiente, região, projeto...

Os provedores lógicos trabalham inteiramente dentro da lógica do Terraform e, muitas vezes,


não interagem com nenhum outro serviço, entao podemos pensar em sua complexidade como
O(1). Os provedores lógicos mais comuns incluem random, local, terraform, null, time.

Introdução à estruturação de configurações do Terraform


Colocar todo o código em um único main.tf é uma boa ideia quando você está começando ou
escrevendo um código de exemplo. Em todos os outros casos, será melhor ter vários arquivos divididos
logicamente assim:
main.tf - chame módulos, locais e fontes de dados para criar todos os recursos.

variables.tf - contém declarações de variáveis utilizadas em main.tf.

outputs.tf - contém saídas dos recursos criados em main.tf.

versions.tf - contém requisitos de versão para Terraform e provedores.

terraform.tfvars não deve ser utilizado em nenhum lugar exceto na composição.

Como pensar sobre a estrutura de configurações do Terraform?

Por favor, certifique-se de entender os principais conceitos - módulo de recursos,


módulo de infraestrutura e composição, conforme são utilizados nos exemplos a seguir.

Recomendações comuns para estruturar código

É mais fácil e rápido trabalhar com um número menor de recursos


terraform plan e terraform apply fazem chamada API na nuvem para verificar o status
dos recursos.
Se você tiver toda a sua infraestrutura em uma única composição, isso pode levar algum tempo.
O raio afetado é menor com menos recursos

Isolar recursos não relacionados uns aos outros, colocando-os em composições separadas, reduz
o risco se algo der errado.
Inicie seu projeto utilizando o estado remoto porque:

Seu notebook não é lugar para sua fonte de verdade de infraestrutura.

Gerenciar um arquivo tfstate no git é um pesadelo.

Mais tarde, quando as camadas de infraestrutura começarem a crescer em várias direções (número
de dependências ou recursos), será mais fácil manter as coisas sob controle.
Pratique uma estrutura consistente e uma convenção de nomenclatura:
Assim como o código procedural, o código do Terraform deve ser escrito para que as pessoas leiam
primeiro, a consistência ajudará quando as mudanças ocorrerem daqui a seis meses.
É possível mover recursos no arquivo de estado do Terraform, mas pode ser mais difícil de efetuar
se você tiver estrutura e nomenclatura inconsistentes.
Mantenha os módulos de recursos o mais simples possível.
Não codifique valores que possam ser passados como variáveis ou descobertos usando fontes de
dados.
Use fontes de dados e o terraform_remote_state especificamente como uma cola entre os
módulos de infraestrutura na composição.
Neste livro, os projetos de exemplo são agrupados por complexidade - de infraestruturas pequenas a muito
grandes. Essa separação não é rígida, portanto, verifique também outras estruturas.

Orquestração de módulos e composições de infraestrutura

Ter uma infraestrutura pequena significa haver um pequeno número de dependências e poucos recursos. À
medida que o projeto cresce, torna-se óbvia a necessidade de encadear a execução das configurações do
Terraform, conectar diferentes módulos de infraestrutura e passar valores em uma composição.

Existem pelo menos 5 grupos distintos de soluções de orquestração que os desenvolvedores usam:

1. Somente o Terraform. Muito simples, os desenvolvedores precisam conhecer apenas o Terraform para
realizar o trabalho.
2. Terragrunt. Ferramenta de orquestração pura que pode ser usada para orquestrar toda a infraestrutura,
bem como lidar com dependências. O Terragrunt opera com módulos e composições de infraestrutura
nativamente, reduzindo assim a duplicação de código.
3. Roteiros internos (in-house scripts). Muitas vezes isso acontece como um ponto de partida para a
orquestração e antes de descobrir o Terragrunt.
4. Ansible ou ferramenta de automação de uso geral similar. Geralmente utilizado quando o Terraform é
adotado após o Ansible, ou quando a “interface” do usuário do Ansible é usada ativamente.
5. Crossplane e outras soluções inspiradas no Kubernetes. Às vezes, faz sentido utilizar o ecossistema
Kubernetes e empregar um recurso de “loop” de reconciliação para atingir o estado desejado de suas
configurações do Terraform. Observe o vídeo Crossplane vs Terraform para mais informações.

Com isso em mente, este livro analisa às duas primeiras dessas estruturas de projeto, apenas Terraform e
Terragrunt.

Veja exemplos de estruturas de código para o Terraform e/ou Terragrunt no próximo capítulo.
Exemplos de estrutura de códigos

Estruturas de código do Terraform

Esses exemplos estão mostrando o provedor da AWS, mas a maioria dos princípios mostrados
nos exemplos pode ser aplicada a outros provedores de núvem pública, bem como a outros tipos
de provedores (DNS, DB, Monitoring, etc).

Tipo Descrição Disponibilidade

Poucos recursos, sem


dependências externas. Conta
pequeno Sim
única da AWS. Região única.
Ambiente único.

Diversas contas e ambientes na


AWS, módulos de infraestrutura
médio Sim
prontos para o uso utilizando o
Terraform.

Muitas contas na AWS, muitas


regiões, necessidade urgente
de reduzir copiar e colar,
grande módulos de infraestrutura Trabalho em progresso
personalizados, uso intenso de
composições. Utilizando o
Terraform.

Diversos provedores (AWS,


GCP, Azure). Implementações
muito grande (nível Enterprise) Não
em diversas nuvens. Utilizando
o Terraform.

Estruturas de código do Terragrunt


Tipo Descrição Disponibilidade

Diversas contas e ambientes na


AWS, módulos de infraestrutura
médio Não
prontos para o uso utilizando o
Terragrunt.

Muitas contas na AWS, muitas


regiões, necessidade urgente
de reduzir copiar e colar,
grande módulos de infraestrutura Não
personalizados, uso intenso de
composições. Utilizando o
Terragrunt.

Diversos provedores (AWS,


GCP, Azure). Implementações
muito grande (nível Enterprise) Não
em diversas nuvens. Utilizando
o Terragrunt.
Terragrunt
Terraform
Infraestrutura pequena com o Terraform

Fonte: https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/small-terraform

Este exemplo contém código como um exemplo de estruturação de configurações do Terraform para uma
infraestrutura de pequeno porte, onde nenhuma dependência externa é utilizada.

Perfeito para começar e refatorar à medida que avança

Perfeito para pequenos módulos de recursos


Bom para módulos de infraestrutura pequenos e lineares (ex, terraform-aws-atlantis)

Bom para um número pequeno de recursos (menos de 20-30)

Um arquivo de estado único para todos os recursos pode tornar o processo de trabalho com o
Terraform lento, se o número de recursos estiver crescendo (considere utilizar o argumento -
target para limitar o número de recursos)
Infraestrutura média com o Terraform

Fonte: https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/medium-terraform

Este exemplo contém código como um exemplo de estruturação de configurações do Terraform para uma
infraestrutura de médio porte, que utiliza:

2 contas na AWS

2 ambientes separados ( prod e stage que não compartilham nada entre eles). Cada ambiente está
em uma conta separada na AWS.

Cada ambiente utiliza uma versão diferente do módulo de infraestrutura pronto para uso ( alb )
originado do Terraform Registry
Cada ambiente utiliza a mesma versão de módulos/rede de um módulo interno, pois é originado de
um diretório local.

Perfeito para projetos em que a infraestrutura é separada logicamente (contas AWS


separadas)
Bom para quando não há necessidade de modificar recursos compartilhados entre contas da
AWS (um ambiente = uma conta da AWS = um arquivo de estado)
Bom para quando não há necessidade na orquestração de mudanças entre os ambientes

Bom para quando os recursos de infraestrutura são diferentes por ambiente de propósito e
não podem ser generalizados (por exemplo, alguns recursos estão ausentes em um
ambiente ou em algumas regiões)

À medida que o projeto cresce, será mais difícil manter esses ambientes atualizados entre sí.
Considere o uso de módulos de infraestrutura (já prontos ou internos) para tarefas repetíveis.
Infraestrutura grande com o Terraform

Fonte: https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/large-terraform

Este exemplo contém código como um exemplo de estruturação de configurações do Terraform para uma
infraestrutura de médio porte, que utiliza:

2 contas na AWS

2 regiões ( ap-southeast-2 e us-west-1 , por exemplo)

2 ambientes separados ( prod e stage que não compartilham nada entre eles). Cada ambiente está
em uma conta separada na AWS.

Cada ambiente utiliza uma versão diferente do módulo de infraestrutura pronto para uso ( alb )
originado do Terraform Registry
Cada ambiente utiliza a mesma versão de módulos/rede de um módulo interno, pois é originado de
um diretório local.

Em um grande projeto como o descrito aqui, os benefócios do uso do Terragrunt se tornam muito
visíveis. Veja Estruturas de código de exemplos com o Terragrunt.

Perfeito para projetos em que a infraestrutura é separada logicamente (contas AWS


separadas)
Bom para quando não há necessidade de modificar recursos compartilhados entre contas da
AWS (um ambiente = uma conta da AWS = um arquivo de estado)
Bom para quando não há necessidade na orquestração de mudanças entre os ambientes
Bom para quando os recursos de infraestrutura são diferentes por ambiente de propósito e
não podem ser generalizados (por exemplo, alguns recursos estão ausentes em um
ambiente ou em algumas regiões)

À medida que o projeto cresce, será mais difícil manter esses ambientes atualizados entre sí.
Considere o uso de módulos de infraestrutura (já prontos ou internos) para tarefas repetíveis.
Convenções de nomenclatura

Convenções gerais

Não deve haver razão alguma para não seguir pelo menos essas convenções :)

Esteja ciente de que os recursos reais da núvem geralmente têm restrições em nomes
permitidos. Alguns recursos, por exemplo, não podem conter travessões, alguns devem ser em
caixa de camelo (mais conhecido como CamelCase). As convenções neste livro referem-se aos
próprios nomes do Terraform.

1. Utilize _ (subtraço) ao invés do - (traço) em todo o lugar (nomes de recursos, nomes de fontes de
dados, nomes de variáveis, outputs, etc.).
2. Prefira usar letras minúsculas e números (mesmo que o UTF-8 seja suportado).

Argumentos de recursos e fontes de dados


1. Não repita a categoria de recurso no nome do recurso (não parcialmente, nem completamente):

resource "aws_route_table" "public" {}

resource "aws_route_table" "public_route_table" {}

resource "aws_route_table" "public_aws_route_table" {}

2. O nome do recurso deve ser nomeado this se não houver mais um nome descritivo e geral
disponível ou se o módulo de recurso criar um único recurso desse tipo (por exemplo, no módulo AWS
VPC há um único recurso do tipo aws_nat_gateway e vários recursos do
tupo aws_route_table , então aws_nat_gateway deve ser nomeado this e
aws_route_table deve ter nomes mais descritivos - como private , public , database ).

3. Sempre utilize substantivos singulares para nomes.


4. Utilize - em valores de argumentos e em locais onde o valor será exposto a um humano (por
exemplo, no nome de DNS da instância RDS).
5. Inclua o(s) argumento(s) count / for_each no bloco de recurso ou fonte de dados como o primeiro
argumento na parte superior e separe por uma nova linha depois dele.
6. Inclua o argumento tags, se suportadas pelo recurso, como o último argumento real, seguido por

depends_on e lifecycle , se necessário. Estes devem ser separados por uma única linha vazia.

7. Ao utilizar condições em um argumento count / for_each , prefira valores boleanos ( true /


false ) em vez de usar length ou outras expressões.

Exemplos de código de resource

Uso do count / for_each

main.tf
resource "aws_route_table" "public" {
count = 2

vpc_id = "vpc-12345678"
# ... argumentos restantes omitidos
}

resource "aws_route_table" "private" {


for_each = toset(["one", "two"])

vpc_id = "vpc-12345678"
# ... argumentos restantes omitidos
}
main.tf
resource "aws_route_table" "public" {
vpc_id = "vpc-12345678"
count = 2

# ... argumentos restantes omitidos


}

Colocação das tags

main.tf
resource "aws_nat_gateway" "this" {
count = 2

allocation_id = "..."
subnet_id = "..."

tags = {
Name = "..."
}

depends_on = [aws_internet_gateway.this]

lifecycle {
create_before_destroy = true
}
}
main.tf
resource "aws_nat_gateway" "this" {
count = 2

tags = "..."

depends_on = [aws_internet_gateway.this]

lifecycle {
create_before_destroy = true
}

allocation_id = "..."
subnet_id = "..."
}

Condições com o count

outputs.tf
resource "aws_nat_gateway" "that" { # Perfeito
count = var.create_public_subnets ? 1 : 0
}

resource "aws_nat_gateway" "this" { # Bom


count = length(var.public_subnets) > 0 ? 1 : 0
}

Variáveis
1. Não reinvente a roda em módulos de recursos: use name , description , e valor default para
variáveis conforme definido na seção “Referência de argumento” para o recurso com o qual você está
trabalhando.

2. O suporte para validação em variáveis é bastante limitado (por exemplo, não pode acessar outras
variáveis ou fazer pesquisas). Planeje de acordo porque em muitos casos esse recurso é inútil.
3. Use a forma plural em um nome de variável quando o tipo for list(...) ou map(...) .

4. Chaves de ordem em um bloco variável como: description , type , default , validation .

5. Sempre inclua description em todas as variáveis, mesmo que você julgue ser óbvio (você
precisará disso, no futuro).

6. Prefira usar tipos simples ( number , string , list(...) , map(...) , any ) sobre tipos

específicos como object() , a menos que você precise ter restrições estritas em cada chave.

7. Use tipos específicos como map(map(string)) se todos os elementos do mapa tiverem o mesmo
tipo (ex. string ) ou podem ser convertidos para ele (ex. number pode ser convertido para
string ).

8. Use tipo any para desabilitar a validação de tipo a partir de uma determinada profundidade ou
quando vários tipos devem ser suportados.
9. O valor {} às vezes é um mapa, mas às vezes é um objeto. Use tomap(...) para criar um mapa
porque não há como criar um objeto.

Outputs
Torne os outputs consistentes e compreensíveis fora de seu escopo (quando um usuário está usando um
módulo, deve ser óbvio que tipo e atributo do valor ele retorna).
1. O nome do output deve descrever a propriedade que ela contém e ser menos livre do que você
normalmente desejaria.

2. Uma boa estrutura para o nome do output parece com {name}_{type}_{attribute} , onde:

1. {name} um nome de recurso ou fonte de dados sem um prefixo de provedor. O {name} do


aws_subnet é subnet , para o aws_vpc é vpc .

2. {type} é um tipo de fontes de recursos.

3. {attribute} é um atributo retornado pelo output.

4. Veja exemplos.

3. Se o output estiver retornando um valor com funções de interpolação e vários recursos, {name} e
{type} devem ser o mais genéricos possível ( this como prefixo deve ser omisso). Veja exemplos.

4. Se o valor retornado for uma lista, deve ter um nome no plural. Veja exemplos.

5. Sempre inclua description para todos os outputs mesmo que você julgue que ser óbvio.

6. Evite definir o argumento sensitive , a menos que você controle totalmente o uso desse output em

todos os locais em todos os módulos.


7. Prefira try() (disponível desde o Terraform 0.13) ao invés de element(concat(...))
(abordagem herdada para a versão anterior a 0.13).

Exemplos de código do output

Retorne no máximo um ID do security-group :

outputs.tf
output "security_group_id" {
description = "The ID of the security group"
value = try(aws_security_group.this[0].id, aws_security_group.name_prefix[0]
}

Quando há vários recursos do mesmo tipo, this deve ser omisso no nome do output:

outputs.tf
output "this_security_group_id" {
description = "The ID of the security group"
value = element(concat(coalescelist(aws_security_group.this.*.id, aws_securi
}

Use o nome no plural se o valor de retorno for uma lista


outputs.tf

output "rds_cluster_instance_endpoints" {
description = "A list of all cluster instance endpoints"
value = aws_rds_cluster_instance.this.*.endpoint
}
Estilo de código

Os módulos de exemplos e do Terraform devem conter documentação explicando os


recursos e como usá-los.

Todos os links nos arquivos README.md devem ser absolutos para que o site do Terraform
Registry os mostre corretamente.
A documentação pode incluir diagramas criados com mermaid e plantas criadas com o
cloudcraft.co.
Utilize o Terraform pre-commit hooks para garantir que o código seja válido, formatado
corretamente e documentado automaticamente antes de ser enviado para o git e revisado
por humanos.

Documentação

Documentação gerada automaticamente

O pre-commit é um framework para gerenciar e manter hooks pré-commit multi-idioma. Ele é escrito em
Python e é uma ferramente poderosa para fazer algo automaticamente na máquina de um desenvolvedor
antes que o código seja enviado para o repositório git. Normalmente, ele é usado para executar linters e
formatar código (veja supported hooks).

Com as configurações do Terraform, o pre-commit pode ser usado para formatar e validar o código, bem
como para atualizar a documentação.

Confirma o repositório pre-commit-terraform para se familiarizar com ele e os repositórios existentes (por
exemplo, terraform-aws-vpc) onde ele já é utilizado.

terraform-docs

O terraform-docs é uma ferramente que faz a geração de documentação a partir de módulos Terraform em
vários formatos de saída (output). Você pode executá-lo manualmente (sem ganchos — pre-commit hooks
— de pré-commit) ou usar o pre-commit-terraform hooks para atualizar a documentação automaticamente.

@todo: Document module versions, release, GH actions

Recursos

1. pre-commit framework homepage


2. Collection of git hooks for Terraform to be used with pre-commit framework
3. Blog post by Dean Wilson: pre-commit hooks and terraform - a safety net for your repositories
FAQ
FTP (Frequent Terraform Problems)

Quais são as ferramentas que eu deveria estar ciente e considerar utilizar?

Terragrunt - Ferramenta de orquestração

tflint - Ferramenta de checagem de código

tfenv - Sistema de controle de versão

Atlantis - Automação de Pull Requests


pre-commit-terraform - Coleção de git hooks para Terraform para ser usado com o framework pre-
commit
Infracost - Estimativas de custo de nuvem para Terraform em solicitações de Pull Requests. Funciona
com Terragrunt, Atlantis e pré-commits também.

Quais são as soluções do Inferno de Dependências com módulos?


As versões dos módulos de recursos e infraestrutura devem ser especificadas. Os provedores devem ser
configurados fora dos módulos, mas apenas na composição. A versão dos provedores e do Terraform
podem também ser travadas.

Não existe uma ferramenta de gerenciamento de dependência mestre, mas existem algumas dicas para
tornar a dependência menos problemática. Por exemplo, o Dependabot pode ser usado para automatizar
as atualizações de dependências seguras e atualizadas. O Dependabot é compatível com as
configurações do Terraform.
Referências

Existem muitas pessoas que criam ótimos conteúdos e gerenciam projetos de código aberto
relevantes para a comunidade Terraform, mas não consigo pensar na melhor estrutura para obter
esses links listados aqui sem copiar listas como a awesome-terraform.

https://twitter.com/antonbabenko/lists/terraform-experts - Lista de pessoas que trabalham com o Terraform


muito ativamente e podem lhe dizer muito sobre (se você perguntar-lhes).

https://github.com/shuaibiyy/awesome-terraform - Lista com curadoria de recursos no Terraform da


HashiCorp.

http://bit.ly/terraform-youtube - O canal do YouTube "Your Weekly Dose of Terraform" de Anton Babenko.


Transmissões ao vivo com análises, entrevistas, perguntas e respostas, codificação ao vivo e alguns hacks
com o Terraform.

https://weekly.tf - Boletim semanal Terraform. Várias notícias no mundo Terraform (projetos, anúncios,
discussões) por Anton Babenko.
Escrevendo configurações do Terraform

Use locals para especificar dependências explícitas entre recursos


Uma maneira útil de dar uma dica ao Terraform de que alguns recursos devem ser excluídos antes mesmo
quando não houver dependência direta nas configurações do Terraform.

https://raw.githubusercontent.com/antonbabenko/terraform-best-practices/master/snippets/locals.tf

Terraform 0.12 - Argumentos obrigarórios vs opcionais

1. O argumento obrigatório index_document deve ser definido, se var.website não for um mapa
vazio.
2. O argumento opcional error_document pode ser omitido.

main.tf
variable "website" {
type = map(string)
default = {}
}

resource "aws_s3_bucket" "this" {


# omitted...

dynamic "website" {
for_each = length(keys(var.website)) == 0 ? [] : [var.website]

content {
index_document = website.value.index_document
error_document = lookup(website.value, "error_document", null)
}
}
}

terraform.tfvars
website = {
index_document = "index.html"
}
Workshop

Há também um ‘workshop’ para pessoas que desejam praticar algumas das coisas descritas neste guia.

Você pode conferir o material aqui (em inglês) - https://github.com/antonbabenko/terraform-best-practices-


workshop

Você também pode gostar