Only this pageAll pages
Powered by GitBook
1 of 15

Português (Brazilian Portuguese)

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Terraform

Terragrunt

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.

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.

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 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)

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.

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.

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.

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 é 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 -

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.

Patrocinadores

Please if you want to become a sponsor.

Traduções

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, , ou curta um já aberto que você julga ser importante e deva ter prioridade.

Autores

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

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-2023 Anton Babenko.

Conceitos chave

A documentação oficial do Terraform descreve. 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 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 utiliza módulo de recursos tais como o e para gerenciar infraestrutura necessária para executar o no .

Outro exemplo é o módulo , onde vários módulos do 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.

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 , 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 , onde o nome do arquivo é calculado chamando um script Python externo.

A fonte de dados 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 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 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. .

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

Infraestrutura grande com o Terraform

Fonte:

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

  • 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

  • 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.

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"
}
https://raw.githubusercontent.com/antonbabenko/terraform-best-practices/master/snippets/locals.tf
https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/large-terraform
Terraform Registry
Estruturas de código de exemplos com o Terragrunt.

Compliance.tf — Terraform Compliance Simplified. Make your Terraform modules compliance-ready.

—

Terraform
https://www.terraform-best-practices.com/
contact me
abra um problema no Github
Anton Babenko
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)
    }
  }

}
todos os aspectos da configuração em detalhes
módulo AWS VPC Terraform
terraform-aws-atlantis
terraform-aws-vpc
terraform-aws-security-group
Atlantis
AWS Fargate
terraform-aws-cloudquery
terraform-aws-modules
externa
terraform-aws-lambda
http
estado Terraform
terraform-aws-security-group
Existem várias maneiras de compartilhar dados entre as configurações
Composição de infraestrutura simples

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 e plantas criadas com o .

  • Utilize o 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 é 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 ).

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 para se familiarizar com ele e os repositórios existentes (por exemplo, ) onde ele já é utilizado.

terraform-docs

O é 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 para atualizar a documentação automaticamente.

@todo: Document module versions, release, GH actions

Recursos

  1. Blog post by :

mermaid
cloudcraft.co
Terraform pre-commit hooks
pre-commit
supported hooks
pre-commit-terraform
terraform-aws-vpc
terraform-docs
pre-commit-terraform hooks
pre-commit framework homepage
Collection of git hooks for Terraform to be used with pre-commit framework
Dean Wilson
pre-commit hooks and terraform - a safety net for your repositories
العربية (Arabic)
Bosanski (Bosnian)
English
Français (French)
ქართული (Georgian)
Deutsch (German)
ελληνικά (Greek)
עברית (Hebrew)
हिंदी (Hindi)
Bahasa Indonesia (Indonesian)
Italiano (Italian)
日本語 (Japanese)
ಕನ್ನಡ (Kannada)
한국어 (Korean)
Polski (Polish)
Română (Romanian)
简体中文 (Simplified Chinese)
Español (Spanish)
Türkçe (Turkish)
Українська (Ukrainian)
اردو (Urdu)

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

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 tupoaws_route_table, então aws_nat_gatewaydeve 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 oaws_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].id, "")
}

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_security_group.web.*.id), [""]), 0)
}

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
}

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 única da AWS. Região única. Ambiente único.

Sim

Diversas contas e ambientes na AWS, módulos de infraestrutura prontos para o uso utilizando o Terraform.

Sim

Muitas contas na AWS, muitas regiões, necessidade urgente de reduzir copiar e colar, módulos de infraestrutura personalizados, uso intenso de composições. Utilizando o Terraform.

Trabalho em progresso

muito grande (nível Enterprise)

Diversos provedores (AWS, GCP, Azure). Implementações em diversas nuvens. Utilizando o Terraform.

Não

Estruturas de código do Terragrunt

Tipo
Descrição
Disponibilidade

médio

Diversas contas e ambientes na AWS, módulos de infraestrutura prontos para o uso utilizando o Terragrunt.

Não

grande

Muitas contas na AWS, muitas regiões, necessidade urgente de reduzir copiar e colar, módulos de infraestrutura personalizados, uso intenso de composições. Utilizando o Terragrunt.

Não

muito grande (nível Enterprise)

Diversos provedores (AWS, GCP, Azure). Implementações em diversas nuvens. Utilizando o Terragrunt.

Não

pequeno
médio
grande