跳转到内容

Terraform 基础设施

Terraform 是一个开源的基础设施即代码软件工具,使您能够安全且可预测地创建、更改和改进基础设施。

Terraform 基础设施生成器创建一个 Terraform 基础设施项目。生成的应用程序通过 Checkov 安全检查包含安全最佳实践。

您可以通过两种方式生成新的 Terraform 项目:

运行此生成器@aws/nx-plugin:terraform#project

pnpm nx g @aws/nx-plugin:terraform#project
构建你的命令5

必需

生成器选项5 个选项
name必需string

项目的名称。

typeenum默认值: application

项目类型,是 terraform 库(可重用模块)还是应用(可部署)。

applicationlibrary
directorystring默认值: packages

新项目的目录。

subDirectorystring

项目所在的子目录。默认为项目名称。

preferInstallDependenciesboolean默认值: true

是否在生成器运行后优先安装依赖项。设置为 false 可在批量运行多个生成器时延迟安装(如果后续生成器需要计算 Nx 项目图,仍会运行安装);在最后统一安装一次。

生成器根据项目类型创建不同的文件结构:

type = application

对于应用程序项目(--type=application),生成器创建一个完整的 Terraform 应用程序,具有远程状态管理:

  • 文件夹src
    • main.tf 主 Terraform 配置文件
    • providers.tf 带有 S3 后端的提供程序配置
    • variables.tf 输入变量定义
    • outputs.tf 输出值定义
    • 文件夹env 特定环境的变量文件
      • dev.tfvars 开发环境变量
  • 文件夹bootstrap 远程状态的引导配置
    • main.tf 用于状态存储的 S3 存储桶和策略
    • providers.tf AWS 提供程序配置
    • variables.tf 引导变量定义
  • 文件夹scripts 由 nx bootstrapbootstrap-destroyinit 目标运行的 Node 辅助程序
    • aws-config.ts 通过 AWS SDK 凭证链解析账户 + 区域
    • bootstrap.ts 拉取/推送引导 tfstate 并运行 terraform apply
    • bootstrap-destroy.ts 清空状态存储桶并运行 terraform destroy
    • init.ts 使用 S3 后端配置运行 terraform init
    • env.ts terraform init 指向共享提供程序缓存
  • checkov.yml Checkov 配置,包括要跳过的检查
  • project.json 项目配置和构建目标
type = library

对于库项目(--type=library),生成器为可重用的 Terraform 模块创建一个更简单的结构:

  • 文件夹src
    • main.tf 主 Terraform 模块文件
  • checkov.yml Checkov 配置,包括要跳过的检查
  • project.json 项目配置和构建目标

您可以在 src/main.tf 中开始编写您的 Terraform 基础设施,例如:

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"
}

请注意,上面的 S3 存储桶将无法通过 Checkov 安全扫描,该扫描会检查存储桶是否启用了适当的安全设置。

如果您想从单独的项目(库)执行模块,可以按如下方式操作:

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

这将自动更新 Nx 图,在您的使用应用程序和您的库之间添加依赖关系。

src/env/*.tfvars 文件中配置特定环境的变量。

要添加新环境,请创建一个新的 src/env/<environment>.tfvars 文件,其中包含特定环境的变量,并在 project.json 中为新环境配置添加 apply, destroy, init, plan 的新条目。例如,假设我们想添加一个 prod 环境:

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

远程状态引导(仅限应用程序项目)

Section titled “远程状态引导(仅限应用程序项目)”

在部署基础设施之前,您需要引导远程状态后端。这将创建一个 S3 存储桶来存储您的 Terraform 状态文件:

Terminal window
pnpm nx bootstrap tf-infra

可用目标取决于您的项目类型:

您可以使用 validate 目标验证您的 Terraform 配置:

Terminal window
pnpm nx validate tf-infra

Terraform 项目使用 terraform fmt 来检查格式。

要调用 linter 检查您的项目,您可以运行 lint 目标。

Terminal window
pnpm nx lint tf-infra

大多数 linting 或格式化问题可以通过使用 --configuration=fix 参数运行来自动修复。

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

同样,如果您想修复工作区中所有包的所有 lint 问题,可以运行:

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

为了避免在开发过程中 linting 问题拖慢您的速度(特别是如果您的项目中有无法自动修复的问题),您可以使用 skip-lint 配置运行构建:

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

这会在构建期间完全跳过格式检查。

使用 Checkov 通过 checkov 目标对您的基础设施运行安全检查:

Terminal window
pnpm nx checkov tf-infra

您将在根 dist 文件夹下的 dist/packages/<my-terraform-project>/checkov 中找到您的安全测试结果。

Checkov 作为 build 的一部分运行。

检查在项目的 checkov.yml 中配置。将检查 ID 添加到 skip-check 以在整个项目中抑制它:

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

要仅对单个资源抑制检查,请在资源块内添加 #checkov:skip=<id>:<reason> 注释:

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

test 目标在项目中的任何 .tftest.hcl 文件上运行 Terraform 的原生测试框架

Terminal window
pnpm nx test tf-infra

没有测试文件的项目是无操作成功,因此您可以在需要时添加测试。build 运行此目标,因此您的测试作为正常构建的一部分运行。

每个 run 块评估您的配置。使用 command = plan 检查 Terraform _将会_执行的操作(这会展开整个模块图,因此它可以捕获 validate 无法捕获的计划时错误),或使用 command = apply 创建真实资源并断言其输出。声明 mock_provider 意味着不会进行 API 调用,也不需要 AWS 凭证,这使得 plan 测试快速且可以安全地在 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"
}
}

variables 块中设置配置所需的每个变量,否则运行将失败并显示”has a required variable … with no set value”。

每个运行 terraform init 的目标都在工作区根目录的 .terraform/plugin-cache 下重用提供程序缓存,因此提供程序只下载一次而不是每次运行时都下载。每个项目在那里都有自己的目录:两个 terraform init 运行同时填充一个缓存时,每个都可能为同一个提供程序计算不同的哈希值,然后 terraform 会根据您的 .terraform.lock.hcl 拒绝它。有关更多信息,请参阅 Terraform 文档

在您的环境中设置 TF_PLUGIN_CACHE_DIR 以将提供的 init 脚本指向您自己管理的缓存——例如在工作区之间共享的卷。请注意,test 目标从 project.json 读取其路径,因此也要在那里更改它。

type = application

以下目标仅适用于应用程序类型项目:

在应用更改之前,您可以通过运行 plan 目标来查看 Terraform 将执行的操作:

Terminal window
pnpm nx plan tf-infra

这将在 dist/packages/<my-terraform-project>/terraform/dev.tfplan 中创建一个计划文件。

plan 依赖于 assemble,因此它会生成您的模块引用的工件,例如 Lambda 包和生成的操作元数据,而不运行 lint、test 和 type-check 门控。

使用 init 目标初始化您的 Terraform 工作目录:

Terminal window
pnpm nx run tf-infra:init

规划后,您可以使用 apply 目标将基础设施部署到 AWS:

Terminal window
pnpm nx apply tf-infra

从您的 Terraform 配置中检索输出值:

Terminal window
pnpm nx output tf-infra

当您需要拆除基础设施时,使用 destroy 目标:

Terminal window
pnpm nx destroy tf-infra

要清理引导资源(用于状态存储的 S3 存储桶):

Terminal window
pnpm nx bootstrap-destroy tf-infra

这会在销毁状态存储桶之前清空它,并从 AWS SDK 凭证链解析区域,因此它可以在 CI 中无人值守运行。

有关 Terraform 的更多信息,请参阅 Terraform 文档AWS 提供程序文档