Terraform创建AWS Lambda后更新source_code_hash及部署咨询
问题1 实现方案
完全不需要在CI/CD里跑terraform apply,也不需要手动维护source_code_hash,核心是把Lambda代码的生命周期从Terraform管理里剥离,直接通过AWS原生接口更新代码即可,具体操作:
- 先调整Terraform配置,避免后续执行基础设施变更时回滚Lambda代码。在
aws_lambda_function资源块里加生命周期忽略规则,让Terraform不再接管代码相关的属性变更:
resource "aws_lambda_function" "middleware" { // 原有配置全部保留,包括创建时需要的初始s3_bucket、s3_key、source_code_hash(用来首次创建函数时传初始占位包就行) function_name = var.function_name s3_bucket = var.s3_bucket s3_key = var.s3_bucket_key source_code_hash = var.source_code_hash runtime = "nodejs14.x" memory_size = 1024 timeout = 900 handler = "dist/src/lambda.handler" role = var.role environment { variables = { DATABASE_URL = "postgres://****" } } // 新增下面这段 lifecycle { ignore_changes = [ source_code_hash, s3_key, filename ] } }
这步是关键,很多人踩过坑:没加这个规则的话,下次你改Lambda内存、环境变量这类基础设施配置跑terraform apply,Terraform会发现当前Lambda的代码哈希和配置文件里写的旧值不一致,直接把代码回滚到初始版本。加完之后Terraform只会在首次创建Lambda时部署初始包,后续代码怎么变它都不会干预。
2. CI/CD流水线里不需要碰Terraform,代码构建打包完做两步就行:
- 把zip包上传到S3,推荐用带git提交哈希、构建号的key,比如
lambda/middleware/build-<commit-sha>.zip,方便回滚,也避免固定key覆盖带来的缓存问题;如果图省事儿用固定key,建议开S3版本控制。 - 调AWS CLI更新Lambda代码:
aws lambda update-function-code \ --function-name "你的Lambda函数名" \ --s3-bucket "你的S3桶名" \ --s3-key "上传后的包key"
执行完这个命令AWS会自动拉取新包部署,服务端自己会做哈希校验、版本切换,根本不需要你手动计算、传入source_code_hash。用AWS SDK、其他CD工具的AWS集成插件也是一样的逻辑,核心就是直接调用Lambda的UpdateFunctionCode接口,绕开Terraform。
问题2 方案合理性说明
你选的基础设施和应用部署分离的流程是非常标准的生产实践,完全合理,优势很明确:
- 风险彻底隔离:基础设施变更频率低,通常需要更严格的评审、校验流程,应用发布频率高、流程轻量。分离后应用发布流水线不需要访问Terraform状态,也不需要拥有全量基础设施的修改权限,只给它上传对应S3路径、更新指定Lambda代码的最小权限就行,从根上避免了你担心的误改其他资源的问题。
- 发布效率更高:应用发布不需要走
terraform plan、apply的长流程,也不会被Terraform状态锁、provider更新这类基础设施层面的问题阻塞,发布速度快很多。 - 职责边界清晰:基础设施配置和业务代码的管理权限拆分,运维/平台团队管基础资源,业务团队管代码发布,各自迭代互不干扰。
- 回滚成本更低:应用出问题要回滚,直接在流水线里调一次更新接口指回旧版本的S3包就行,不需要改Terraform配置、走基础设施变更流程。
唯一要注意的就是前面说的配置ignore_changes,避免Terraform后续意外回滚代码。
内容的提问来源于stack exchange,提问作者LP13
相关产品推荐
相关产品推荐

