跨多个区域可变地创建 1 个或多个 AWS 存储桶

Posted

技术标签:

【中文标题】跨多个区域可变地创建 1 个或多个 AWS 存储桶【英文标题】:Variably create 1 or more AWS Buckets across multiple regions 【发布时间】:2020-11-25 17:51:19 【问题描述】:

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

我有 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 表明有一个 region attribute 但它没有'不起作用,因为提供程序是如何使用 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

【问题讨论】:

我想同时对两个区域应用更改是否是个好主意。如果你要分开这些(也许你的目录结构会变成account/region/cluster 或类似的东西),那么它会变得更简单,并且还能最小化爆炸半径。 【参考方案1】:

region 属性刚刚从 2020 年 7 月 31 日起从 terraform-provider-aws v3.0.0 中的 s3_bucket 中删除。在此之前,您可以为存储桶设置 region,它会受到尊重并且存储桶将在该选定区域中创建。但是,这不是任何其他资源的管理方式,它可能只是在那里,因为 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]

【讨论】:

如果我想独立运行这些基础设施更改,这种方法不允许我这样做。例如,如果我希望能够独立于eu-prod1 部署到us-prod1,我只需要规划和应用与相应区域相关的资源。那么我该如何处理呢? @Jonathan 这是一个根本不同的要求,你的问题根本没有提到这个要求。但是您可以通过更改 lambdas 的过滤器逻辑来实现这一点,并将其添加到答案中。 @luk2303 非常感谢!这就是我一直在寻找的。太好了!

以上是关于跨多个区域可变地创建 1 个或多个 AWS 存储桶的主要内容,如果未能解决你的问题,请参考以下文章

跨多个AWS地理区域的Mongodb副本

多个存储桶的 AWS IAM 策略

Terraform - 同一个存储桶上的多个 aws_s3_bucket_notification 触发器

S3 跨区域复制

aws 中的多个 s3 存储桶放大

如何将驻留在账户 A 中的 s3 存储桶的访问权限授予来自多个 aws 账户的不同 iam 用户?