配置Terraform S3后端时出现错误

31

我正在使用terraform为AWS配置S3后端。

terraform {
  backend "s3" {}
}

在运行“terraform init”命令并提供(S3后端)存储桶名称、密钥和区域的值时,出现以下错误:

配置后端“s3”时出错:未找到AWS提供程序的有效凭据来源。请参见https://terraform.io/docs/providers/aws/index.html以获取有关为AWS提供程序提供凭据的更多信息。请更新Terraform文件中的配置以解决此错误,然后再次运行此命令。

我已经在providers.tf中将访问密钥和秘密密钥声明为变量。在运行“terraform init”命令时,它没有提示任何访问密钥或秘密密钥。

如何解决这个问题?


只是出于好奇,如果在运行Terraform之前使用相同的凭据运行“aws configure”,它是否有效?另外,您是在Windows还是Linux / OSX上运行?我看到一些示例,在Windows下运行Terraform会忽略Git的凭据设置。也许这里发生了类似的事情。 - mhvelplund
请展示您提供程序的相关代码。 - Matt Schuchard
我的供应商代码provider "aws" { access_key = "${var.access_key}" secret_key = "${var.secret_key}" region = "${var.region}" }terraform { backend "s3" {} } - MKM
这里有一个后端配置示例:https://github.com/getstrake/aws-pricing-sheets-addon - A. R. Younce
12个回答

45
在运行terraform init时,您需要添加-backend-config选项以添加您的凭证(AWS密钥)。因此,您的命令应如下所示:

terraform init -backend-config="access_key=<您的访问密钥>" -backend-config="secret_key=<您的秘密密钥>"

请注意保留所有html标签。

我在代码中有provider块,请查看下面的代码provider "aws" { access_key = "${var.access_key}" secret_key = "${var.secret_key}" region = "${var.region}" }terraform { backend "s3" {} } - MKM
抱歉之前指错了方向。我现在认为我知道问题所在,并已相应地编辑了我的答案。 - codinghaus
感谢您的帮助。现在terraform init正常工作。但是,在执行terraform plan命令时,它会抛出一个新错误:“无法加载后端:配置后端“s3”时出错:不是有效的区域:”。我是否应该在运行terraform plan命令时提供-backend-config呢? - MKM
不错!但是 backend-config 绝对只在 terraform init 过程中需要。关于新错误:请确保你在 backend "s3" {} 块中设置了 region=<region> - codinghaus
我正在尝试执行 terraform plan -var-file 命令,但是出现了错误。在此文件中,必须添加哪些配置细节?我已经创建了一个示例 .tfvars 文件,并将访问密钥和秘密密钥添加到其中。这样做正确吗?还需要其他内容吗? - MKM
显示剩余4条评论

31

我也遇到了同样的问题,最简单而安全的方法是配置AWS文件。即使您在项目中正确地提到了AWS_PROFILE,您还必须在backend.tf中再次提到它

我的问题是,我已经按照以下方式设置了项目中的AWS提供程序,并且它正常工作。

provider "aws" {
region = "${var.AWS_REGION}"
profile = "${var.AWS_PROFILE}"
}

但是在项目结束时,我试图配置S3后端配置文件。因此,我运行了命令terraform init,并且我也收到了相同的错误消息。

Error: error configuring S3 Backend: no valid credential sources for S3 Backend found.

注意,这对于terraform后端配置来说还不够。你还需要在后端文件中提及AWS_PROFILE

  • 完整解决方案

我目前正在使用最新版本的terraform。它是v0.13.5。

请查看provider.tf

provider "aws" {
region = "${var.AWS_REGION}"
profile = "${var.AWS_PROFILE}" # lets say profile is my-profile
}
例如,您的AWS_PROFILE是< strong>my-profile,那么您的< code>backend.tf 应如下所示。
terraform {
    backend "s3" {
    bucket = "my-terraform--bucket"
    encrypt = true
    key = "state.tfstate"
    region = "ap-southeast-2"
    profile = "my-profile" # you have to give the profile name here. not the variable("${var.AWS_PROFILE}")
  }
}

然后运行 terraform init 命令。


1
非常感谢,这对我来说是正确的答案。 - Willemoes
1
这就是正确的答案,非常感谢! - Yayotrón
我正在使用aws-okta进行身份验证。我已经在aws提供程序设置中设置了配置文件。我无法成功运行terraform init,并且尝试了很多方法后感到疲倦。需要在后端配置中两次提及配置文件的信息帮助解决了我的问题,非常感谢! - Pankaj

9

我曾经遇到过类似的问题,当我重命名AWS凭证文件中的配置文件时。删除.terraform文件夹,并再次运行terraform init解决了这个问题。


非常感谢您的评论,这对我来说也是如此。 - undefined

5
如果您已经设置了自定义的AWS配置文件,请使用以下选项:

terraform init -backend-config="profile=your-profile-name"

如果没有自定义配置文件,则需要将access_key和secret_key添加到默认配置文件中并尝试。

3

我决定一劳永逸地解决这个问题,因为有很多关于同一个问题的不同主题。这个问题的主要原因是在开发本地环境与运行CI/CD流水线时使用了不同形式的身份验证。人们往往会混合不同的身份验证选项,而不考虑优先级顺序。

当在本地运行时,您应该绝对使用aws cli,因为您不想每次运行构建都必须设置访问密钥。如果您在本地使用多个帐户,则可以告诉aws cli切换配置文件:

export AWS_PROFILE=my-profile

当你想在 CI/CD 流水线(例如 Github Actions、CircleCI)中运行相同的代码时,你只需要在构建流程中导出所需的环境变量即可:
export AWS_ACCESS_KEY_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export AWS_REGION="eu-central-1"

只有在provider块中没有设置任何硬编码配置时,此方法才有效。因为AWS Terraform提供程序文档告诉我们认证的顺序。提供程序配置中的参数首先进行评估,然后是环境变量。

示例:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

provider "aws" {}

terraform {
  backend "s3" {}
}

在计划或应用此操作之前,您需要初始化后端:

terraform init \
  -backend-config="bucket=${TFSTATE_BUCKET}" \
  -backend-config="key=${TFSTATE_KEY}" \
  -backend-config="region=${TFSTATE_REGION}"

最佳实践:

  • 在本地运行时,请使用aws cli进行身份验证。在构建流水线中运行时,请使用环境变量进行身份验证。
  • 尽可能保持Terraform配置的简洁,避免硬编码设置,并保持提供程序块为空,以便您能够动态进行身份验证。
  • 最好也将s3后端配置保持为空,并从环境变量或配置文件初始化此配置。
  • Terraform文档建议将.terraform.lock.hcl包含在版本控制中,以便您可以通过代码审查讨论对外部依赖项的潜在更改。
  • 在构建流水线中设置AWS_PROFILE基本上是无用的。大多数情况下,在运行时您没有安装aws cli。如果您确实需要这个,那么您应该考虑将其拆分成单独的构建流水线。
  • 个人而言,我喜欢使用Terragrunt作为Terraform的包装器。其中一个主要原因是它使您能够动态设置后端配置。这在纯Terraform中是不可能的。

3
不要 - 添加用于机密信息的变量。这是非常非常糟糕的做法,并且是不必要的。
Terraform将使用默认的AWS配置文件或使用您设置的AWS_PROFILE。如果在AWS中,应该使用实例配置文件。也可以使用角色。
如果在tf代码中硬编码配置文件,则必须在想要运行此脚本的任何位置具有相同的配置文件名称,并且在针对每个不同帐户运行时更改它。
不要 - 进行所有这些命令行操作,除非您喜欢包装脚本或输入。 做 - 添加一个名为 remote_state.tf 的远程状态文件,如下所示:
terraform {
  backend "s3" {
    bucket         = "WHAT-YOU-CALLED-YOUR-STATEBUCKET"
    key            = "mykey/terraform.tfstate"
    region         = "eu-west-1"
  }
}

现在,当您进行terraform init时:

初始化远程后端...

成功配置了 "s3" 后端!除非后端配置更改,否则Terraform将自动使用此后端。

在提供程序中的值与远程状态的权限无关,甚至可以是不同的AWS帐户(甚至是其他云提供商)。


2
我遇到了同样的问题,以下是我的用例。
AWS账户1:管理账户(在此创建IAM用户,该用户将扮演Dev和Prod账户的角色)
AWS账户2:开发环境账户(在此为受信任的账户创建角色,在这种情况下是管理账户用户)
AWS账户3:生产环境账户(在此为受信任的账户创建角色,在这种情况下是管理账户用户)
因此,我创建了一个名为dev-backend.confprod-backend.conf的文件,其内容如下。解决此问题的主要方法是在S3后端配置中传递“role_arn”值。
在dev-backend.conf和prod-backend.conf文件中定义以下内容。
bucket = "<your bucket name>" 
key = "< your key path>" 
region = "<region>" 
dynamodb_table = "<db name>" 
encrypt = true 
profile = "< your profile>" # this profile has access key and secret key of the IAM user created in Management account 
role_arn = "arn:aws:iam::<dev/prod account id>:role/<dev/prod role name >"

使用本地状态的dev s3桶配置初始化Terraform,并将其转换为S3状态。
$ terraform init -reconfigure -backend-config="dev-backend.conf"

使用开发环境变量文件执行Terraform apply
$ terraform apply --var-file="dev-app.tfvars"

使用dev s3 bucket中的prod s3 bucket配置初始化Terraform,以便将状态存储到prod s3 bucket中

$ terraform init -reconfigure -backend-config="prod-backend.conf"

使用生产环境变量文件进行Terraform应用程序执行
$ terraform apply --var-file="prod-app.tfvars"

FYI:我的解决方案是使用个人资料标签。我的TF一开始运行得很好,后来突然出了问题。添加个人资料标签后问题得到了解决。 - granthbr
FYI:我的解决方案是使用个人资料标签。我的TF一开始运行得很好,后来出了问题。添加个人资料标签解决了这个问题。 - undefined

2

我曾经遇到同样的问题,一直在使用export AWS_PROFILE。我检查了我的凭证,它们是正确的。

重新运行aws configure出于某种原因解决了这个问题。


0

如果有人在使用localstack,对我而言只有这个提示有效 https://github.com/localstack/localstack/issues/3982#issuecomment-1107664517

 backend "s3" {
    bucket                      = "curso-terraform"
    key                         = "terraform.tfstate"
    region                      = "us-east-1"
    endpoint                    = "http://localhost:4566"
    skip_credentials_validation = true
    skip_metadata_api_check     = true
    force_path_style            = true
    dynamodb_table              = "terraform_state"
    dynamodb_endpoint           = "http://localhost:4566"
    encrypt                     = true
  }

不要忘记在提供者中添加终端点。
provider "aws" {
  region                      = "us-east-1"
  skip_credentials_validation = true
  skip_requesting_account_id  = true
  skip_metadata_api_check     = true
  s3_force_path_style         = true

  endpoints {
    ec2 = "http://localhost:4566"
    s3 = "http://localhost:4566"
    dynamodb = "http://localhost:4566"
  }
}

0

这是AWS的秘钥和访问秘钥问题,您需要添加正确的秘钥。另外,如果您正在使用GitLab CI,则取消选中“保护变量”和“掩码变量”框。

在此输入图片描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接