【问题标题】:How to deploy AWS resources across all regions via terraform?如何通过 terraform 跨区域部署 AWS 资源?
【发布时间】:2021-12-21 09:40:37
【问题描述】:

我需要在我的 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: ...

【问题讨论】:

  • 您可以为资源执行此操作,但根据路线图,这仍在为提供商开发中。如果可以的话,我可以写出相应的答案。
  • @MattSchuchard,是的,请为资源部分提供答案。

标签: terraform terraform-provider-aws


【解决方案1】:

providerresource 块都需要 for_each 元参数才能在单个块中迭代所有 AWS 区域。如果尝试将for_each 元参数与provider 块一起使用,则会显示错误消息:

提供者参数名称“for_each”保留供 Terraform 在未来版本中使用。

这是未来发展的路线图。

但是,可以使用资源块中的for_each 元参数来执行此操作。首先,您建议使用数据aws_regions 检索所有可用区域,以始终真正针对所有区域:

data "aws_regions" "this" {}

all_regionsfilters 参数可以向下选择所需区域。 list(string) 类型的导出资源属性 names 将存储所需的区域。

假设您按照问题中的描述配置提供程序及其别名,那么您将在资源块中使用此 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 区域中的资源。

【讨论】:

  • 需要provider = "aws.${each.value}" 吗?
  • @immutableT 是的,我正在检查 ids 导出的属性,看看是否应该在字符串插值中使用它,结果分散了我的注意力。
  • 提供者似乎不支持插值。
  • @immutableT 插值后我没有更新本地测试,所以我错过了这个问题。您可以在元参数中的 for 表达式中进行插值。再次更新答案。
  • @immutableT 对,我在本地测试中有each.value,但忘记将其移植到答案中。附带说明一下,虽然 each.key 在此处有效,但建议不要在迭代的 set 中使用该临时 lambda 范围迭代器变量。
猜你喜欢
  • 1970-01-01
  • 2020-02-27
  • 2019-08-05
  • 2021-09-13
  • 2016-11-06
  • 2021-06-09
  • 1970-01-01
  • 2015-05-18
  • 2021-06-26
相关资源
最近更新 更多