【问题标题】:Terraform Replacing Bucket Object Instead of VersioningTerraform 替换存储桶对象而不是版本控制
【发布时间】:2019-12-08 06:30:19
【问题描述】:

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

我尝试在 terraform 配置中向 s3 存储桶添加版本控制,并将 api-version 移动到变量字符串。

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 发生更改,则可以更改回旧版本。

【问题讨论】:

    标签: amazon-web-services terraform


    【解决方案1】:

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

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

    现在 AWS Lambda 支持环境变量,不再推荐该模式。相反,部署工件应该由 Terraform 之外的一些单独的构建过程创建,并记录在 Terraform 可以发现它们的地方。例如,您可以使用 SSM Parameter Store 记录您当前所需的版本,然后让 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 运行部署它。
    • 要在不部署新函数版本的情况下更改基础架构的其他方面,只需在不更改 SSM 参数的情况下运行 Terraform,Terraform 将保持 Lambda 函数不变。
    • 如果您发现新版本存在缺陷,您可以将旧工件的位置写入 SSM 参数并运行 Terraform 以部署旧版本。

    Terraform 指南Serverless Applications with AWS Lambda and API Gateway 中对这种方法进行了更完整的描述,该指南使用 Lambda Web 应用程序作为示例,但也可以应用于许多其他 AWS Lambda 用例。使用 SSM 只是一个例子; Terraform 可以使用 data source 检索的任何数据都可以用作中介,以将构建和部署步骤彼此分离。

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

    【讨论】:

    • 你好,这非常有用,谢谢分享,我有一个关于 Glue 的问题,因为它需要从 S3 存储桶中读取脚本,我正在考虑使用 Terraform 将脚本部署到存储桶中将它指向胶水,但在阅读了您关于 Lambda 的答案后,我想知道是否应该考虑在 Terraform 之外构建/部署胶水二进制文件?有什么建议?谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-01
    • 2019-12-21
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    相关资源
    最近更新 更多