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 }
错误根源
- 资源名称不匹配:生成的
helm_provider.tf中,data资源的名称是eks,但Helm Provider里引用的是cluster,导致Terraform无法找到对应的资源。 - 集群未创建时的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在集群创建前后都能获取有效配置:
- 更新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 # 标记集群未创建 } }
- 修改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 }
- 在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
相关产品推荐
相关产品推荐

