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

Terraform无法检测到S3中的TF State问题排查

问题

我用Terraform独立管理DNS,将代码部署到staging和production环境,采用GitHub Actions作为CI/CD工具部署到AWS。初始部署正常,但执行staging环境的destroy操作时会删除production环境的DNS记录,虽可重新运行production任务恢复,但不够理想。

于是我将DNS配置拆分到独立模块,项目结构如下:

├── deploy
│   ├── dns.tf
│   ├── ecs.tf
│   ├── load_balancer.tf
│   ├── main.tf
│   ├── modules
│   │   └── dns
│   │       ├── backend.tf
│   │       ├── main.tf
│   │       ├── outputs.tf
│   │       └── variables.tf
│   ├── network.tf
│   ├── outputs.tf
│   ├── templates
│   │   └── ecs
│   │       ├── task-assume-role-policy.json
│   │       ├── task-execution-role-policy.json
│   │       └── task-ssm-policy.json
│   └── variables.tf
├── docker-compose.yml
└── setup
    ├── ecr.tf
    ├── iam.tf
    ├── main.tf
    ├── outputs.tf
    └── variables.tf

尝试通过跨引用状态让基础架构配置使用DNS模块的输出,相关配置如下:

deploy/modules/dns/backend.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.89.0"
    }
  }

  backend "s3" {
    bucket               = "rsec-main-website-tf-state"
    key                  = "dns"
    workspace_key_prefix = "tf-state-deploy-env"
    encrypt              = true
    dynamodb_table       = "rsec-main-website-tf-lock"
    region = "eu-west-2"
  }
}

deploy/main.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.89.0"
    }
  }

  backend "s3" {
    bucket               = "rsec-main-website-tf-state"
    key                  = "tf-state-deploy"
    workspace_key_prefix = "tf-state-deploy-env"
    encrypt              = true
    dynamodb_table       = "rsec-main-website-tf-lock"
  }
}

provider "aws" {
  region = "eu-west-2"
  default_tags {
    tags = {
      Environment = terraform.workspace
      Project     = var.project
      Contact     = var.contact
      ManageBy    = "Terraform/deploy"
    }
  }
}

locals {
  prefix = "${var.prefix}-${terraform.workspace}"
}

data "terraform_remote_state" "dns" {
  backend = "s3"
  config = {
    bucket               = "rsec-main-website-tf-state"
    key                  = "dns"
    region               = "eu-west-2"
    workspace_key_prefix = "tf-state-deploy-env"
  }
}

data "aws_region" "current" {}

GitHub Actions工作流deploy.yml

name: Build and push images. Cache build artifacts.
on:
  workflow_call:
    inputs:
      version:
        required: true
        type: string

permissions:
  id-token: write
  contents: read

jobs:
  build_and_push_to_ecr:
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set Vars
        run: |
          if [[ $GITHUB_REF == 'refs/heads/production' ]]; then
            echo "production" > .workspace
          else
            echo "staging" > .workspace
          fi

      ...SNIP...

      - name: Terraform Apply
        run: |
          export TF_VAR_ecr_app_image="${{ vars.ECR_REPO_APP }}:${{ steps.compute_tags.outputs.app_tag }}"
          export TF_VAR_ecr_proxy_image="${{ vars.ECR_REPO_PROXY }}:${{ steps.compute_tags.outputs.proxy_tag }}"
          
          workspace=$(cat .workspace)
          cd infra/
          
          docker compose run --rm terraform -chdir=deploy/modules/dns init
          docker compose run --rm terraform -chdir=deploy/modules/dns workspace select -or-create $workspace
          docker compose run --rm terraform -chdir=deploy/modules/dns apply -auto-approve
          
          docker compose run --rm terraform -chdir=deploy/ init
          docker compose run --rm terraform -chdir=deploy/ workspace select -or-create $workspace
          docker compose run --rm terraform -chdir=deploy/ apply -auto-approve

AWS中的状态路径已正常创建,但流水线运行时出现错误:DNS部署成功、基础架构部署完成检查/差异分析后,应用前失败,错误信息如下:

╷
│ Error: Unable to find remote state
│ 
│   with data.terraform_remote_state.dns,
│   on main.tf line 34, in data "terraform_remote_state" "dns":
│   34: data "terraform_remote_state" "dns" {
│ 
│ No stored state was found for the given workspace in the given backend.

补充:DNS路径已包含预期的DNS记录,且deploy/modules/dns/outputs.tf已定义输出:

output "cert_arns" {
  description = "Map of certificate ARNs for each domain"
  value = {
    for domain, cert in aws_acm_certificate_validation.cert : domain => cert.certificate_arn
  }
}
解决方案

问题核心是**data.terraform_remote_state.dns未指定要读取的工作区**,默认会尝试读取default工作区的状态,但你的DNS模块是用staging或production工作区部署的,所以找不到对应状态文件。

具体修复步骤

  1. 更新deploy/main.tf中的远程状态数据源,添加workspace参数绑定当前工作区:
data "terraform_remote_state" "dns" {
  backend = "s3"
  config = {
    bucket               = "rsec-main-website-tf-state"
    key                  = "dns"
    region               = "eu-west-2"
    workspace_key_prefix = "tf-state-deploy-env"
  }
  # 关键:指定读取与当前部署工作区一致的DNS状态
  workspace = terraform.workspace
}
  1. 验证工作区一致性:确认工作流中DNS模块和基础架构模块使用的是同一个工作区(staging或production),你的现有工作流已经通过workspace=$(cat .workspace)保证了这一点,无需调整。

  2. 可选:检查S3状态文件路径:登录AWS S3控制台,确认DNS模块的状态文件路径为tf-state-deploy-env/<workspace>/dns,确保文件存在且权限正确。

修改后,基础架构模块就能正确读取对应环境的DNS状态数据,解决找不到远程状态的错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 19:24:51