Amazon web services Terraform替换Bucket对象而不是版本控制

Amazon web services Terraform替换Bucket对象而不是版本控制,amazon-web-services,terraform,Amazon Web Services,Terraform,我正在设置一些地形来管理lambda和s3存储桶,并对s3的内容进行版本控制。创建基础架构的第一个版本很好。发布第二个版本时,terraform将替换zip文件,而不是创建新版本 我尝试在terraform配置中将版本控制添加到s3 bucket中,并将api版本移动到变量字符串中 data "archive_file" "lambda_zip" { type = "zip" source_file = "main.js" output_path = "main.zip

我正在设置一些地形来管理lambda和s3存储桶,并对s3的内容进行版本控制。创建基础架构的第一个版本很好。发布第二个版本时,terraform将替换zip文件,而不是创建新版本

我尝试在terraform配置中将版本控制添加到s3 bucket中,并将api版本移动到变量字符串中

data "archive_file" "lambda_zip" {
  type        = "zip"
  source_file = "main.js"
  output_path = "main.zip"
}

resource "aws_s3_bucket" "lambda_bucket" {
  bucket = "s3-bucket-for-tft-project"
  versioning {
    enabled = true
  }
}
resource "aws_s3_bucket_object" "lambda_zip_file" {
  bucket = "${aws_s3_bucket.lambda_bucket.bucket}"
  key    = "v${var.api-version}-${data.archive_file.lambda_zip.output_path}"
  source = "${data.archive_file.lambda_zip.output_path}"
}

resource "aws_lambda_function" "lambda_function" {
  s3_bucket         = "${aws_s3_bucket.lambda_bucket.bucket}"
  s3_key            = "${aws_s3_bucket_object.lambda_zip_file.key}"
  function_name     = "lambda_test_with_s3_version"
  role              = "${aws_iam_role.lambda_exec.arn}"
  handler           = "main.handler"
  runtime           = "nodejs8.10"
}

我希望输出是另一个zip文件,但lambda现在指向新版本,如果
var.api-version
发生更改,则能够更改回旧版本。

Terraform不是为创建这种“工件”对象而设计的,在这种对象中,每个新版本都应该与之前的版本分开

在AWS Lambda早期,将
data.archive_文件
数据源添加到Terraform中,当时将值从Terraform传递到Lambda函数的唯一方法是检索预期的zip工件,修改它以包括包含这些设置的附加文件,然后将其写入Lambda

现在AWS Lambda支持环境变量,不再推荐这种模式。相反,部署工件应该由Terraform之外的一些单独的构建过程创建,并记录在Terraform可以发现它们的地方。例如,您可以使用SSM参数存储记录当前所需的版本,然后让Terraform读取该版本以决定检索哪个工件:

data "aws_ssm_parameter" "lambda_artifact" {
  name = "lambda_artifact"
}

locals {
  # Let's assume that this SSM parameter contains a JSON
  # string describing which artifact to use, like this
  # {
  #   "bucket": "s3-bucket-for-tft-project",
  #   "key": "v2.0.0/example.zip"
  # }
  lambda_artifact = jsondecode(data.aws_ssm_parameter.lambda_artifact)
}

resource "aws_lambda_function" "lambda_function" {
  s3_bucket         = local.lambda_artifact.bucket
  s3_key            = local.lambda_artifact.key
  function_name     = "lambda_test_with_s3_version"
  role              = aws_iam_role.lambda_exec.arn
  handler           = "main.handler"
  runtime           = "nodejs8.10"
}
这种构建/部署分离允许执行三种不同的操作,而在Terraform中执行所有操作只允许执行一种操作:

  • 要发布新版本,您可以运行构建过程(可能在CI系统中),让它将生成的工件推送到S3,并将其记录为SSM参数中的最新版本,然后触发Terraform运行以部署它
  • 要在不部署新功能版本的情况下更改基础设施的其他方面,只需运行Terraform而不更改SSM参数,Terraform将保持Lambda功能不变
  • 如果发现新版本有缺陷,可以将旧工件的位置写入SSM参数,并运行Terraform来部署以前的版本
Terraform指南中对此方法有更完整的描述,该指南以Lambda web应用程序为例,但也可以应用于许多其他AWS Lambda用例。使用SSM只是一个例子;Terraform可以使用检索到的任何数据都可以用作中介,将构建和部署步骤彼此分离


这一总体思路可以应用于各种代码构建工件以及Lambda zip文件。例如:使用HashiCorp Packer创建的自定义AMI,使用
Docker build
创建的Docker图像。将构建过程、版本选择机制和部署过程分离提供了一定程度的工作流灵活性,可以支持愉快路径和事件期间采取的任何异常路径。

hi这非常有用,感谢分享,我有一个关于Glue的问题,因为它需要从S3存储桶读取脚本,我正想用TrRAFrm把脚本部署到桶中,并把它指向胶水,但是在阅读了Lambda的答案之后,我想知道我是否应该考虑在Terraform之外构建/部署胶二进制文件?有什么建议吗?谢谢