Terraform用timestamp做null_resource触发器时强制重建资源如何解决?
问题根因
timestamp() 属于Terraform运行时函数,仅在apply阶段才会计算出具体值,plan阶段无法预知其结果,因此Terraform会默认判定triggers发生了变更,强制要求重建资源。你遇到的数据源值触发强制重建的问题,本质也是因为对应值在plan阶段被判定为未知,触发了资源替换逻辑。
解决方案
方案1:使用time_rotating资源(官方推荐)
HashiCorp官方的time provider提供的time_rotating资源专门用于按固定时间间隔触发资源变更,其值会在plan阶段完成计算,不会出现未知值强制重建的问题。
首先声明provider依赖:
terraform { required_providers { time = { source = "hashicorp/time" version = ">= 0.11.1" } } } provider "time" {}
创建每小时轮换的时间资源:
resource "time_rotating" "hourly" { rotation_hours = 1 }
修改null_resource的trigger配置:
resource "null_resource" "helm_login" { triggers = { hour = time_rotating.hourly.formatted("YYYYMMDDhh") } provisioner "local-exec" { command = <<-EOF az acr login -n ${var.helm_chart_acr_fqdn} -t -o tsv --query accessToken \ | helm registry login ${var.helm_chart_acr_fqdn} \ -u "00000000-0000-0000-0000-000000000000" \ --password-stdin EOF } }
方案2:使用外部数据源预计算时间戳
如果不想引入额外provider,可以用external数据源在plan阶段就计算出当前小时值,避免未知值问题:
data "external" "current_hour" { program = ["sh", "-c", "echo '{\"hour\": \"'$(date +%Y%m%d%H)'\"}'"] } resource "null_resource" "helm_login" { triggers = { hour = data.external.current_hour.result.hour } # 其余provisioner配置保持不变 }
通用优化方案(针对数据源触发重建问题)
对于从data数据源取值触发强制重建的场景,可以通过以下方式处理:
- 尽量避免给data数据源添加不必要的
depends_on配置,让Terraform可以正常在plan阶段计算其值 - 如果必须依赖其他资源,可拆分配置分步apply,先完成依赖资源的部署,再执行包含data数据源的配置部署
- 对于不需要随属性变更重建的资源,可添加
lifecycle { ignore_changes = [对应属性名] }配置,忽略该属性的变更检测
内容的提问来源于stack exchange,提问作者The Fool
相关产品推荐
相关产品推荐

