跨多个区域可变地创建 1 个或多个 AWS Buckets

Variably create 1 or more AWS Buckets across multiple regions

我正在寻求建议和帮助,以解决我在为单个环境中的多个环境和多个区域设置和管理存储桶和存储桶策略创建时遇到的问题。

我有 4 个 AWS 账户(dev、stg、prod1、prod2,它是 prod1 的副本)。在 prod1 中,我们有两个 kubernetes 集群 aws-us-prod1 和 aws-eu-prod1。这两个集群完全相互独立,只服务于那些地区的客户。

我在这两个不同的集群(aws-us-prod1 和 aws-eu-prod1)上有一个应用程序 运行,需要将内容写入 S3 存储桶。但是这两个集群共享一个AWS账户(prod1)。

我正在尝试编写一些 terraform 资源自动化来管理它,但我无法可变地控制将桶放入哪个区域。latest doc shows that there is a region attribute but it doesn’t work because of how the provider has been implemented with the aws provider region attribute

我想做的是这样的:

variable "buckets" {
    type = map(string) # e.g. buckets='{"a-us-prod1": "us-west-2", "a-eu-prod1":"eu-west-2"}'
}

resource "aws_s3_bucket" "my_buckets" {
    for_each = var.buckets

    bucket = each.key
    region = each.value
}

resource "aws_s3_bucket_policy" "my_buckets_policy" {
    for_each = aws_s3_bucket.my_buckets
    bucket = each.value.id
    policy = ...
}

我试过使用 multiple providers using aliases,但您不能根据要迭代的变量的值以编程方式使用提供程序。组织此项目和资源以实现此目标的正确方法是什么?

我遇到的这些问题与此有关: https://github.com/hashicorp/terraform/issues/3656 https://github.com/terraform-providers/terraform-provider-aws/issues/5999

从 2020 年 7 月 31 日起,region 属性刚刚从 terraform-provider-aws v3.0.0 中的 s3_bucket 中删除。在此之前,您可以将 region 设置为bucket,它会受到尊重,并且会在该选定区域中创建 bucket。然而,这不是任何其他资源的管理方式,它可能就在那里,因为 S3 是全局范围的,并且存储桶在 arn 中没有区域。所有其他服务都使用提供商本身的区域(应该如此)。

我建议为您可能想要支持的所有不同区域创建不同的提供程序,然后根据它们的区域拆分 var.buckets,然后为每个区域创建一个 resource "aws_s3_bucket" "this_region" { }

variable "buckets" {
    type = map(string) # e.g. buckets='{"a-us-prod1": "us-west-2", "a-eu-prod1":"eu-west-2"}'
}

provider "aws" {
    region = "eu-west-2"
    alias  = "eu-west-2"
}

locals {
    eu_west_2_buckets = [for name, region in var.buckets: name if region == "eu-west-2"]
}

resource "aws_s3_bucket" "eu_west_2_buckets" {
    count   = length(local.eu_west_2_buckets)
    bucket  = eu_west_2_buckets[count.index]
    provider = aws.eu-west-2
}

如果您只想推出与当前部署区域匹配的存储桶,您只需更改存储桶过滤逻辑即可:

variable "buckets" {
    type = map(string) # e.g. buckets='{"a-us-prod1": "us-west-2", "a-eu-prod1":"eu-west-2"}'
}

locals {
    buckets = [for name, region in var.buckets: name if region == data.aws_region.current.name]
}

data "aws_region" "current" { }

resource "aws_s3_bucket" "buckets" {
    count   = length(local.buckets)
    bucket  = buckets[count.index]
}