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工作区部署的,所以找不到对应状态文件。
具体修复步骤
- 更新
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 }
验证工作区一致性:确认工作流中DNS模块和基础架构模块使用的是同一个工作区(
staging或production),你的现有工作流已经通过workspace=$(cat .workspace)保证了这一点,无需调整。可选:检查S3状态文件路径:登录AWS S3控制台,确认DNS模块的状态文件路径为
tf-state-deploy-env/<workspace>/dns,确保文件存在且权限正确。
修改后,基础架构模块就能正确读取对应环境的DNS状态数据,解决找不到远程状态的错误。
内容的提问来源于stack exchange,提问作者3therk1ll

