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

Terragrunt无法读取父级生成的provider.tf,AWS凭证获取失败

Terragrunt无法识别父级生成的provider配置问题分析与解决

目录结构

Project root
├── terraform
│   └── non_live
│       ├── base
│       │   └── terragrunt.hcl
│       ├── global.hcl
│       └── terragrunt.hcl

父级terragrunt.hcl内容

terragrunt_version_constraint = "< v0.52.0"
terraform_version_constraint  = ">= 1.5.5, < 1.6.0"

remote_state {
  backend = "s3"
  generate = {
    path      = "backend.tf"
    if_exists = "overwrite"
  }
  config = {
    bucket         = "my-bucket"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-west-1"
    encrypt        = true
    dynamodb_table = "my-lock-table"
  }
}

generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
provider "aws" {
  region  = "us-west-1"
  profile = "my-profile"
}
EOF
}

generate "version" {
  path      = "terraform.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
terraform {
  required_version = "1.5.5"
}
EOF
}

non_live/base/terragrunt.hcl内容

include "root" {
  path = find_in_parent_folders()
}

include "global" {
  path   = "${get_terragrunt_dir()}/../global.hcl"
  expose = true
}

terraform {
  source = "tfr:///terraform-aws-modules/s3-bucket/aws//.?version=3.15.1"
}

inputs = {
  bucket                                = "terragrunt-test-bucket"
  attach_deny_insecure_transport_policy = true
  s3_bucket_region                      = "${include.global.locals.region}"
}

问题现象

在non_live/base目录执行terragrunt init时,发现provider.tf被生成在.terragrunt-cache目录而非当前目录,同时Terragrunt报错无法找到AWS凭证:

ERRO[0007] Error finding AWS credentials (did you set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables?): NoCredentialProviders: no valid providers in chain. Deprecated.
        For verbose messaging see aws.Config.CredentialsChainVerboseErrors 
ERRO[0007] Unable to determine underlying exit code, so Terragrunt will exit with error code 1 

手动设置环境变量export AWS_PROFILE=my-profile后,问题可解决。


原因分析

  1. 生成文件位置问题:当Terragrunt通过terraform.source引用远程模块时,所有generate块创建的配置文件都会被写入到.terragrunt-cache下的模块副本中——这是Terragrunt的默认行为,目的是将生成的配置和远程模块代码合并后再交给Terraform执行,所以不会出现在当前工作目录。
  2. 凭证读取时机问题:Terragrunt初始化远程状态(remote_state)的操作,会在Terraform加载provider.tf之前执行。此时.terragrunt-cache里的provider.tf还没生效,Terragrunt无法读取其中配置的profile参数,只能依赖环境变量或AWS默认凭证链,因此会出现找不到凭证的报错。

解决方法

方法1:给远程状态配置添加profile

在父级terragrunt.hcl的remote_state.config中添加profile参数,让Terragrunt处理远程状态时直接使用指定的profile:

remote_state {
  backend = "s3"
  generate = {
    path      = "backend.tf"
    if_exists = "overwrite"
  }
  config = {
    bucket         = "my-bucket"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-west-1"
    encrypt        = true
    dynamodb_table = "my-lock-table"
    profile        = "my-profile"  # 新增这一行
  }
}

这样Terragrunt在初始化远程状态时就会用指定的profile,无需依赖环境变量。

方法2:用extra_arguments传递profile参数

在父级或子级terragrunt.hcl中添加extra_arguments块,给Terraform命令传递profile参数:

extra_arguments "aws_profile" {
  commands = ["init", "plan", "apply", "destroy"]
  arguments = ["-var", "aws_profile=my-profile"]
}

注意需要确保引用的远程模块支持aws_profile变量,或者在生成的provider块中引用该变量(比如把profile = "my-profile"改成profile = var.aws_profile)。

方法3:使用本地模块(不推荐)

如果一定要让provider.tf生成在当前目录,可以放弃远程模块的source配置,把模块代码放在本地目录。但这种方式会失去远程模块版本管理的优势,不适合生产环境。


内容的提问来源于stack exchange,提问作者zaman sakib

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 10:58:11