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.
Gerar um Projeto Terraform
Seção intitulada “Gerar um Projeto Terraform”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 yarn nx g @aws/nx-plugin:terraform#project npx nx g @aws/nx-plugin:terraform#project bunx nx g @aws/nx-plugin:terraform#project- Instale o Nx Console VSCode Plugin se ainda não o fez
- Abra o console Nx no VSCode
- Clique em
Generate (UI)na seção "Common Nx Commands" - Procure por
@aws/nx-plugin - terraform#project - Preencha os parâmetros obrigatórios
- Clique em
Generate
Monte seu comando5
Obrigatório
nameObrigatóriostringO nome do projeto.
typeenumPadrão:applicationSe este é uma lib terraform (módulos reutilizáveis) ou app (implantável).
applicationlibrarydirectorystringPadrão:packagesO diretório do novo projeto.
subDirectorystringO subdiretório onde o projeto é colocado. Por padrão, este é o nome do projeto.
preferInstallDependenciesbooleanPadrão:trueSe 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.
Saída do Gerador
Seção intitulada “Saída do Gerador”O gerador cria diferentes estruturas de arquivos dependendo do tipo de projeto:
Tipo Application
Seção intitulada “Tipo 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-destroyandinittargets- 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 initwith the S3 backend config - env.ts Points
terraform initat the shared provider cache
- checkov.yml Checkov configuration, including the checks to skip
- project.json Project configuration and build targets
Tipo Library
Seção intitulada “Tipo 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
Implementando sua Infraestrutura Terraform
Seção intitulada “Implementando sua Infraestrutura Terraform”Você pode começar a escrever sua infraestrutura Terraform dentro de src/main.tf, por exemplo:
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 hereresource "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.
Dependências entre projetos
Seção intitulada “Dependências entre projetos”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.
Configuração de Ambiente
Seção intitulada “Configuração de Ambiente”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 variablesenvironment = "prod"aws_region = "us-west-2"{ "targets": { "apply": { "executor": "nx:run-commands", "defaultConfiguration": "dev", "configurations": { "dev": { "command": "terraform apply ../../../dist/packages/infra/terraform/dev.tfplan" }, "prod": { "command": "terraform apply ../../../dist/packages/infra/terraform/prod.tfplan" } }, "options": { "forwardAllArgs": true, "cwd": "{projectRoot}/src" }, "dependsOn": ["plan"] }, "destroy": { "executor": "nx:run-commands", "defaultConfiguration": "dev", "configurations": { "dev": { "command": "terraform destroy -var-file=env/dev.tfvars" }, "prod": { "command": "terraform destroy -var-file=env/prod.tfvars" } }, "options": { "forwardAllArgs": true, "cwd":"{projectRoot}/src" }, "dependsOn": ["init"] }, "init": { "executor": "nx:run-commands", "defaultConfiguration": "dev", "configurations": { "dev": { "env": { "TF_ENV": "dev" } }, "prod": { "env": { "TF_ENV": "prod" } } }, "options": { "forwardAllArgs": true, "commands": ["tsx {projectRoot}/scripts/init.ts {projectRoot}"], "cwd": "{workspaceRoot}" } }, "plan": { "executor": "nx:run-commands", "defaultConfiguration": "dev", "configurations": { "dev": { "command": "terraform plan -var-file=env/dev.tfvars -out=../../../dist/packages/infra/terraform/dev.tfplan" }, "prod": { "command": "terraform plan -var-file=env/prod.tfvars -out=../../../dist/packages/infra/terraform/prod.tfplan" } }, "options": { "forwardAllArgs": true, "cwd": "{projectRoot}/src" }, "dependsOn": ["init"] } }}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:
pnpm nx bootstrap tf-infrayarn nx bootstrap tf-infranpx nx bootstrap tf-infrabunx nx bootstrap tf-infraTargets Disponíveis
Seção intitulada “Targets Disponíveis”Os targets disponíveis dependem do tipo do seu projeto:
Targets Comuns (Application e Library)
Seção intitulada “Targets Comuns (Application e Library)”Validando sua Infraestrutura
Seção intitulada “Validando sua Infraestrutura”Você pode validar sua configuração Terraform usando o target validate:
pnpm nx validate tf-infrayarn nx validate tf-infranpx nx validate tf-infrabunx nx validate tf-infraLinting
Seção intitulada “Linting”Projetos Terraform usam terraform fmt para verificar a formatação.
Executando o Linter
Seção intitulada “Executando o Linter”Para invocar o linter para verificar seu projeto, você pode executar o target lint.
pnpm nx lint tf-infrayarn nx lint tf-infranpx nx lint tf-infrabunx nx lint tf-infraCorrigindo Problemas de Lint
Seção intitulada “Corrigindo Problemas de Lint”A maioria dos problemas de linting ou formatação pode ser corrigida automaticamente executando com o argumento --configuration=fix.
pnpm nx lint tf-infra --configuration=fixyarn nx lint tf-infra --configuration=fixnpx nx lint tf-infra --configuration=fixbunx nx lint tf-infra --configuration=fixDa mesma forma, se você quiser corrigir todos os problemas de lint em todos os pacotes no seu workspace, você pode executar:
pnpm nx run-many --target lint --all --configuration=fixyarn nx run-many --target lint --all --configuration=fixnpx nx run-many --target lint --all --configuration=fixbunx nx run-many --target lint --all --configuration=fixPulando Problemas de Lint
Seção intitulada “Pulando Problemas de Lint”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:
pnpm nx run-many --target build --configuration=skip-lintyarn nx run-many --target build --configuration=skip-lintnpx nx run-many --target build --configuration=skip-lintbunx nx run-many --target build --configuration=skip-lintIsso pula a verificação de formato inteiramente durante o build.
Testes de Segurança
Seção intitulada “Testes de Segurança”Execute verificações de segurança em sua infraestrutura usando Checkov com o target checkov:
pnpm nx checkov tf-infrayarn nx checkov tf-infranpx nx checkov tf-infrabunx nx checkov tf-infraVocê 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:
skip-check: - CKV_AWS_115 # Concurrent execution limit - CKV_AWS_116 # Dead Letter QueuePara 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"}Executando Testes Terraform
Seção intitulada “Executando Testes Terraform”O target test executa o framework de testes nativo do Terraform sobre quaisquer arquivos .tftest.hcl no seu projeto:
pnpm nx test tf-infrayarn nx test tf-infranpx nx test tf-infrabunx nx test tf-infraUm 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:
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.
Targets Exclusivos de Application
Seção intitulada “Targets Exclusivos de Application”Os seguintes targets estão disponíveis apenas para projetos do tipo application:
Planejando sua Infraestrutura
Seção intitulada “Planejando sua Infraestrutura”Antes de aplicar mudanças, você pode ver o que o Terraform fará executando o target plan:
pnpm nx plan tf-infrayarn nx plan tf-infranpx nx plan tf-infrabunx nx plan tf-infraIsso 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.
Inicializando o Terraform
Seção intitulada “Inicializando o Terraform”Inicialize seu diretório de trabalho Terraform com o target init:
pnpm nx run tf-infra:inityarn nx run tf-infra:initnpx nx run tf-infra:initbunx nx run tf-infra:initImplantando na AWS
Seção intitulada “Implantando na AWS”Após planejar, você pode implantar sua infraestrutura na AWS usando o target apply:
pnpm nx apply tf-infrayarn nx apply tf-infranpx nx apply tf-infrabunx nx apply tf-infraObtendo Outputs
Seção intitulada “Obtendo Outputs”Recupere valores de saída da sua configuração Terraform:
pnpm nx output tf-infrayarn nx output tf-infranpx nx output tf-infrabunx nx output tf-infraDestruindo Infraestrutura
Seção intitulada “Destruindo Infraestrutura”Quando você precisar derrubar sua infraestrutura, use o target destroy:
pnpm nx destroy tf-infrayarn nx destroy tf-infranpx nx destroy tf-infrabunx nx destroy tf-infraDestruindo Recursos de Bootstrap
Seção intitulada “Destruindo Recursos de Bootstrap”Para limpar os recursos de bootstrap (bucket S3 para armazenamento de estado):
pnpm nx bootstrap-destroy tf-infrayarn nx bootstrap-destroy tf-infranpx nx bootstrap-destroy tf-infrabunx nx bootstrap-destroy tf-infraIsso 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.
Mais Informações
Seção intitulada “Mais Informações”Para mais informações sobre Terraform, consulte a Documentação do Terraform e a Documentação do AWS Provider.