Terraform的新手,所以也许它不应该以这种方式工作。我想使用aws_s3_bucket_object将包上传到存储桶 - 这是应用部署的一部分。我将改变每个部署的包,我想保留旧版本。
resource "aws_s3_bucket_object" "object" {
bucket = "mybucket-app-versions"
key = "version01.zip"
source = "version01.zip"
}
但是在为将来的部署运行之后,我将要上传版本02然后版本03等.Terraform 用新的预期行为替换旧的zip。
但是有没有办法让terraform不破坏旧版本?这是一个支持的用例,还是这不是我应该如何使用terraform?如果terraform没有官方支持做我喜欢做的事情,我不想用丑陋的黑客强迫这个。
我当然可以通过脚本调用S3 api,但如果将此定义与此应用程序的其余terraform定义一起使用会很棒。
答案 0 :(得分: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>"
}
}
答案 1 :(得分:1)
使用Terraform进行应用程序部署时,建议的方法是将构建步骤与部署步骤分开,并仅将Terraform用于后者。
构建步骤的责任 - 使用单独的工具(取决于部署方法)实现 - 是生成一些工件(存档,docker容器,虚拟机映像等),发布它某处,然后将其位置或标识符传递给Terraform进行部署。
构建和部署之间的这种分离允许更复杂的情况,例如,如果新版本存在问题,则回滚到较旧的工件(无需重建)。
在简单的场景中,可以使用Input Variables将工件位置传递给Terraform。例如,在构建过程将zip文件写入S3的情况下,您可以定义如下变量:
variable "archive_name" {
}
然后可以使用${var.archive_name}
插值语法将其传递给任何需要它的资源。要部署特定工件,请使用-var
在命令行上传递其名称:
$ terraform apply -var="archive_name=version01.zip"
有些组织喜欢记录当前&#34;某种数据存储中每个应用程序的版本,例如HashiCorp Consul,并使用data source读取它。这种方法可以更容易在自动构建管道中进行编排,因为它允许使用这个单独的数据存储来间接地在构建和部署步骤之间传递存档名称,而无需向Terraform本身传递任何异常参数。