使用 Terraform/CloudFormation/Something 有效地部署 lambdas(只部署那些改变的)

Posted

技术标签:

【中文标题】使用 Terraform/CloudFormation/Something 有效地部署 lambdas(只部署那些改变的)【英文标题】:Deploying lambdas effectively (only deploy those that changed) with Terraform/CloudFormation/Something else 【发布时间】:2019-05-14 08:01:40 【问题描述】:

到目前为止,我一直在使用 CloudFormation 来部署我的 lambda。我发现这个过程非常缓慢且效率低下 - 例如。它可能需要几分钟,但如果它只是部署那个 1 功能应该只需要几秒钟?大多数功能都不会改变,但我相信 CloudFormation 不会区分并且无论如何都会部署所有内容。有没有办法可以更有效地做到这一点?比如检查发生了什么变化并只部署这些变化?

另一个好处是我可以有更少的版本?

【问题讨论】:

您是否尝试通过 Jenkins 等 CI 运行它并检查是否有任何提交? @BeshoyHanna,但通常 CI 是由新提交触发的,在我看来,这是不够的,因为新提交可能只会更改 1 个函数。或者 CI 可能同时部署基础设施和代码。有时只有基础设施更改(例如 terraform/CloudFormation)所以我不需要部署我的代码 是的,我想你是对的,但我是在暗示每个函数可能有单独的存储库? @BeshoyHanna,但这将意味着大量的回购:( @Jiew Meng 能否提供一些示例代码? 【参考方案1】:

您可以使用 aws_lambda_function 资源的 source_code_hash 让 Terraform 检查 Lambda 函数是否已更改。如果没有任何更改,则不会上传新版本,您的计划将显示无需更改。

这是example in the docs:

resource "aws_lambda_function" "test_lambda" 
  filename         = "lambda_function_payload.zip"
  function_name    = "lambda_function_name"
  role             = "$aws_iam_role.iam_for_lambda.arn"
  handler          = "exports.test"
  source_code_hash = "$base64sha256(file("lambda_function_payload.zip"))"
  runtime          = "nodejs8.10"

  environment 
    variables = 
      foo = "bar"
    
  

【讨论】:

我不确定我是否正确,但我注意到即使更改了源代码并且我做了terraform apply,新的源代码也不会被应用。好像 terraform 更新了上次更新时间和哈希但没有上传新的 zip? 可能值得编辑您的问题以显示您尝试过的内容以及您尝试让 Terraform 更新 Lambda 函数代码所遵循的步骤。查看 aws_lambda_function 资源的源代码,它从 AWS 获取函数包哈希,并独立检查与提供的 source_code_hash 相比,因此 Terraform 不可能忽略对包的更改而只是更新自己的状态文件。 如果使用版本化的 lambda 函数,则需要在 aws_lambda_function 资源上设置 publish = true。 terraform.io/docs/providers/aws/r/lambda_function.html#publish【参考方案2】:

我创建了this Terraform 模块来解决这个问题。即使设置 source_code_hash 也是不够的,因为在制作 zip 时,它们通常包含一些文件系统元数据。使用我的模块,哈希应该是稳定的(仅在源更改时才更改)。该模块特定于 Python,但哈希稳定性可以应用于任何运行时。

【讨论】:

【参考方案3】:

我在 gitlab 管道中使用 aws cli 在提交时部署和更新我的 lambda。

我压缩内容。将其上传到 S3 并使用 S3 上的新工件触发函数更新。

这比运行 Cloud Formation 模板快得多:

# Filename
FILENAME="$ARTIFACT_ID-$version-$BUILD_NUMBER.zip"
zip -r -D $FILENAME ./*
# Copy the bundle to s3
aws s3 cp $FILENAME "s3://$S3_BUCKET/$FILENAME"
# Trigger update of lambda function
aws lambda update-function-code --function-name $LAMBDA_FUNCTION_NAME --s3-bucket $S3_BUCKET --s3-key $FILENAME

希望对你有帮助。

【讨论】:

【参考方案4】:

试试https://serverless.com。轻松部署 lambda 函数,您还可以通过几行创建其他资源,例如 dynamodb 或 s3 存储桶。

1) 创建无服务器项目。

serverless create --template aws-nodejs --path my-service

2) 在 handler.js 文件中写入函数登录并部署。

serverless deploy 

3) 您可以在一项服务中创建多个功能。此外,您可以选择仅部署一项功能。

serverless deploy // for all the functions in one service
serverless deploy function -f functionName //deploy function with name 'functionName'

您也可以从终端查看日志,无服务器框架也支持插件,例如您可以在 typescript 中编写源代码,而 typescript 的无服务器插件将自行完成其余的工作。 我已经使用无服务器很长一段时间了,这是我找到的持续集成的最佳解决方案。值得一试。

【讨论】:

以上是关于使用 Terraform/CloudFormation/Something 有效地部署 lambdas(只部署那些改变的)的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)