【问题标题】:How to add lifecycle rules to an S3 bucket using terraform?如何使用 terraform 向 S3 存储桶添加生命周期规则?
【发布时间】:2019-08-17 19:16:20
【问题描述】:

我正在使用 Terraform 在 S3 中创建一个存储桶,我想向其中添加“文件夹”和生命周期规则。

我可以创建存储桶(使用“aws_s3_bucket”资源)。

我可以在同一个“aws_s3_bucket”资源中创建存储桶并定义我的生命周期规则,即。在创建时。

我可以使用“aws_s3_bucket_object”资源将“文件夹”添加到存储桶(我知道它们不是真正的文件夹,但它们呈现给客户端系统就好像它们是...... :-)),即.创建存储桶后。

一切顺利……

但我希望能够在创建存储桶后添加生命周期规则,但我收到一条错误消息,告诉我存储桶已存在。 (实际上我希望能够在需要时添加文件夹和相应的生命周期规则。)

现在,我可以将生命周期规则添加到 AWS GUI 中的现有存储桶,所以我知道这样做是合理的。

但是有没有办法用 Terraform 做到这一点?

我错过了什么吗?

resource "aws_s3_bucket" "bucket" {
    bucket      = "${replace(var.tags["Name"],"/_/","-")}"
    region      = "${var.aws_region}"

    #tags                = "${merge(var.tags, map("Name", "${var.tags["Name"]}"))}"
    tags                = "${merge(var.tags, map("Name", "${replace(var.tags["Name"],"/_/","-")}"))}"
}


resource "aws_s3_bucket" "bucket_quarterly" {
    bucket      = "${aws_s3_bucket.bucket.id}"
    #region      = "${var.aws_region}"

    lifecycle_rule {
        id      = "quarterly_retention"
        prefix  = "quarterly/"
        enabled = true

        expiration {
            days = 92
        }
    }

}


resource "aws_s3_bucket" "bucket_permanent" {
    bucket      = "${aws_s3_bucket.bucket.id}"
    #region      = "${var.aws_region}"

    lifecycle_rule {
        id      = "permanent_retention"
        enabled = true
        prefix  = "permanent/"

        transition {
            days            = 1
            storage_class   = "GLACIER"
        }
    }

}


resource "aws_s3_bucket_object" "quarterly" {
    bucket  = "${aws_s3_bucket.bucket.id}"
    #bucket  = "${var.bucket_id}"
    acl     = "private"
    key     = "quarterly"
    source  = "/dev/null"
}


resource "aws_s3_bucket_object" "permanent" {
    bucket  = "${aws_s3_bucket.bucket.id}"
    #bucket  = "${var.bucket_id}"
    acl     = "private"
    key     = "permanent"
    source  = "/dev/null"
}

我希望有一个包含 2 个生命周期规则的存储桶,但我收到以下错误:

错误:应用计划时出错:

2 error(s) occurred:

* module.s3.aws_s3_bucket.bucket_quarterly: 1 error(s) occurred:

* aws_s3_bucket.bucket_quarterly: Error creating S3 bucket: BucketAlreadyOwnedByYou: Your previous request to create the named bucket succeeded and you already own it.
    status code: 409, request id: EFE9C62B25341478, host id: hcsCNracNrpTJZ4QdU0AV2wNm/FqhYSEY4KieQ+zSHNsj6AUR69XvPF+0BiW4ZOpfgIoqwFoXkI=
* module.s3.aws_s3_bucket.bucket_permanent: 1 error(s) occurred:

* aws_s3_bucket.bucket_permanent: Error creating S3 bucket: BucketAlreadyOwnedByYou: Your previous request to create the named bucket succeeded and you already own it.
    status code: 409, request id: 7DE1B1A36138A614, host id: 8jB6l7d6Hc6CZFgQSLQRMJg4wtvnrSL6Yp5R4RScq+GtuMW+6rkN39bcTUwQhzxeI7jRStgLXSc=

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

【问题讨论】:

标签: amazon-web-services amazon-s3 terraform


【解决方案1】:

让我们首先分解正在发生的事情以及我们如何克服这个问题。每次定义 resource "aws_s3_bucket" 时,terraform 都会尝试使用指定的参数创建存储桶。如果您想将生命周期策略附加到存储桶,请在您定义存储桶的地方进行,例如:

resource "aws_s3_bucket" "quarterly" {
    bucket  = "quarterly_bucket_name"
    #bucket  = "${var.bucket_id}"
    acl     = "private"
    lifecycle_rule {
        id      = "quarterly_retention"
        prefix  = "folder/"
        enabled = true

        expiration {
            days = 92
        }
    }
}

resource "aws_s3_bucket" "permanent" {
    bucket  = "perm_bucket_name"
    acl     = "private"
    lifecycle_rule {
        id      = "permanent_retention"
        enabled = true
        prefix  = "permanent/"

        transition {
            days            = 1
            storage_class   = "GLACIER"
        }
    }
}

一个桶可以有多个lifecycle_rule 块。 如果要将生命周期规则定义为外部块,可以这样:

// example of what the variable would look like:
variable "lifecycle_rules" {
  type = "list"
  default = []
}

// example of what the assignment would look like:
lifecycle_rules = [{
  id = "cleanup"
  prefix = ""
  enabled = true
  expiration = [{
    days = 1
  }]
}, {...}, {...} etc...]

// example what the usage would look like
resource "aws_s3_bucket" "quarterly" {
    bucket  = "quarterly_bucket_name"
    #bucket  = "${var.bucket_id}"
    acl     = "private"
    source  = "/dev/null"
    lifecycle_rule = [ "${var.lifecycle_rules}" ]
}

注意:上面的实现外部生命周期策略并不是最好的方法,而是唯一的方法。您几乎可以欺骗 terraform 接受地图列表,该列表恰好与生命周期规则的类型相同,因此它可以工作。理想情况下,Terraform 应该有自己的 resource 块用于生命周期规则,但它没有。

编辑:当我们现在有动态块时,为什么还要有单独的资源块!呜呜呜

【讨论】:

  • > 这里不需要“lifecycle_rule”类型的块。 aws_s3_bucket_object 似乎没有 lifecycle_rule
  • 感谢您指出这一点。我现在已更新资源名称以使其正确。
  • @Moe,dynamic blocks 是什么意思?
  • google "dynamic blocks terraform" 第一个结果详细解释了它:github.com/hashicorp/terraform-guides/tree/master/…
【解决方案2】:

据我所知,您不能单独制定生命周期策略。

有人提出了要创建的资源的 PR 以允许您这样做,但看起来它仍然是开放的:https://github.com/terraform-providers/terraform-provider-aws/issues/6188


至于您的错误,我相信您收到错误的原因是:

  • resource "aws_s3_bucket" "bucket"

创建具有特定名称的存储桶。

  • resource "aws_s3_bucket" "bucket_quarterly"

引用bucket = "${aws_s3_bucket.bucket.id}",因此尝试创建与前一个资源同名的存储桶(由于名称是唯一的,因此无法完成)。

  • resource "aws_s3_bucket" "bucket_permanent"

同样,此资源引用bucket = "${aws_s3_bucket.bucket.id}",因此尝试创建与第一个资源同名的存储桶(由于名称是唯一的,因此无法完成)。


您提到了I expect to have a bucket with 2 lifecycle rules,但在上面的代码中,您创建了 3 个单独的 s3 存储桶(一个没有生命周期,2 个有生命周期)和两个对象(文件夹)被放入没有生命周期策略的 s3 存储桶中.

【讨论】:

    【解决方案3】:

    感谢您提供的信息(我喜欢列表将规则与资源分开的想法)。

    问题是我不明白您可以在资源中定义生命周期规则并随后更改它们,所以我试图弄清楚如何单独定义它们......

    所需要做的就是在资源中指定它们并应用 terraform,然后您可以对其进行编辑并添加/修改/删除生命周期规则项,然后再次应用 terraform 以应用更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-07
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      • 2021-04-18
      • 2016-06-23
      • 2022-11-29
      • 1970-01-01
      相关资源
      最近更新 更多