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

Terragrunt中EKS集群未创建时run-all plan触发数据源报错求助

Terragrunt run-all plan 首次执行Helm Provider报错解决方法

问题描述

计划通过Terragrunt+Terraform AWS EKS模块创建集群,再用Helm Provider部署cert-manager和ingress-nginx。单独创建集群无问题,但首次执行terragrunt run-all plan(无任何现有资源)时,出现以下错误:

│ Error: Reference to undeclared resource
│
│   on helm_provider.tf line 13, in provider "helm":
│   13:     host                   = data.aws_eks_cluster.cluster.endpoint
│
│ A data resource "aws_eks_cluster" "cluster" has not been declared in the
│ root module.
╵
╷
│ Error: Reference to undeclared resource
│
│   on helm_provider.tf line 14, in provider "helm":
│   14:     cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
│
│ A data resource "aws_eks_cluster" "cluster" has not been declared in the
│ root module.
╵
╷
│ Error: Reference to undeclared resource
│
│   on helm_provider.tf line 15, in provider "helm":
│   15:     token                  = data.aws_eks_cluster_auth.cluster.token
│
│ A data resource "aws_eks_cluster_auth" "cluster" has not been declared in
│ the root module.
╵

当前用于安装Addons的terragrunt.hcl配置:

terraform {
  source = "../../../modules/k8s-addons"
}

include "root" {
  path = find_in_parent_folders()
}

include "env" {
  path   = find_in_parent_folders("env.hcl")
  expose = true
}

inputs = {
  cluster_name = dependency.eks.outputs.cluster_name
}

dependency "eks" {
  config_path = "../eks"

  mock_outputs = {
    cluster_name     = "eks-cluster"
    cluster_endpoint = "https://eks-cluster.k8s.local"
    cluster_version  = "1.29"
  }
}

generate "helm_provider" {
  path      = "helm_provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF

data "aws_eks_cluster" "eks" {
    name = "${dependency.eks.outputs.cluster_name}"
}

data "aws_eks_cluster_auth" "eks" {
    name = "${dependency.eks.outputs.cluster_name}"
}

provider "helm" {
  kubernetes {
    host                   = data.aws_eks_cluster.cluster.endpoint
    cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
    token                  = data.aws_eks_cluster_auth.cluster.token
  }
}
EOF
}

错误根源

  1. 资源名称不匹配:生成的helm_provider.tf中,data资源的名称是eks,但Helm Provider里引用的是cluster,导致Terraform无法找到对应的资源。
  2. 集群未创建时的data资源读取:首次执行run-all plan时,EKS集群尚未创建,data资源会尝试读取不存在的集群,即使名称正确也会触发错误。

解决方案

步骤1:修正资源名称匹配问题

修改generate "helm_provider"块中的内容,将data资源的名称改为cluster,与Provider中的引用保持一致:

generate "helm_provider" {
  path      = "helm_provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF

data "aws_eks_cluster" "cluster" {
    name = "${dependency.eks.outputs.cluster_name}"
}

data "aws_eks_cluster_auth" "cluster" {
    name = "${dependency.eks.outputs.cluster_name}"
}

provider "helm" {
  kubernetes {
    host                   = data.aws_eks_cluster.cluster.endpoint
    cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
    token                  = data.aws_eks_cluster_auth.cluster.token
  }
}
EOF
}

步骤2:处理集群未创建时的配置读取

为了让run-all plan在集群创建前也能正常执行,结合mock输出和条件判断,让Helm Provider在集群创建前后都能获取有效配置:

  1. 更新dependency的mock_outputs,添加必要的模拟字段:
dependency "eks" {
  config_path = "../eks"

  mock_outputs = {
    cluster_name     = "eks-cluster"
    cluster_endpoint = "https://eks-cluster.k8s.local"
    cluster_version  = "1.29"
    cluster_ca_data  = "dGhpcy1pcy1hLW1vY2stY2EtZGF0YQ==" # 模拟Base64编码的CA数据
    cluster_created  = false # 标记集群未创建
  }
}
  1. 修改generate块,用条件判断切换模拟值和真实资源值:
generate "helm_provider" {
  path      = "helm_provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF

data "aws_eks_cluster" "cluster" {
  count = dependency.eks.outputs.cluster_created ? 1 : 0
  name  = "${dependency.eks.outputs.cluster_name}"
}

data "aws_eks_cluster_auth" "cluster" {
  count = dependency.eks.outputs.cluster_created ? 1 : 0
  name  = "${dependency.eks.outputs.cluster_name}"
}

provider "helm" {
  kubernetes {
    host                   = length(data.aws_eks_cluster.cluster) > 0 ? data.aws_eks_cluster.cluster[0].endpoint : "${dependency.eks.outputs.cluster_endpoint}"
    cluster_ca_certificate = length(data.aws_eks_cluster.cluster) > 0 ? base64decode(data.aws_eks_cluster.cluster[0].certificate_authority[0].data) : base64decode("${dependency.eks.outputs.cluster_ca_data}")
    token                  = length(data.aws_eks_cluster_auth.cluster) > 0 ? data.aws_eks_cluster_auth.cluster[0].token : "mock-auth-token-123"
  }
}
EOF
}
  1. 在EKS模块的outputs.tf中添加对应输出字段,确保集群创建后能传递真实值:
output "cluster_created" {
  value = true
}

output "cluster_ca_data" {
  value = aws_eks_cluster.cluster.certificate_authority[0].data
}

额外优化

在dependency块中添加skip_outputs = false,确保依赖的输出能被正确读取:

dependency "eks" {
  config_path = "../eks"
  skip_outputs = false
  mock_outputs = {
    # ... 现有mock内容
  }
}

验证

执行terragrunt run-all plan,此时会先处理EKS集群的plan,再处理Addons模块的plan,由于配置了条件判断和mock输出,Addons模块能正常生成plan,无需提前创建集群。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 18:10:56