Aws lambda Terraform lambda源代码\u哈希更新,代码相同

Aws lambda Terraform lambda源代码\u哈希更新,代码相同,aws-lambda,terraform,Aws Lambda,Terraform,我已成功使用Terraform部署了AWS Lambda: resource "aws_lambda_function" "lambda" { filename = "dist/subscriber-lambda.zip" function_name = "test_get-code" role = <my_role> handler

我已成功使用Terraform部署了AWS Lambda:

resource "aws_lambda_function" "lambda" {
  filename                       = "dist/subscriber-lambda.zip"
  function_name                  = "test_get-code"
  role                           = <my_role>
  handler                        = "main.handler"
  timeout                        = 14
  reserved_concurrent_executions = 50
  memory_size                    = 128
  runtime                        = "python3.6"
  tags                           = <my map of tags>
  source_code_hash               = "${base64sha256(file("../modules/lambda/lambda-code/main.py"))}"
  kms_key_arn                    = <my_kms_arn>
  vpc_config {
    subnet_ids         = <my_list_of_private_subnets>
    security_group_ids = <my_list_of_security_groups>
  }
  environment {
    variables = {
      environment = "dev"
    }
  }
}

我想这是因为每次压缩Python源代码时,源代码都会发生变化。如果Python代码中没有更改,如何避免这种情况?如果我没有更改Python代码库,我的假设是否一致(我的意思是,为什么哈希会更改)?

这是因为您只对main.py进行哈希,但正在上载dist/subscriber-lambda.zip。Terraform将哈希与文件上载到lambda时计算的哈希进行比较。因为散列是在两个不同的文件上完成的,所以最终会得到不同的散列。尝试在正在上载的文件上运行哈希。我将添加我的答案,以与@ODYN Kon提供的答案形成对比

资源“aws_lambda_function”中的源代码散列字段不会与上载的zip文件的某些散列进行比较。相反,散列只是根据上次运行时Terraform保存的状态进行检查。因此,下次运行Terraform时,它会计算实际python文件的哈希值,以查看它是否已更改。如果已更改,则假定zip已更改,需要再次运行Lambda函数资源。源代码\u散列可以有您想要给它的任何值,也可以完全忽略它。您可以将其设置为某个任意字符串的常量,然后它将永远不会更改,除非您编辑地形配置

现在,问题是Terraform假设您更新了zip文件。假设zip归档文件中只有一个目录或一个文件,则可以使用Terraform数据源归档文件创建zip文件。我有一个例子,我不能使用它,因为我需要一个目录和一个文件(JS-world:source+node_modules/)。但以下是如何使用它:

data "archive_file" "lambdaCode" {
  type = "zip"
  source_file = "lambda_process_firewall_updates.js"
  output_path = "${var.lambda_zip}"
}
或者,如果将“source\u file”语句替换为
source\u dir=“node\u modules”

执行此操作后,可以引用zip存档文件的哈希代码以插入
资源“aws_lambda_函数”“lambda”{
块作为
“${data.archive_file.lambdaCode.output_base64sha256}”
用于字段source\u散列。然后,只要zip发生更改,lambda函数就会更新。而且,数据源存档文件知道,只要source\u文件发生更改,就必须重新生成zip

现在,我还没有深入到您的案例中的根本原因,但希望能提供一些帮助,以便找到更好的地方。您可以通过以下方式检查地形的保存状态:
tf state list
-其中列出了保存状态的项。您可以找到与lambda功能块匹配的项,然后执行
tf state show
。例如e、 就我正在做的一件事而言:

tf state show aws_lambda_函数。test lambda networking
给出大约30行输出,包括:

源代码散列=2fKX9v/duluQF0H6O9+iRnID2gokhfpXIXpxyeVBUM0=

您可以通过命令行命令比较散列。MacOS上的示例:
sha256sum my lambda.zip
,其中sha256sum是由
brew install coreutils
安装的


如前所述,如果zip中有多个元素没有被隔离到一个目录中,则使用archive_文件是不起作用的。我认为这种情况可能会经常发生,因此我希望Hashicorp的人能够扩展archive_文件以支持多个。我甚至查看了Go代码,但这是一个未雨绸缪的项目。我使用的一个变体是to将源代码散列设置为“${base64sha256(file(“my lambda.zip”))}”。但这仍然需要我运行tf两次。

正如其他人所说,您的zip应该用于文件名和散列中


我想指出的是,如果在lambda定义中使用错误的哈希函数,您也可能会遇到类似的重新创建问题。例如,filesha256(.zip)每次都会重新创建lambda。您必须使用filebase64sha256(“file.zip”)(terraform 0.11.12+)或base64sha256(file(“file.zip”))正如在源代码散列中提到的,这对我来说是有效的,并且在代码没有更改时也不会触发Lambda函数的更新

data "archive_file" "lambda_zip" {                                                                                                                                                                                   
  type        = "zip"                                                                                                                                                                                                
  source_dir  = "../dist/go"                                                                                                                                                                                         
  output_path = "../dist/lambda_package.zip"                                                                                                                                                                         
}                                                                                                                                                                                                                    


resource "aws_lambda_function" "aggregator_func" {                                                                                                                                                                   
  description      = "MyFunction"                                                                                                                                                                       
  function_name    = "my-func-${local.env}"                                                                                                                                                                  
  filename         = data.archive_file.lambda_zip.output_path                                                                                                                                                        
  runtime          = "go1.x"                                                                                                                                                                                         
  handler          = "main"                                                                                                                                                                                    
  source_code_hash = data.archive_file.lambda_zip.output_base64sha256                                                                                                                                                
  role             = aws_iam_role.function_role.arn                                                                                                                                                                  


  timeout = 120                                                                                                                                                                                                      
  publish = true                                                                                                                                                                                                     

  tags = {                                                                                                                                                                                                           
    environment = local.env                                                                                                                                                                                                                                                                                                                                                                    
  }                                                                                                                                                                                                                  
}                              

超级棒!我通过将main.py的哈希替换为所有dist/subscriber-lambda.zip的哈希来解决这个问题。此外,由于我已经通过terraform archive\u file函数创建了这个zip,我已经能够使用该归档文件源代码\u hash=“${data.archive\u file.lambda.output\u base64sha256}”的输出@Kon我对如何创建存储在S3中的文件的散列感到困惑?我使用
aws\u S3\u bucket\u对象
资源将jar文件上载到S3,在lambda资源中,我使用S3键指定S3文件位置。只需确保对正在上载的确切文件进行散列。在您的情况下,它将是jar文件。@Kon yeah奏效了!需要注意的是jar文件的情况。需要
filebase64sha256()
函数来创建散列值。你知道如何在CI/CD场景中解决这个问题吗?例如,我遇到了这个问题,因为当CI/CD启动时,它会构建并压缩我的代码。然后它运行terraform apply。源代码实际上没有改变,但zip的散列已经改变。我希望terraform知道它不需要重新部署在这个场景中。根据这个和我自己的测试,terraform存储上传的zip的散列,而不管您提供什么作为源代码散列
data "archive_file" "lambda_zip" {                                                                                                                                                                                   
  type        = "zip"                                                                                                                                                                                                
  source_dir  = "../dist/go"                                                                                                                                                                                         
  output_path = "../dist/lambda_package.zip"                                                                                                                                                                         
}                                                                                                                                                                                                                    


resource "aws_lambda_function" "aggregator_func" {                                                                                                                                                                   
  description      = "MyFunction"                                                                                                                                                                       
  function_name    = "my-func-${local.env}"                                                                                                                                                                  
  filename         = data.archive_file.lambda_zip.output_path                                                                                                                                                        
  runtime          = "go1.x"                                                                                                                                                                                         
  handler          = "main"                                                                                                                                                                                    
  source_code_hash = data.archive_file.lambda_zip.output_base64sha256                                                                                                                                                
  role             = aws_iam_role.function_role.arn                                                                                                                                                                  


  timeout = 120                                                                                                                                                                                                      
  publish = true                                                                                                                                                                                                     

  tags = {                                                                                                                                                                                                           
    environment = local.env                                                                                                                                                                                                                                                                                                                                                                    
  }                                                                                                                                                                                                                  
}