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

Terraform Route53别名记录因S3网站域名未就绪执行失败问题

问题:Terraform配置S3静态站点+Route53需两次terraform apply才能成功

场景概述

我需要完成以下操作:

  • 创建S3存储桶
  • 向存储桶上传静态站点文件
  • 将存储桶配置为静态网站
  • 配置Route53将子域名转发至该存储桶网站,替代S3默认的冗长域名

目前Terraform文件已编写完成,站点最终可正常访问,但必须执行两次terraform apply:

  1. 首次执行会创建存储桶、上传站点文件并完成静态网站的相关配置,但Route53记录资源会报错
  2. 第二次执行才能成功创建Route53记录

首次执行报错信息

Error: Missing required argument
│
│   with module.ui_site.aws_route53_record.www-a,
│   on modules\UI\route53.tf line 14, in resource "aws_route53_record" "www-a":
│   14:     name                   = aws_s3_bucket.site.website_domain
│
│ The argument "alias.0.name" is required, but no definition was found.

对应的Terraform代码

resource "aws_s3_bucket" "site" {
  bucket = "${var.ui_bucket_name}.${var.root_domain}"
}


resource "aws_s3_bucket_public_access_block" "site" {
  bucket = aws_s3_bucket.site.id

  block_public_acls       = false
  block_public_policy     = false
  ignore_public_acls      = false
  restrict_public_buckets = false
}

resource "aws_s3_bucket_website_configuration" "site" {
  bucket = aws_s3_bucket.site.id

  index_document {
    suffix = "index.html"
  }

  error_document {
    key = "index.html"
  }
}

resource "aws_s3_bucket_ownership_controls" "site" {
  bucket = aws_s3_bucket.site.id
  rule {
    object_ownership = "BucketOwnerPreferred"
  }
}

resource "aws_s3_bucket_acl" "site" {
  bucket = aws_s3_bucket.site.id

  acl = "public-read"
  depends_on = [
    aws_s3_bucket_ownership_controls.site,
    aws_s3_bucket_public_access_block.site
  ]
}


resource "aws_s3_bucket_policy" "site" {
  bucket = aws_s3_bucket.site.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "PublicReadGetObject"
        Effect    = "Allow"
        Principal = "*"
        Action    = "s3:GetObject"
        Resource = [
          aws_s3_bucket.site.arn,
          "${aws_s3_bucket.site.arn}/*",
        ]
      },
    ]
  })

  depends_on = [
    aws_s3_bucket_public_access_block.site
  ]
}


module "template_files" {
  source = "hashicorp/dir/template"

  base_dir = "${path.module}/../../../client_ui/build"

}
resource "aws_s3_object" "site" {
  bucket = aws_s3_bucket.site.bucket
  for_each = module.template_files.files
  key          = each.key
  content_type = each.value.content_type

  # The template_files module guarantees that only one of these two attributes
  # will be set for each file, depending on whether it is an in-memory template
  # rendering result or a static file on disk.
  source  = each.value.source_path
  content = each.value.content

  # Unless the bucket has encryption enabled, the ETag of each object is an
  # MD5 hash of that object.
  etag = each.value.digests.md5
}


#######################################################
## Route53

data "aws_route53_zone" "zone" {
  name         = var.root_domain
  private_zone = false
}


resource "aws_route53_record" "www-a" {
  zone_id = data.aws_route53_zone.zone.zone_id
  name = aws_s3_bucket.site.bucket
  type    = "A"

  alias {
    name                   = aws_s3_bucket.site.website_domain
    zone_id                = aws_s3_bucket.site.hosted_zone_id
    evaluate_target_health = true
  }
  depends_on = [
    aws_s3_bucket_website_configuration.site
  ]
}

已尝试的解决方法

在Route53记录的depends_on部分添加不同的资源(存储桶资源、存储桶网站配置资源),但问题仍未解决。


解决方案

问题根源在于:aws_s3_bucket.site.website_domain和aws_s3_bucket.site.hosted_zone_id这两个属性只有在存储桶的静态网站配置生效后才会被Terraform正确获取,但仅通过depends_on = [aws_s3_bucket_website_configuration.site]无法让Terraform明确感知到这两个属性的依赖关系。

修改Route53资源的配置,将alias块中的属性替换为从aws_s3_bucket_website_configuration资源导出的值,而不是直接从aws_s3_bucket资源获取:

resource "aws_route53_record" "www-a" {
  zone_id = data.aws_route53_zone.zone.zone_id
  name    = aws_s3_bucket.site.bucket
  type    = "A"

  alias {
    name                   = aws_s3_bucket_website_configuration.site.website_domain
    zone_id                = aws_s3_bucket_website_configuration.site.hosted_zone_id
    evaluate_target_health = true
  }
}

为什么这样修改有效?

  • aws_s3_bucket_website_configuration.site.website_domain和aws_s3_bucket_website_configuration.site.hosted_zone_id是明确依赖于静态网站配置资源的属性,Terraform会自动等待aws_s3_bucket_website_configuration.site创建完成后再计算这些值,不需要额外的depends_on声明。
  • 原配置中直接使用aws_s3_bucket.site.website_domain,Terraform在首次计划时无法确定该值是否存在,因为存储桶本身创建完成后,静态网站配置可能还未生效,导致属性值为空,触发"缺少必填参数"的错误。

修改后,只需要执行一次terraform apply即可完成所有资源的创建。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:57:34