32

有没有办法为项目中定义的所有模块抽象提供者。

例如,我有这个项目

├── modules
│   ├── RDS
│   └── VPC
└── stacks
    ├── production
    │   └── main.tf
    └── staging
        └── main.tf

它工作正常......问题在于模块的定义

├── RDS
│   ├── README.md
│   ├── main.tf
│   ├── providers.tf
│   └── variables.tf
└── VPC
    ├── README.md
    ├── main.tf
    ├── providers.tf
    └── variables.tf

这两个模块中的提供者完全相同

# providers.tf
provider "aws" {
  region = "${var.region}"
  version = "~> 1.26"
}

并且每个模块中的变量都是不同的,但它们都有region变量。

# variables.tf
variable "region" {
  default     = "eu-central-1"
  description = "AWS region."
}
# other module dependent variables...

有没有办法在模块级别定义这些信息,以便我最终得到大致这样的东西

├── modules
│   ├── providers.tf  <<< include the *shared* provider definition block
│   ├── variables.tf  <<< include the *shared* region vaiable definition block
│   ├── RDS
│   │   ├── README.md
│   │   ├── main.tf
│   │   └── variables.tf
│   └── VPC
│       ├── README.md
│       ├── main.tf
│       └── variables.tf

最后一件事,模块定义大部分时间都具有资源属性(从 terraform 注册表中提取模块......因此我不知道从注册表和基本模块继承源是否可行)

4

4 回答 4

15

目前不可能实现这一目标。之前在github上有过关于同一主题的讨论,有以下几期:

TL;DR
模块之间的变量共享违反了 terraform 核心清晰度/明确性原则。

解决方法
解决方法是将*shared*文件放在父目录中并使用符号链接将它们添加到模块中。

于 2018-07-06T22:20:31.943 回答
7

如果你知道terragrunt,这完全没有问题。

Terragrunt 是 Terraform 的瘦包装器,它提供了用于处理多个 Terraform 模块的额外工具。

它专为您刚刚遇到的问题而设计。

account
 └ _global
 └ region
    └ _global
    └ environment
       └ resource

快速开始

查看terragrunt-infrastructure-modules-exampleterragrunt-infrastructure-live-example 存储库以获取演示这些功能的完整工作示例代码

您可以将prod/terraform.tfvarsorprod/account.tfvars用于全局变量或将 tfvars 文件放在_global文件夹下。

于 2018-07-07T10:20:25.337 回答
7

您可以通过传入要使用的提供者别名从模块中抽象出提供者参数。这允许您在不参考 Region 之类的东西的情况下创建模块,然后在调用时传递这些详细信息。

对于您的用例,您可以在堆栈文件夹中定义别名提供程序(最好在文件中定义它并为每个堆栈文件夹创建符号链接):

# stacks/{staging,production}/providers.tf
provider "aws" {
  alias  = "us-east-1"
  region = "us-east-1"
}

provider "aws" {
  alias   = "us-east-2"
  region  = "us-east-2"
}

然后,当您调用模块时,传入您要使用的提供程序别名(假设模块仅使用任何特定提供程序类型中的一种):

# stacks/{staging,production}/main.tf
module "VPC-us-east-1" {
  source = "../../modules/VPC"

  providers = {
    aws      = "aws.us-east-1"
  }
}

module "VPC-us-east-2" {
  source = "../../modules/VPC"

  providers = {
    aws      = "aws.us-east-2"
  }
}
于 2018-07-08T04:15:54.020 回答
0

目前 Hashicorp 配置语言没有全局变量功能。

variables用于定义模块的模块接口或充当类似 ENV 变量(内联 ENV)。因此,这不是将变量用作全局共享的最佳方式。因为每次定义一些模块时,总是需要考虑在上层模块上使用了哪些变量。也许你最终会喜欢:first_module_s3_bucket_name, second_module_s3_bucket_name.

但是locals共享给子模块更有意义。因为,当地人认为有助于避免重复相同的价值。

如果您有兴趣,有关于 Hashicorp 功能请求的新讨论。

https://github.com/hashicorp/terraform/issues/25431

于 2020-06-30T05:22:07.883 回答