Terraform中带depends_on的archive_file在plan阶段仍校验source_dir报错
问题核心原因
Terraform的data资源(包括archive_file)会在plan阶段就执行验证和数据生成,而null_resource的local-exec provisioner仅在apply阶段运行。即便给data.archive_file添加depends_on,也只能控制apply阶段的执行顺序,无法阻止plan阶段的目录检查。在干净CI工作区中,plan阶段还未执行打包脚本,目标目录根本不存在,直接触发报错。
另外,尝试用resource "archive_file"失败的原因是:该资源的哈希类属性(如output_base64sha256)在plan阶段无法生成有效计算值,而你使用的lambda模块可能依赖这些值提前存在,导致流程卡壳。
有效解决办法
办法1:将打包逻辑移到Terraform执行前(推荐,CI环境最稳定)
在CI流水线中,先单独执行Python依赖安装和打包脚本,再运行terraform plan/apply。这样Terraform执行时,压缩包已提前生成,无需依赖内部provisioner。
示例Bitbucket Pipelines脚本:
script: - rm -rf .build/lambda-package - mkdir -p .build/lambda-package - pip3 install requests -t .build/lambda-package --quiet - cp src/handler.py .build/lambda-package/ - zip -r .build/lambda-package.zip .build/lambda-package/ - terraform init - terraform apply -auto-approve
对应Terraform代码直接引用预生成的压缩包路径:
module "lambda" { source = "terraform-aws-modules/lambda/aws" version = "~> 7.0" create_package = false local_existing_package = "${path.root}/.build/lambda-package.zip" # ... 其他Lambda配置 }
办法2:在null_resource内部完成打包,跳过archive_file数据资源
把压缩逻辑直接整合到build_lambda的local-exec中,无需单独的archive_file资源,直接用预定义的压缩包路径传给lambda模块。
修改后的Terraform代码:
resource "null_resource" "build_lambda" { triggers = { source_hash = local.source_hash } provisioner "local-exec" { interpreter = ["/bin/bash", "-euo", "pipefail", "-c"] command = <<-EOT rm -rf "${local.build_dir}" mkdir -p "${local.build_dir}" pip3 install requests -t "${local.build_dir}" --quiet cp "${var.source_dir}/handler.py" "${local.build_dir}/" # 直接在打包步骤后完成压缩 zip -r "${local.zip_path}" "${local.build_dir}/" date -u > "${local.build_dir}/.build_complete" EOT } } module "lambda" { source = "terraform-aws-modules/lambda/aws" version = "~> 7.0" create_package = false local_existing_package = local.zip_path # 确保lambda模块在打包完成后再执行 depends_on = [null_resource.build_lambda] # ... 其他Lambda配置 }
这种方式下,plan阶段仅需确认路径存在即可(lambda模块的local_existing_package在plan阶段不会强制检查文件存在),打包逻辑在apply阶段的provisioner中执行,依赖关系可保证执行顺序。
办法3:使用external数据源触发打包(较复杂,不推荐)
通过data "external"调用外部脚本完成打包,利用external数据源在apply阶段执行的特性,但需要严格处理脚本的JSON输入输出格式,实现成本高于前两种方案。
内容的提问来源于stack exchange,提问作者mon

