0

terraform 的新手,所以也许它不应该以这种方式工作。我想使用 aws_s3_bucket_object 将包上传到存储桶 - 这是应用程序部署的一部分。我将为每次部署更改包,我想保留旧版本。

resource "aws_s3_bucket_object" "object" {
    bucket = "mybucket-app-versions"
    key    = "version01.zip"
    source = "version01.zip"
}

但是在为将来的部署运行此程序后,我将要上传 version02,然后是 version03 等。Terraform用新的预期行为替换了旧的 zip。

但是有没有办法让 terraform 不破坏旧版本?这是这里受支持的用例,还是我不应该使用 terraform?如果 terraform 没有官方支持做我在这里尝试做的事情,我不想用丑陋的黑客来强迫它。

我当然可以只通过脚本调用 S3 api,但是如果用这个应用程序的 terraform 定义的其余部分来定义它会很棒。

4

2 回答 2

1

目前,您告诉 terraform 管理一个aws_s3_bucket_object文件,然后 terraform 负责其整个生命周期,这意味着如果 terraform 看到文件有任何更改,它也会替换该文件。

您可能正在寻找的是null_resource。您可以使用它来运行local-exec配置程序,以通过脚本上传您需要的文件。这样,旧文件不会被删除,因为它不是由 terraform 直接管理的。那时您仍将通过脚本调用 API,但上传到 s3 的整个过程仍将包含在您的terraform apply步骤中。

这里有一个大纲null_resource

resource "null_resource" "upload_to_s3" {
  depends_on = ["<any resource that should already be created before upload>"]
  ...

  triggers = ["<A resource change that must have happened so terraform starts the upload>"]

  provisioner "local-exec" {
    command = "<command to upload local package to s3>"
  }
}
于 2017-11-16T13:09:40.027 回答
1

使用 Terraform 进行应用程序部署时,推荐的方法是将构建步骤与部署步骤分开,仅将 Terraform 用于后者。

构建步骤(根据部署方法使用单独的工具实现)的职责是生成一些工件(存档、docker 容器、虚拟机映像等),将其发布到某个地方,然后然后将其位置或标识符传递给 Terraform 进行部署。

构建和部署之间的这种分离允许更复杂的情况,例如,如果新版本出现问题,则回滚到较旧的工件(而不重建它)。

在简单的场景中,可以使用Input Variables将工件位置传递给 Terraform 。例如,在构建过程将 zip 文件写入 S3 的情况下,您可以定义如下变量:

variable "archive_name" {
}

然后可以使用${var.archive_name}插值语法将其传递给任何需要它的资源。要部署特定工件,请使用以下命令在命令行上传递其名称-var

$ terraform apply -var="archive_name=version01.zip"

一些组织更喜欢在某种数据存储(例如HashiCorp Consul )中记录每个应用程序的“当前”版本,并使用数据源读取它。这种方法可以更容易地在自动构建管道中进行编排,因为它允许使用这个单独的数据存储在构建和部署步骤之间间接传递存档名称,而无需将任何不寻常的参数传递给 Terraform 本身。

于 2017-11-17T01:58:05.973 回答