Pular para o conteúdo

Infraestrutura Terraform

Terraform é uma ferramenta de software de infraestrutura como código de código aberto que permite criar, alterar e melhorar a infraestrutura de forma segura e previsível.

O gerador de infraestrutura Terraform cria um projeto de infraestrutura Terraform. A aplicação gerada inclui práticas recomendadas de segurança através de verificações de segurança do Checkov.

Você pode gerar um novo projeto Terraform de duas maneiras:

Execute este gerador@aws/nx-plugin:terraform#project

pnpm nx g @aws/nx-plugin:terraform#project
Monte seu comando5

Obrigatório

Opções do gerador5 opções
nameObrigatóriostring

O nome do projeto.

typeenumPadrão: application

Se este é uma lib terraform (módulos reutilizáveis) ou app (implantável).

applicationlibrary
directorystringPadrão: packages

O diretório do novo projeto.

subDirectorystring

O subdiretório onde o projeto é colocado. Por padrão, este é o nome do projeto.

preferInstallDependenciesbooleanPadrão: true

Se deve preferir instalar dependências após a execução do gerador. Defina como false para adiar a instalação ao executar múltiplos geradores em lote (uma instalação ainda é executada se necessário para que geradores subsequentes possam calcular o grafo de projetos Nx); instale uma vez no final.

O gerador cria diferentes estruturas de arquivos dependendo do tipo de projeto:

type = application

Para projetos de aplicação (--type=application), o gerador cria uma aplicação Terraform completa com gerenciamento de estado remoto:

  • Directorysrc
    • main.tf Main Terraform configuration file
    • providers.tf Provider configuration with S3 backend
    • variables.tf Input variable definitions
    • outputs.tf Output value definitions
    • Directoryenv Environment-specific variable files
      • dev.tfvars Development environment variables
  • Directorybootstrap Bootstrap configuration for remote state
    • main.tf S3 bucket and policies for state storage
    • providers.tf AWS provider configuration
    • variables.tf Bootstrap variable definitions
  • Directoryscripts Node helpers run by the nx bootstrap, bootstrap-destroy and init targets
    • aws-config.ts Resolves account + region via the AWS SDK credential chain
    • bootstrap.ts Pulls/pushes the bootstrap tfstate and runs terraform apply
    • bootstrap-destroy.ts Empties the state bucket and runs terraform destroy
    • init.ts Runs terraform init with the S3 backend config
    • env.ts Points terraform init at the shared provider cache
  • checkov.yml Checkov configuration, including the checks to skip
  • project.json Project configuration and build targets
type = library

Para projetos de biblioteca (--type=library), o gerador cria uma estrutura mais simples para módulos Terraform reutilizáveis:

  • Directorysrc
    • main.tf Main Terraform module file
  • checkov.yml Checkov configuration, including the checks to skip
  • project.json Project configuration and build targets

Você pode começar a escrever sua infraestrutura Terraform dentro de src/main.tf, por exemplo:

src/main.tf
locals {
account_id = data.aws_caller_identity.current.account_id
aws_region = data.aws_region.current.id
}
resource "null_resource" "print_info" {
# triggers = {
# always_run = timestamp()
# }
provisioner "local-exec" {
command = "echo 'AWS Region: ${local.aws_region}, AWS Account: ${local.account_id}, Environment: ${var.environment}'"
}
}
# Declare your infrastructure here
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-unique-bucket-name"
}

Observe que o bucket S3 acima falharia na verificação de segurança do Checkov, que verifica se o bucket tem as configurações de segurança apropriadas habilitadas.

Se você quiser executar um módulo de um projeto separado (lib), você pode fazer isso da seguinte forma:

module "lib_module" {
source = "../../path/to/my-lib/src"
}

Isso atualizará automaticamente o grafo Nx para adicionar uma dependência entre sua aplicação consumidora e sua lib.

Configure variáveis específicas do ambiente nos arquivos src/env/*.tfvars.

Para adicionar novos ambientes, crie um novo arquivo src/env/<environment>.tfvars com as variáveis específicas do ambiente e adicione novas entradas para apply, destroy, init, plan no project.json para a nova configuração de ambiente. Por exemplo, vamos supor que queremos adicionar um ambiente prod:

# Production environment variables
environment = "prod"
aws_region = "us-west-2"
type = application

Bootstrap de Estado Remoto (Somente Projetos Application)

Seção intitulada “Bootstrap de Estado Remoto (Somente Projetos Application)”

Antes de implantar sua infraestrutura, você precisará fazer o bootstrap do backend de estado remoto. Isso cria um bucket S3 para armazenar seus arquivos de estado Terraform:

Terminal window
pnpm nx bootstrap tf-infra

Os targets disponíveis dependem do tipo do seu projeto:

Você pode validar sua configuração Terraform usando o target validate:

Terminal window
pnpm nx validate tf-infra

Projetos Terraform usam terraform fmt para verificar a formatação.

Para invocar o linter para verificar seu projeto, você pode executar o target lint.

Terminal window
pnpm nx lint tf-infra

A maioria dos problemas de linting ou formatação pode ser corrigida automaticamente executando com o argumento --configuration=fix.

Terminal window
pnpm nx lint tf-infra --configuration=fix

Da mesma forma, se você quiser corrigir todos os problemas de lint em todos os pacotes no seu workspace, você pode executar:

Terminal window
pnpm nx run-many --target lint --all --configuration=fix

Para evitar que problemas de linting te atrasem durante o desenvolvimento (particularmente se você tiver problemas não corrigíveis automaticamente no seu projeto), você pode executar um build com a configuração skip-lint:

Terminal window
pnpm nx run-many --target build --configuration=skip-lint

Isso pula a verificação de formato inteiramente durante o build.

Execute verificações de segurança em sua infraestrutura usando Checkov com o target checkov:

Terminal window
pnpm nx checkov tf-infra

Você encontrará os resultados dos testes de segurança na pasta dist raiz, em dist/packages/<my-terraform-project>/checkov.

Checkov é executado como parte do build.

As verificações são configuradas no checkov.yml do projeto. Adicione um id de verificação ao skip-check para suprimi-lo em todo o projeto:

checkov.yml
skip-check:
- CKV_AWS_115 # Concurrent execution limit
- CKV_AWS_116 # Dead Letter Queue

Para suprimir uma verificação para um único recurso, adicione um comentário #checkov:skip=<id>:<reason> dentro do bloco do recurso:

resource "aws_s3_bucket" "example" {
#checkov:skip=CKV_AWS_18:Access logging not required for this bucket
bucket = "example"
}

O target test executa o framework de testes nativo do Terraform sobre quaisquer arquivos .tftest.hcl no seu projeto:

Terminal window
pnpm nx test tf-infra

Um projeto sem arquivos de teste é um sucesso sem operação, então você pode adicionar testes quando precisar deles. O build executa este target, então seus testes são executados como parte de um build normal.

Cada bloco run avalia sua configuração. Use command = plan para verificar o que o Terraform faria (isso expande todo o grafo de módulos, então captura erros em tempo de planejamento que o validate não consegue), ou command = apply para criar recursos reais e fazer asserções sobre suas saídas. Declarar mock_provider significa que nenhuma chamada de API é feita e nenhuma credencial AWS é necessária, o que mantém os testes plan rápidos e seguros para executar em CI:

src/main.tftest.hcl
mock_provider "aws" {
mock_data "aws_caller_identity" {
defaults = { account_id = "123456789012" }
}
mock_data "aws_region" {
defaults = { region = "us-east-1" }
}
}
variables {
aws_region = "us-east-1"
environment = "dev"
}
run "plan_is_valid" {
command = plan
assert {
condition = data.aws_caller_identity.current.account_id == "123456789012"
error_message = "Unexpected account id"
}
}

Defina todas as variáveis que sua configuração requer no bloco variables, caso contrário a execução falhará com “has a required variable … with no set value”.

Cada target que executa terraform init reutiliza um cache de provedores em .terraform/plugin-cache na raiz do seu workspace, então os provedores são baixados uma vez em vez de a cada execução. Cada projeto obtém seu próprio diretório lá: duas execuções de terraform init preenchendo um cache ao mesmo tempo podem cada uma calcular um hash diferente para o mesmo provedor, que o terraform então rejeita contra seu .terraform.lock.hcl. Consulte a documentação do Terraform para mais informações.

Defina TF_PLUGIN_CACHE_DIR no seu ambiente para apontar o script init fornecido para um cache que você gerencia — um volume compartilhado entre workspaces, por exemplo. Observe que o target test lê seu caminho do project.json, então altere-o lá também.

type = application

Os seguintes targets estão disponíveis apenas para projetos do tipo application:

Antes de aplicar mudanças, você pode ver o que o Terraform fará executando o target plan:

Terminal window
pnpm nx plan tf-infra

Isso criará um arquivo de plano em dist/packages/<my-terraform-project>/terraform/dev.tfplan.

plan depende de assemble, então ele produz os artefatos que seus módulos referenciam, como os bundles Lambda e metadados de operações gerados, sem executar os gates de lint, test e type-check.

Inicialize seu diretório de trabalho Terraform com o target init:

Terminal window
pnpm nx run tf-infra:init

Após planejar, você pode implantar sua infraestrutura na AWS usando o target apply:

Terminal window
pnpm nx apply tf-infra

Recupere valores de saída da sua configuração Terraform:

Terminal window
pnpm nx output tf-infra

Quando você precisar derrubar sua infraestrutura, use o target destroy:

Terminal window
pnpm nx destroy tf-infra

Para limpar os recursos de bootstrap (bucket S3 para armazenamento de estado):

Terminal window
pnpm nx bootstrap-destroy tf-infra

Isso esvazia o bucket de estado antes de destruí-lo, e resolve a região da cadeia de credenciais do AWS SDK, então é executado sem supervisão em CI.

Para mais informações sobre Terraform, consulte a Documentação do Terraform e a Documentação do AWS Provider.