首页 > 解决方案 > Terraform 未部署到多个帐户中

问题描述

我在将 terraform/terragrunt 部署到多个帐户时遇到问题。我想在我的“主”帐户中管理 DNS 和 KMS,并将其他所有内容部署到我的 dev/uat/prod 环境中。

我已经使用提供商配置了多个 AWS 账户。一个是通过 terragrunt 自动创建的,另一个是在我的 main.tf 文件中创建的。

我已经尝试了许多不同的方法来让它发挥作用。为这两个提供者设置别名,只为一个提供者设置别名,并从等式中完全删除 terragrunt。在每种情况下,terraform 都将应用于我的“主”帐户以获取所有资源。

下面是我的代码示例:

  backend = "s3"
#   generate = {
#       path = "backend.tf"
#       if_exists = "overwrite"
#   }
  config = {
    bucket                  = "arm-terraform-state"
    key                     = "${path_relative_to_include()}/terraform.tfstate"
    region                  = "us-west-2"
    dynamodb_table          = "arm-terraform-state-lock"
  }
  generate = {
    path = "backend.tf"
    if_exists = "overwrite_terragrunt"
  }
}
generate "provider" {
  path = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents = <<EOF
provider "aws" {
  alias                   = "main"
  region                  = "${local.aws_region}"
  profile                 = "${local.account}"
}
EOF
}
locals {
    region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
    account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl"))
    aws_region   = local.region_vars.locals.aws_region
    account = local.account_vars.locals.aws_profile
}

以上是我的 Terragrunt 代码。这是我的模块:

resource "aws_iam_role_policy" "logging_role_policy" {
  provider = aws.main
  name = format("aws-sftp-logging-policy-%s-%s",var.product_name,var.env)

  role= aws_iam_role.logging_role.id

  policy = data.aws_iam_policy_document.sftp_logging.json
}
############
# Route 53 #
############
resource "aws_route53_record" "sftp_record" {
  provider = aws.master
  zone_id = data.aws_route53_zone.facteus.zone_id
  name = format("%s-%s",var.product_name,var.env)
  type = "CNAME"
  ttl = "30"
  records = [aws_transfer_server.aws_transfer_service.endpoint]
}

标签: amazon-web-servicesterraformterragrunt

解决方案


您应该首先创建一个反映您所需帐户结构的目录结构。根据您的问题,听起来您可能想要这样的东西:

├── dev
│   ├── terragrunt.hcl
│   └── us-east-1
├── master
│   ├── _global
│   │   └── dns
│   ├── terragrunt.hcl
│   └── us-east-1
│       └── kms
├── prod
│   ├── terragrunt.hcl
│   └── us-east-1
└── uat
    ├── terragrunt.hcl
    └── us-east-1

这里的master账号有两个其他人没有的目录:

  1. _global/dns- 由于 AWS 中的 Route 53 是一个全局实体(不是区域性的),因此您不想将其嵌套在us-east-1. 它只存在于master帐户中,因为您声明要从 master 控制 DNS。(我也建议命名它route53而不是dns,但我离题了。)

  2. us-east-1/kms- 这包含 KMS 配置,也仅适用于master.

现在,在 中master/terragrunt.hcl,设置您的remote_state配置:

remote_state {
  backend = "s3"
  config = {
    encrypt        = true
    bucket         = "master-terraform-state" # Just for example - must be a globally unique
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
  }
}

或者,您还可以包含一个iam_role属性

iam_role = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"

请注意,这是可选的,因为您也可以使用主帐户的凭据简单地执行 Terragrunt,或者您可以使用--terragrunt-iam-roleCLI 选项,或者您可以设置TERRAGRUNT_IAM_ROLEenv var。在所有情况下,您都将使用对主帐户具有权限的角色执行 terragrunt。

现在,对于 dev/uat/prod 帐户,您可以使用类似的remote_state配置,为每个帐户替换不同的存储桶名称。然后,您可以使用适合每个账户的 IAM 角色,方法是在每个账户中定义它iam_roleterragrunt.hcl或者通过我提到的其他方法。

TL;DR 您不需要为此生成提供程序,也不需要在提供程序配置中命名配置文件。您只需为每个账户使用正确的 IAM 角色执行 terragrunt。Terragrunt 将在调用 Terraform 之前担任该角色。将提供程序配置放在 Terraform 模块中,关闭配置文件。


推荐阅读