如何通过terraform在所有区域部署AWS资源?

3
我需要在我的AWS组织中部署AWS GuardDuty,覆盖所有账户和区域。 我的第一步是将GuardDuty的管理委托给一个指定的帐户。由于GuardDuty是区域资源,我需要在所有区域执行这样的委派。请注意,我们在几乎所有的AWS区域运营。
以下是完成此任务的暴力方法:
provider "aws" {
  region  = "us-east-1"
  alias   = "us-east-1"
}
provider "aws" {
  region  = "us-east-2"
  alias   = "us-east-2"
}
# Do the same for the remaining regions

resource "aws_guardduty_organization_admin_account" "us-east-1" {
   provider = aws.us-east-1
   admin_account_id = "123456789..."
}
resource "aws_guardduty_organization_admin_account" "us-east-2" {
 provider = aws.us-east-2
 admin_account_id = "123456789..."
}

# Do the same for the remaining regions

这个方法可行,但有几个缺点:
  • 大量重复
  • 我需要记住在添加新区域时更新此代码
问题:有更好的方法吗? 这里有一个旧的讨论帖子: https://github.com/hashicorp/terraform/issues/451 然而,当时似乎没有好的选择,所以我想看看现在是否有更好的选择。
理想情况下,我想利用data "aws_regions" "all" {}来循环现有区域并动态创建委托资源和提供程序。
我尝试了@Matt Schuchard建议的方法:
给定这个资源:
resource "aws_guardduty_organization_admin_account" "us-east-1" {
  # interpolate in for expression here since not allowed in provider argument
  for_each = toset([for region in data.aws_regions.this.names : "aws.${region}"])

  provider         = each.value
  admin_account_id = "123456789..."
}


Terraform 1.0.10会产生以下错误:
Error: Failed to query available provider packages
Could not retrieve the list of available versions for provider hashicorp/each: ...

你可以这样做来获取资源,但根据路线图,这项服务提供者仍在开发中。如果您同意,我可以编写相应的答案。 - Matt Schuchard
@MattSchuchard,是的,请提供有关资源部分的答案。 - immutableT
1个回答

3
您需要在providerresource块中均使用for_each元参数来迭代单个块中的所有AWS区域。如果尝试在provider块中使用for_each元参数,则会显示以下错误消息:

提供程序参数名称"for_each"已被Terraform保留用于将来的版本。

这是未来开发计划中的内容。
然而,您可以使用资源块中的for_each元参数来完成此操作。首先,建议使用数据aws_regions检索所有可用区域以始终针对所有区域。
data "aws_regions" "this" {}

在这里,all_regionsfilters参数可以筛选所需的区域。导出的资源属性nameslist(string)类型,将存储所需的区域。

假设您按照问题描述配置提供程序及其别名,则可以在资源块中使用此list

resource "aws_guardduty_organization_admin_account" "us-east-1" {
  # interpolate in for expression here since not allowed in provider argument
  for_each = toset([for region in data.aws_regions.this.names : "aws.${region}"])

  provider         = each.value
  admin_account_id = "123456789..."
}

这将管理所有所需的 AWS 区域中的资源。


1
需要这样写吗:provider = "aws.${each.value}" - immutableT
@immutableT 是的,我正在检查导出属性中的 ids,看看是否应该在字符串插值中使用它,结果分散了我的注意力。 - Matt Schuchard
1
看起来提供者并不支持插值。 - immutableT
1
@immutableT 对的,我在本地测试中使用了 each.value,但忘记将其移植到答案中。另外,虽然 each.key 在这里是有效的,但不建议在迭代的 set 中使用该临时 lambda 作用域迭代器变量。 - Matt Schuchard
2
这绝对行不通。@immutableT,你解决了吗? - Azy Sır
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接