Terraform 配置未将其他文件的输出用于已创建的资源,而是尝试重新创建它并失败(安全组 ID)



在terraform/aws/global/vpc/security_groups.tf中,我有以下代码来创建我的堡垒安全组,以及下面的 output.tf 文件。但是在 terraform/aws/layers/bastion/main.tf(代码也在下面(中,我引用了该安全组,因为我需要它的安全组 ID 来创建我的 EC2 实例,我遇到的问题是,它不是从/vpc/security_groups.tf 配置创建的现有安全组中获取 ID,而是尝试创建整个安全组,运行显然失败,因为它已经存在。如何更改我的代码以获取现有 SG 的 ID?我不想在与实例相同的配置文件中创建我的 SG,我的一些安全组在不同的资源之间共享。我正在使用Terraform Cloud,VPC有自己的工作区,所以我认为这实际上可能是状态不同的问题。有解决方法吗?

terraform/aws/global/vpc/security_groups.tf

provider "aws" {
region = "eu-west-1"
}
resource "aws_security_group" "bastion" {
name        = "Bastion_Terraform"
description = "Bastion SSH access Terraform"
vpc_id      = "vpc-12345"
ingress {
description = "Bastion SSH"
from_port   = ##
to_port     = ##
protocol    = "##"
cidr_blocks = ["1.2.3.4/56"]
}
ingress {
description = "Bastion SSH"
from_port   = ##
to_port     = ##
protocol    = "##"
cidr_blocks = ["1.2.3.4/0"]    
}
egress {
description = "Access to "
from_port   = ##
to_port     = ##
protocol    = "tcp"
security_groups = ["sg-12345"]
}
egress {
description = "Access to ##"
from_port   = ##
to_port     = ##
protocol    = "tcp"
security_groups = ["sg-12345"]
}
tags = {
Name = "Bastion Terraform"
}
}

terraform/aws/global/vpc/outputs.tf

output "bastion-sg" {
value = aws_security_group.bastion.id
}

terraform/aws/layers/bastion/main.tf

provider "aws" {
region = var.region
}
module "vpc" {
source = "../../global/vpc"
}
module "ec2-instance" {
source = "terraform-aws-modules/ec2-instance/aws"
name = "bastion"
instance_count = 1
ami = var.image_id
instance_type = var.instance_type
vpc_security_group_ids = ["${module.vpc.bastion-sg}"]
subnet_id = var.subnet
iam_instance_profile = var.iam_role
tags = {
Layer = "Bastion"
}
}

当您在 TF 模块中有这样的子模块块时:

module "ec2-instance" {
source = "terraform-aws-modules/ec2-instance/aws"
name = "bastion"
instance_count = 1
ami = var.image_id
instance_type = var.instance_type
vpc_security_group_ids = ["${module.vpc.bastion-sg}"]
subnet_id = var.subnet
iam_instance_profile = var.iam_role
tags = {
Layer = "Bastion"
}
}

它不仅引用该子模块,还生成一个全新的实例,该实例仅对父模块及其状态是唯一的。不要把它想象成一个赋值或指针,而是构造一个全新的模块实例(使用模块作为模板(,并再次创建其所有资源。

您需要在具有其模块块的父模块中直接引用子模块的输出,或者需要使用terraform_remote_state数据源或 Terragrunt 依赖项从状态文件加载输出。

最新更新