问题描述
我有一些在 AWS 中创建资源的 terraform 代码。
对于生产,我们有一个针对真实 AWS 运行的 CICD 管道。对于本地开发,我使用 localstack。所以有两个像这样的提供者:
# AWS config
provider "aws" {
region = ...
}
# Localstack config
provider "aws" {
region = ...
access_key = "mock_access_key"
secret_key = "mock_secret_key"
skip_credentials_validation = true
endpoints {
s3 = "http://localhost:4566"
...
}
}
我当前的解决方案是注释掉未使用的提供程序。这并不理想,因为我们需要记住在本地开发时取消对 localstack 配置的注释,在推送代码时取消对真正的 aws 配置的注释,忘记这可能是一个大问题。
我还尝试为 localstack 配置 alias = localstack
和几个变量创建别名:
variable provider_id {
type = map
default = {
localdev = "aws.localstack"
prod = "aws"
}
}
variable aws_account {
type = string
default = ""
}
然后资源可以这样查找提供者:
provider = lookup(var.provider_id,var.aws_account)
那么想法是我们可以在运行 aws_account=...
时传递变量 terraform apply
,以便资源选择正确的提供者。但是,这不起作用并返回此错误(我认为是因为它应该查找 aws
而不是 "aws"
):
╷
│ Error: Invalid provider configuration reference
│
│ on s3.tf line 2,in resource "aws_s3_bucket" "bucket":
│ 2: provider = lookup(var.provider_id,var.aws_account)
│
│ The provider argument requires a provider type name,optionally followed by a period and then a configuration alias.
╵
即使它确实有效,它也不是理想的,因为我们必须记住将提供者查找添加到每个资源块。
我想知道与这样的多个提供商合作的最佳方式是什么?理想情况下是一个简单的解决方案,例如在运行 terraform apply
时传递变量或参数。我不介意它是否需要重构 terraform(我上周才学会了这个工具)。
解决方法
典型的处理方式是通过terraform workspaces:
特别是,组织通常希望在为不同开发阶段(例如,分阶段与生产)或不同内部团队服务的同一基础架构的多个部署之间创建强隔离。
所以您可以尝试拥有两个工作区,一个用于本地堆栈,第二个用于真正的 aws。
,您可以通过 Alias 工作流程实现这一点 - 但需要更改代码以在资源部分包含别名。请参考此文档:
https://www.terraform.io/docs/language/modules/develop/providers.html
尽管正如您提到的,一个配置用于 prod/root 帐户,另一个用于本地开发,在这种情况下推荐和测试的方法是创建两个工作区 - 分离工作区将为您带来很多优势,例如:
1- code is separate so no chances of messing with it accidentally
2- debugging will be much easier
3- you are free to experiment with your code without fear