Terraform0.15.1多提供商问题-需要参数“区域”,但未设置

所以下面是我的项目文件结构:

??? main.tf
??? tunnel
?   ??? main.tf
?   ??? variables.tf
??? variables.tf

我正在尝试按照此处所述在 Terraform 0.15.1 中使用多个提供程序 -> https://www.terraform.io/docs/language/modules/develop/providers.html

按照示例操作后,我无法使其正常工作。我现在已经简化了我的代码,只使用一个提供程序别名(尽可能简单)。我得到的错误是:

?
? Error: Missing required argument
? 
? The argument "region" is required, but was not set.
?

我在根目录中的 main.tf 文件:

module "tunnel" {
  source    = "./tunnel"
  providers = {
    aws.r = aws.requester
  }
}

我在根目录中的 variables.tf:

provider "aws" {
  alias  = "requester"
  region = "ap-southeast-2"
  profile = "benchmark"
}

我的隧道/variables.tf 文件:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 2.7.0"
      configuration_aliases = [ aws.r ]
    }
  }
}

data "aws_region" "current" {}

data "aws_caller_identity" "current" {}

我的隧道/main.tf 文件:

# Requester's side of the connection.
resource "aws_vpc_peering_connection" "peer" {
  vpc_id        = "vpc-xxxxxxxxxxxxxxxxx"
  peer_vpc_id   = "vpc-xxxxxxxxxxxxxxxxx"
  peer_owner_id = data.aws_caller_identity.current.account_id
  peer_region   = data.aws_region.current.name
  auto_accept   = false

  tags = {
    Side = "Requester"
  }
}

我不明白为什么我会收到这个错误?此代码的最终目标是使 vpc 对等互连的双方自动化,如下所示 -> https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection_accepter。但是我目前坚持让两个 aws 提供程序使用不同的凭据(上面示例中的一个提供程序以简化事情)。

当我alias = "requester"从根 main.tf 中删除时:

provider "aws" {
//  alias  = "requester"
  region = "ap-southeast-2"
  profile = "benchmark"
}

以及根路径中 main.tf 中的提供程序配置:

module "tunnel" {
  source    = "./tunnel"
//  providers = {
//    aws.r = aws.requester
//  }
}

和来自tunnel/variables.tf的别名配置:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 2.7.0"
//      configuration_aliases = [ aws.r ]
    }
  }
}

计划工作正常:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.tunnel.aws_vpc_peering_connection.peer will be created
  + resource "aws_vpc_peering_connection" "peer" {
      + accept_status = (known after apply)
      + auto_accept   = false
      + id            = (known after apply)
      + peer_owner_id = "xxxxxxx"
      + peer_region   = "ap-southeast-2"
      + peer_vpc_id   = "vpc-xxxxxxxxxxxxxxxxx"
      + tags          = {
          + "Side" = "Requester"
        }
      + vpc_id        = "vpc-xxxxxxxxxxx"

      + accepter {
          + allow_classic_link_to_remote_vpc = (known after apply)
          + allow_remote_vpc_dns_resolution  = (known after apply)
          + allow_vpc_to_remote_classic_link = (known after apply)
        }

      + requester {
          + allow_classic_link_to_remote_vpc = (known after apply)
          + allow_remote_vpc_dns_resolution  = (known after apply)
          + allow_vpc_to_remote_classic_link = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

回答

此错误消息是 Terraform 必须使更简单的情况变得更简单的一些自动行为的结果,但不幸的是,这导致在像您这样的更复杂的情况下情况相当不清楚。

在您的子模块中,您已经声明它期望在调用者中传递一个替代(别名)提供者配置,在此模块中将被称为aws.r. 但是,您之后声明的数据资源不包含provider用于指定它们属于哪个提供程序配置的参数,因此 Terraform 选择默认(无别名)提供程序配置。

不幸的是,你的配置实际上并不一个默认提供的配置,因为根模块使用其他供应商的配置aws.requester。因此,Terraform 会自动构建一个空配置,因为这对于http不需要任何特殊配置的简单提供程序来说是一种有用的行为。但这最终对aws提供者不起作用,因为它需要 region设置。

至少有两种不同的方法可以更改子模块以使其工作。其中哪一个最合适取决于该模块如何适应您的更广泛的配置。


第一个选项是根本不声明子模块aws.r,而只在整个过程中使用其默认提供程序配置:

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

data "aws_region" "current" {}

data "aws_caller_identity" "current" {}

因为您的根模块没有默认配置,所以hashicorp/aws您仍然需要在模块调用中明确说明该模块的默认提供aws.requester者是根模块看到的提供者:

module "tunnel" {
  source    = "./tunnel"
  providers = {
    aws = aws.requester
  }
}

对于不需要多个 AWS 提供程序配置的共享模块来说,这种方法是一个不错的选择,因为模块本身可能完全不知道其调用者中的多个配置,而只是期望为其提供默认配置hashicorp/aws使用。

但是,如果您的子模块也需要有多个配置,那么它就行不通hashicorp/aws了。在这种情况下,您将需要我接下来将介绍的另一个选项。


当一个共享模块将与多个提供者配置一起工作时,我们需要为configuration_aliases它期望从其调用者传递的每个配置声明一个条目。你只展示了一个r在你的例子中调用的,我不知道“r”代表什么,所以为了这里的例子,我将把它们称为“src”(对于“源”)和“dst”对于( “目的地”)只是为了举例说明一些有意义的术语。

我们将从configuration_aliases配置开始:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 2.7.0"
      configuration_aliases = [ aws.src, aws.dst ]
    }
  }
}

中给出的每一项都configuration_aliases声明了一个配置地址,providers在对该模块的任何调用中,该地址必须在参数中具有相应的条目,我们将在后面看到。

由于此模块不希望使用默认(无别名)配置,因此我们现在需要为每个资源块告诉 Terraform 它属于哪个提供程序配置。从您的数据资源开始,让我们假设它们属于“源”端:

data "aws_region" "current" {
  provider = aws.src
}

data "aws_caller_identity" "current" {
  provider = aws.src
}

我怀疑在您的真实系统中,aws_vpc_peering_connection您显示的资源在逻辑上也可能属于“源”端,但由于您没有显示任何其他资源,因此我将任意分配它aws.dst以显示其外观:

resource "aws_vpc_peering_connection" "peer" {
  provider = aws.dst

  vpc_id        = "vpc-xxxxxxxxxxxxxxxxx"
  peer_vpc_id   = "vpc-xxxxxxxxxxxxxxxxx"
  peer_owner_id = data.aws_caller_identity.current.account_id
  peer_region   = data.aws_region.current.name
  auto_accept   = false

  tags = {
    Side = "Requester"
  }
}

该模块中的每个dataresource块都需要provider设置,因为在该模块中默认没有可供选择的默认提供程序配置。

当您调用模块时,您需要告诉 Terraform 调用者中的哪些提供程序配置映射到被调用模块中的srcdst配置:

module "tunnel" {
  source    = "./tunnel"
  providers = {
    aws.src = aws.requester
    aws.dst = aws.peer
  }
}

正如我之前提到的,我们需要providersconfiguration_aliases模块内部的每个声明输入一个条目。将这些替代提供者配置视为与输入变量有些相似可能会有所帮助,但它们具有更专门的声明和定义语法,因为提供者对于 Terraform 的执行模型非常重要,需要在正常表达式评估之前解决.

在这里,我只是随意选择了“peer”作为您在根模块中声明的假定第二个配置的名称。将调用者中的默认配置分配给被调用模块中的替代配置也是有效的,例如aws.src = aws,但这似乎不适用于您的情况,因为您在根模块中也没有默认配置。


以上是Terraform0.15.1多提供商问题-需要参数“区域”,但未设置的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>