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

Terraform多循环实现CNAME关联多A记录的配置报错解决方案

问题原因
  • Terraform语法错误:records = [values(aws_route53_record.instance_record)[*].name] 这行额外套了一层方括号,最终传入参数的是双层嵌套列表[["webserver1.domain.com", "webserver2.domain.com"]],而records参数要求一维字符串列表,第一个元素是列表而非字符串,直接触发类型不匹配。
  • DNS协议规则限制:哪怕你修正语法去掉外层方括号,配置也无法正常创建。标准DNS规范(RFC 1034)明确要求单条CNAME记录仅允许配置1个目标域名,不支持同时关联多个值,你预期的单条CNAME绑定2个A记录的效果本身不符合协议规则,Route53会直接拒绝创建这类记录。
  • 隐藏逻辑错误:你现有配置里的instance_record资源也有问题:你用for_each遍历hostname为每个webserver创建单独A记录,但records参数直接传入了所有EC2的IP列表,最终会导致webserver1、webserver2两个A记录都同时绑定2个IP,和你预期的单域名绑定单实例IP的效果不符。
可行实现方案

如果你的核心需求是3个www子域名均可解析到2台EC2实例地址,实现多节点轮询访问,推荐用以下符合规范的方案:

方案1:直接创建多值A记录(最优方案)

不需要额外创建webserver层的A记录再做跳转,直接给www子域名配置多值A记录,少一层CNAME解析,解析性能更好:

# 如果你不需要单独访问webserver1、webserver2这两个域名,可以删掉这段instance_record资源
resource "aws_route53_record" "instance_record" {
  for_each = toset(var.hostnames)

  zone_id = data.aws_route53_zone.route53_zone.zone_id
  name    = "${each.value}.${var.domain}"
  type    = "A"
  ttl     = "300"
  # 按hostname索引取对应实例IP,避免列表顺序错乱;更推荐将EC2模块输出改为map类型做键值匹配,稳定性更高
  records = [module.ec2_instance.server_ip_addresses[index(var.hostnames, each.value)]]
}

resource "aws_route53_record" "webservice_records" {
  for_each = toset(var.subdomain_addresses)

  zone_id = data.aws_route53_zone.route53_zone.zone_id
  name    = "${each.value}.${var.domain}"
  type    = "A"
  ttl     = "300"
  # 二选一即可:不需要保留webserverA记录就直接用EC2输出,保留的话就引用instance_record的IP
  # records = values(aws_route53_record.instance_record)[*].records[0]
  records = module.ec2_instance.server_ip_addresses
}

这个配置最终生成的解析效果和你预期的访问效果完全一致:访问任意www子域名时,DNS会轮询返回两台EC2的IP地址。

方案2:必须使用CNAME的场景处理

如果你因为业务规则必须使用CNAME类型记录,单条CNAME只能指向一个目标域名,你需要配合负载均衡(比如ALB)实现:先创建一个ALB挂载两台EC2实例,给ALB配置单独的访问域名,再将三个www子域名的CNAME指向ALB的域名即可,无法通过单条CNAME直接指向多个A记录实现需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 22:51:19