amazon-web-services - 如何使用 terraform 向 S3 存储桶添加生命周期规则?

标签 amazon-web-services amazon-s3 terraform

我正在使用 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.

最佳答案

让我们首先分解正在发生的事情以及我们如何克服这个问题。每次定义 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 接受 map 列表,该列表恰好与 Lifecycle_rule 的类型相同,因此它可以工作。理想情况下,Terraform 应该拥有自己的 resource阻止生命周期规则,但它没有。
编辑:当我们现在有动态块时,为什么还要有单独的资源块!呜呼

关于amazon-web-services - 如何使用 terraform 向 S3 存储桶添加生命周期规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55373524/

相关文章:

amazon-web-services - AWS Lambda NoClassDefFoundError

amazon-web-services - DynamoDB Multi-Tenancy IAM 策略(与其他用户共享文档)

ruby-on-rails - Ruby on Rails 4-回形针AWS Image URL错误吗?

swift - TransferUtility.uploadData 在 iOS 模拟器上工作得很好,但在实际设备 iOS13 上测试时不起作用

amazon-web-services - 如何创建 Athena 堆栈并使用 Glue 数据目录?

terraform - 如何将 IPv4 地址传递给 terraform 配置程序 local-exec

amazon-web-services - 由于权限问题,无法从 API Gateway 调用简单 Lambda

AWS 上的 Python 网络抓取脚本在 1.5 小时/获取 10,000 个 xml 后一直失败

apache-spark - 如何使用 flatMap() 在 PySpark 中并行列出 S3 对象?

amazon-web-services - terraform 将敏感数据存储在状态文件中