如何修复Terraform archive_file创建Lambda函数Zip包的重复失败问题?
解决Terraform部署Lambda时后续apply找不到ZIP文件的问题
问题根源
你当前的代码用random_id生成ZIP文件的存储目录,而random_id是持久化资源,一旦创建后值就固定。archive_file数据源仅在依赖资源变化或source_dir内容改变时才会重新生成ZIP。如果后续apply时,该固定路径下的ZIP文件被意外删除(比如被.gitignore忽略、本地清理),且此时source_dir和依赖的null_resource都未触发更新,Terraform会默认ZIP文件已存在,不会重新生成,最终导致aws_lambda_function因找不到文件报错。
解决方案
1. 用源码哈希替代random_id生成动态路径
移除random_id资源,改用源码目录的哈希值来触发ZIP更新和命名,确保源码变化时自动生成新的ZIP文件:
# 移除原有的random_id资源 # resource "random_id" "id" { # byte_length = 10 # } # 生成源码目录的全局哈希,覆盖所有文件变更 locals { lambda_src_hash = filesha256(join("\n", [for f in fileset("${path.module}/src", "**/*") : filemd5("${path.module}/src/${f}")])) }
2. 调整archive_file配置
修改archive_file的输出路径为基于源码哈希的动态路径,同时添加源码哈希作为触发条件,确保内容变化时强制重新生成ZIP:
data "archive_file" "python_lambda_package" { type = "zip" source_dir = "${path.module}/src" output_path = "${path.module}/lambda_${local.lambda_src_hash}.zip" depends_on = [null_resource.install_dependencies] # 源码目录内容变更时,强制重新打包 source_code_hash = local.lambda_src_hash }
3. 优化资源命名逻辑
用源码哈希替代random_id命名IAM角色和Lambda函数,确保资源随代码变化同步更新:
resource "aws_iam_role" "iam_for_lambda" { name = "LambdaFunction-${local.lambda_src_hash}" assume_role_policy = data.aws_iam_policy_document.assume_role.json } resource "aws_lambda_function" "custom_name" { function_name = "custom_name-${local.lambda_src_hash}" filename = data.archive_file.python_lambda_package.output_path source_code_hash = data.archive_file.python_lambda_package.output_base64sha256 role = aws_iam_role.iam_for_lambda.arn runtime = "python3.10" memory_size = 1024 handler = "function.handler" timeout = 600 tracing_config { mode = "Active" } }
4. 完善依赖安装触发条件
让null_resource不仅在requirements.txt变化时运行,也在源码文件变更时重新安装依赖:
resource "null_resource" "install_dependencies" { provisioner "local-exec" { command = "pip install -r ${path.module}/src/requirements.txt -t ${path.module}/src/ --upgrade" } triggers = { dependencies_versions = filemd5("${path.module}/src/requirements.txt") source_code_hash = local.lambda_src_hash # 源码变化时重新安装依赖 } }
额外建议
- 在
.gitignore中添加lambda_*.zip,避免将生成的ZIP文件提交到版本库 - 若不需要保留历史ZIP文件,可在
null_resource中添加清理逻辑:provisioner "local-exec" { command = "rm -f ${path.module}/lambda_*.zip" } - 清理旧资源时,使用
terraform destroy -target=module.my_module替代手动移除模块,操作更安全
内容的提问来源于stack exchange,提问作者Octav Chelaru
相关产品推荐
相关产品推荐

