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

Terraform配置多域名CloudFront时Route53Zone匹配错误求助

问题排查:Terraform创建子域名ACM证书时Route53Zone找不到错误

问题场景

尝试通过Terraform配置多CloudFront站点(主域名+多子域名),每个站点对应独立CloudFront分发,第一步创建ACM证书时遇到错误。

ACM证书模块(modules/acm_certificate/main.tf)

data "aws_route53_zone" "public" {
  name = var.domain
}

resource "aws_acm_certificate" "this" {
  domain_name       = "www.${var.domain}"
  subject_alternative_names = ["www.${var.domain}", "${var.domain}"]
  validation_method = "DNS"
  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "cert_validation" {
  allow_overwrite = true
  for_each = {
    for dvo in aws_acm_certificate.this.domain_validation_options : dvo.domain_name => {
      name    = dvo.resource_record_name
      record  = dvo.resource_record_value
      type    = dvo.resource_record_type
      zone_id = data.aws_route53_zone.public.id
    }
  }

  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = each.value.zone_id
}

resource "aws_acm_certificate_validation" "this" {
  certificate_arn         = aws_acm_certificate.this.arn
  validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}

站点模块(sites/route53.tf)

data "aws_route53_zone" "public" {
  name = var.domain # base domain route53
}

locals {
  subdomainsList = {
    for pv in var.project_version : pv.project => {
      subdomain_name = "${pv.project}.${var.domain}"
      #target_distribution    = aws_cloudfront_distribution.engagement_hub_subdomains[pv.project]
    }
  }
}

module "acm_certificate_domain" {
  source = "../../modules/acm_certificate" # for base domain tst.example.com
  domain = var.domain
  env    = var.env
  region = var.region
  dns_name = var.dns_name
  providers = {
    aws        = aws
    aws.global = aws.global
  }
}

module "acm_certificate_subdomain" {
  env    = var.env
  region = var.region
  dns_name = var.dns_name
  for_each = local.subdomainsList
  source   = "../../modules/acm_certificate" # for sub domains 
  domain   = each.value.subdomain_name
  providers = {
    aws        = aws
    aws.global = aws.global
  }
}

错误信息

Error: no matching Route53Zone found
with module.static_site.module.acm_certificate_subdomain["project1"].data.aws_route53_zone.public
on modules/acm_certificate/main.tf line 1, in data "aws_route53_zone" "public":
data "aws_route53_zone" "public" {

工作区变量:var.domain=example.com,var.project_version=[{"project": "project1", "version": "v123.1"}]

错误原因

当创建子域名project1.example.com的ACM证书时,ACM模块中的data "aws_route53_zone" "public"会用传入的var.domain(即project1.example.com)去查找Route53区域,但AWS账号中仅存在example.com的Route53公共区域,没有project1.example.com的独立区域,因此Terraform无法找到匹配的区域,抛出错误。

解决方案

提供两种可行修复方案,推荐方案二(更稳定可控):

方案一:调整模块内Route53区域查找逻辑

修改ACM模块中的data "aws_route53_zone" "public",通过正则提取主域名(最后两个域名段)来查找正确的Route53区域:

data "aws_route53_zone" "public" {
  # 提取主域名,适配子域名场景:project1.example.com → example.com
  name = regex("([^.]+\\.[^.]+)$", var.domain)[0]
}

该正则会自动匹配域名的最后两个部分,无论传入的是主域名还是子域名,都能定位到正确的Route53主区域。

方案二:调用模块时传入主域名的Route53区域ID(推荐)

  1. 修改ACM模块变量:在modules/acm_certificate/variables.tf中添加新变量:
variable "route53_zone_id" {
  type        = string
  description = "ID of the main Route53 zone for DNS validation records"
}
  1. 更新ACM模块代码:删除模块内的data "aws_route53_zone" "public",直接使用传入的区域ID:
# 移除原有的data "aws_route53_zone" "public"块

resource "aws_route53_record" "cert_validation" {
  allow_overwrite = true
  for_each = {
    for dvo in aws_acm_certificate.this.domain_validation_options : dvo.domain_name => {
      name    = dvo.resource_record_name
      record  = dvo.resource_record_value
      type    = dvo.resource_record_type
      zone_id = var.route53_zone_id
    }
  }

  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = each.value.zone_id
}
  1. 更新站点模块调用逻辑:在调用ACM模块时,传入主域名的Route53区域ID:
module "acm_certificate_domain" {
  source          = "../../modules/acm_certificate"
  domain          = var.domain
  env             = var.env
  region          = var.region
  dns_name        = var.dns_name
  route53_zone_id = data.aws_route53_zone.public.id # 传入主区域ID
  providers = {
    aws        = aws
    aws.global = aws.global
  }
}

module "acm_certificate_subdomain" {
  env             = var.env
  region          = var.region
  dns_name        = var.dns_name
  for_each        = local.subdomainsList
  source          = "../../modules/acm_certificate"
  domain          = each.value.subdomain_name
  route53_zone_id = data.aws_route53_zone.public.id # 传入同一主区域ID
  providers = {
    aws        = aws
    aws.global = aws.global
  }
}

这种方式明确指定了验证记录要写入的Route53区域,避免了自动查找的不确定性,更适合多子域名场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:35:00