繁体   English   中英

我如何从 Terraform 中模块的 output 中的元组中获取任何值?

[英]How i get any value from the tuple in output of module in Terraform?

我在 Terraform 中创建了三个模块,一个用于 EC2、VPC 和安全组。 我为三个模块运行完整堆栈,并使用安全组的 output 和 EC2 模块中的 VPC 模块,但我得到了这个错误:

creating EC2 Instance: InvalidSubnetID.NotFound: The subnet ID 'module.vpc_main.primary_private_subnets_id.value[0]' does not exist
        status code: 400, request id: d94befb9-a846-47f9-a7c2-c588996a723c

  on .terraform/modules/main_ec2/main.tf line 66, in resource "aws_instance" "create_instance":
  66: resource "aws_instance" "create_instance" {

VPC模块的output:

output "primary_public_subnets_id" {
  description = "public subnet ID"
  value       = aws_subnet.primary_public_subnets[*].id
}

output "primary_private_subnets_id" {
  description = "public subnet ID"
  value       = aws_subnet.primary_private_subnets[*].id
}

state 文件中的 output

outputs": {
    "primary_private_subnets_id": {
      "value": [
        "subnet-098d3aab6a102656c",
        "subnet-073699d0e266072d6",
        "subnet-07755f92e02ca8756",
        "subnet-0a2f21a6e9b80d91e"
      ],
      "type": [
        "tuple",
        [
          "string",
          "string",
          "string",
          "string"
        ]
      ]
    },
    "primary_public_subnets_id": {
      "value": [
        "subnet-0aea672a2f19cee51",
        "subnet-0a014df85bc56acd3"
      ],
      "type": [
        "tuple",
        [
          "string",
          "string"
        ]
      ]
    },

变量

variable "subnet_id" {
  type = list(string)
  default = [ "module.vpc_main.primary_public_subnets_id[0]", "module.vpc_main.primary_private_subnets_id[1]" ]
}

EC2模块部分:

resource "aws_instance" "create_instance" {

  ami = "${element(data.aws_ami.ami_id.*.id, count.index)}"

  instance_type = var.EC2_Type[count.index]

  subnet_id = var.subnet_id[count.index]

  associate_public_ip_address = var.associate_public_ip_address[count.index]

  vpc_security_group_ids = [ var.vpc_security_group_ids[count.index] ]

  key_name = "${local.name}-KP-${var.Server_Name[count.index]}"

  iam_instance_profile = aws_iam_instance_profile.iam_profile.name

  private_ip = var.EC2_IP[count.index]
  count = length(var.ami_name)

}

EC2 调用模块:

module "main_ec2" {
    source  = "/home/reham/Data/projectes/terraform/modules/EC2Module"
    EC2_Type = var.EC2_Type
    EC2_IP = var.EC2_IP
    subnet_id = var.subnet_id
    associate_public_ip_address = var.associate_public_ip_address
    vpc_security_group_ids = var.vpc_security_group_ids
}

请注意,任何模块都可以很好地单独工作。 请问如何从 Terraform 模块的 output 中的元组中获取任何值?

如果我们认为 VPC 模块也被调用,您不必将默认值添加到变量subnet_id 相反,您可以将变量定义保留为没有任何值:

variable "subnet_id" {
  type = list(string)
}

请注意,您使用的是list(string)类型的变量,而 EC2 实例的参数只需要一个值,因此它是string类型。 此外,在 EC2 模块中,您将count元参数设置为取决于变量ami_name的长度。 因此,即使您要进行正确的价值分配,我认为您也会得到很多意想不到的结果。 在对 EC2 模块进行任何调用之前,我建议将其修复为看起来更像:

resource "aws_instance" "create_instance" {
  count                       = length(var.subnet_id)
  ami                         = element(data.aws_ami.ami_id.*.id, count.index)
  instance_type               = var.EC2_Type[count.index]
  subnet_id                   = var.subnet_id[count.index]
  associate_public_ip_address = var.associate_public_ip_address[count.index]
  vpc_security_group_ids      = [var.vpc_security_group_ids[count.index]]
  key_name                    = "${local.name}-KP-${var.Server_Name[count.index]}"
  iam_instance_profile        = aws_iam_instance_profile.iam_profile.name
  private_ip                  = var.EC2_IP[count.index]
}

将元参数移动到resource块的顶部也是一个很好的做法,因为它对读者更可见。 我已将count设置为使用subnet_id变量的长度,因为我猜您希望每个子网中都有一个 EC2 实例。

另一件不清楚的事情是,如果您想在私有子网、公共子网或两者中拥有 EC2 实例。 为简单起见,假设您希望它们在公共子网中(因为您定义了associate_public_ip_address参数。这里您犯了另一个错误,即尝试设置一个bool参数(它只能具有truefalse值)以使用一个带有count.index的变量( var.associate_public_ip_address[count.index] )。除非您的associate_public_ip_address是 boolean 值的列表,否则这也不起作用。如果是这样,该代码可以保持不变。最后但并非最不重要的,因为VPC 模块提供您想要的输出,使用这些输出的方法如下:

module "vpc" {
 ... your module call goes here ...
}

module "main_ec2" {
  source                      = "/home/reham/Data/projectes/terraform/modules/EC2Module"
  EC2_Type                    = var.EC2_Type
  EC2_IP                      = var.EC2_IP
  subnet_id                   = module.vpc.primary_public_subnets_id
  associate_public_ip_address = var.associate_public_ip_address
  vpc_security_group_ids      = var.vpc_security_group_ids
}

此外,如果 VPC 模块提供了其他输出(例如,安全组 ID),您可以将其称为与子网 ID 相同的名称:

module.vpc.<name of the output>

即使有我回答中的详细信息,也不能保证它会起作用。 要使代码正常工作,需要进行大量重构。 此外,我强烈建议了解资源期望( stringlist(string)bool等)中值 arguments 的类型 [1]。 您还需要确保您了解如何引用模块输出 [2]。


[1] https://www.terraform.io/language/expressions/types

[2] https://www.terraform.io/language/expressions/references#child-module-outputs

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM