You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform创建Azure主机名绑定失败:依赖配置无误却报错

问题:Azure App Service自定义域名绑定首次部署失败,第二次成功

问题场景

我有两个Terraform模块,一个用于创建Azure App Service,另一个为该App Service创建主机名绑定。

主模块main.tf代码

# Inside main.tf

# App Service

module "app_service" {
  source = "./AppService"
  resource_group_name = azurerm_resource_group.rg_0.name
  resource_group_location = azurerm_resource_group.rg_0.location
}

# Custom Domain

module "custom_domain" {
  source = "./CustomDomain"
  base_domain = var.domain_name
  sub_domain = azurerm_resource_group.rg_0.name
  web_app = module.app_service.web_app
}

CustomDomain模块代码

variable "base_domain" { }
variable "sub_domain" { }
variable "web_app" { }

data "azurerm_dns_zone" "dns-zone" {
  name                = var.base_domain
}

resource "azurerm_dns_txt_record" "domain-verification" {
  name                = "asuid.${var.sub_domain}"
  zone_name           = data.azurerm_dns_zone.dns-zone.name
  resource_group_name = data.azurerm_dns_zone.dns-zone.resource_group_name
  ttl                 = 3600

  record {
    value = var.web_app.custom_domain_verification_id
  }
}

resource "azurerm_dns_cname_record" "cname-record" {
  name                = var.sub_domain
  zone_name           = data.azurerm_dns_zone.dns-zone.name
  resource_group_name = data.azurerm_dns_zone.dns-zone.resource_group_name
  ttl                 = 3600
  record              = var.web_app.default_hostname

  depends_on = [azurerm_dns_txt_record.domain-verification]
}

resource "azurerm_app_service_custom_hostname_binding" "hostname-binding" {
  hostname            = "${var.sub_domain}.${var.base_domain}"
  app_service_name    = var.web_app.name
  resource_group_name = var.web_app.resource_group_name

  depends_on = [azurerm_dns_cname_record.cname-record]
}

部署错误信息

module.custom_domain.azurerm_dns_txt_record.domain-verification: Creating...
module.custom_domain.azurerm_dns_txt_record.domain-verification:
Creation complete after 1s [id=/subscriptions/7c34cc50-2353-4be0-bd25-d43ce1e7856e/resourceGroups/simsemsdevopsresources/providers/Microsoft.Network/dnsZones/dummy.net/TXT/asuid.tftest4-env8]
module.custom_domain.azurerm_dns_cname_record.cname-record: Creating...
module.custom_domain.azurerm_dns_cname_record.cname-record: Creation complete after 1s [id=/subscriptions/7c34cc50-2353-4be0-bd25-d43ce1e7856e/resourceGroups/simsemsdevopsresources/providers/Microsoft.Network/dnsZones/dummy.net/CNAME/tftest4-env8]
module.custom_domain.azurerm_app_service_custom_hostname_binding.hostname-binding: Creating...
╷
│ Error: creating/updating Custom Hostname Binding "tftest4-env8.dummy.net" 
(App Service "tftest4-env8" / Resource Group "tftest4-env8"): 
web.AppsClient#CreateOrUpdateHostNameBinding: Failure responding to request:
 StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 
Code="BadRequest" Message="A TXT record pointing from asuid.tftest4-env8.dummy.net to 
05334922dcaf46e4cd40398f25d5c6e96a9c1e8833b716b140eaeb06b9f838aa was not found."

我设置的依赖关系看似正确:azurerm_app_service_custom_hostname_binding显式依赖azurerm_dns_cname_record,后者又依赖azurerm_dns_txt_record。azurerm_linux_web_app从AppService模块输出后传入CustomDomain模块,供TXT记录使用custom_domain_verification_id。Terraform输出和Azure门户都显示TXT记录已创建成功,但首次部署失败,第二次执行部署计划则成功。

原因分析

这是DNS记录的全球传播延迟导致的问题:

  • Terraform仅确认Azure DNS服务端已创建TXT记录,但该记录还未完成全球DNS节点的同步传播。
  • Azure验证自定义域名绑定时,会从全球DNS节点查询TXT记录,此时新创建的记录可能还未同步到所有节点,导致验证失败。
  • 第二次部署时,间隔了足够的时间,DNS记录已完成全球传播,Azure能查询到TXT记录,验证通过。

另外,当前的depends_on仅保证Terraform资源创建的顺序,无法等待DNS记录的全球传播完成。

解决方案

可以通过以下两种方式解决:

  1. 添加显式延迟:在azurerm_app_service_custom_hostname_binding资源前添加time_sleep资源,等待DNS记录传播完成:
resource "time_sleep" "wait_for_dns_propagation" {
  create_duration = "2m" # 根据实际情况调整,一般1-5分钟足够

  depends_on = [azurerm_dns_txt_record.domain-verification]
}

resource "azurerm_app_service_custom_hostname_binding" "hostname-binding" {
  hostname            = "${var.sub_domain}.${var.base_domain}"
  app_service_name    = var.web_app.name
  resource_group_name = var.web_app.resource_group_name

  depends_on = [time_sleep.wait_for_dns_propagation]
}
  1. 使用DNS验证数据源:利用Terraform的dns_txt_record_set数据源,主动查询TXT记录直到存在,替代固定延迟:
data "dns_txt_record_set" "verify_asuid" {
  host = "asuid.${var.sub_domain}.${var.base_domain}"

  depends_on = [azurerm_dns_txt_record.domain-verification]

  # 轮询直到记录存在,最多等待10分钟,每次间隔30秒
  lifecycle {
    postcondition {
      condition     = length(self.records) > 0 && contains(self.records, var.web_app.custom_domain_verification_id)
      error_message = "ASUID TXT record not found or does not match verification ID."
    }
  }
}

resource "azurerm_app_service_custom_hostname_binding" "hostname-binding" {
  hostname            = "${var.sub_domain}.${var.base_domain}"
  app_service_name    = var.web_app.name
  resource_group_name = var.web_app.resource_group_name

  depends_on = [data.dns_txt_record_set.verify_asuid]
}

第二种方式更可靠,因为它会主动验证记录是否可查询,而不是依赖固定时间等待。


内容的提问来源于stack exchange,提问作者Neutrino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 13:06:04