使用模块创建安全组时如何避免重复?—— Terraform

9

更新

我不太明白,但我重新运行了terraform apply,它没有尝试复制资源(没有错误)。现在它可以正确地检查资源。有点出乎意料。


我正在学习 Terraform,并创建了一个模块以允许创建一些基本的安全组。第一次运行很顺利,按预期创建资源。但是如果我第二次运行terraform apply,它会尝试再次创建相同的组,然后我会收到重复错误,因为这样的安全组已经存在。

如果我直接创建安全组而没有使用module,Terraform会识别它并不会尝试重新创建现有资源。

我可能在这里做错了什么。

这是我的模块以及我如何使用它:

我的项目结构如下

├── main.tf
├── modules
│   ├── security_group_ec2
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
│   └── security_group_rds
│       ├── main.tf
│       ├── outputs.tf
│       └── variables.tf
├── scripts
│   └── update-odoo-cfg.py
├── security_groups.tf
├── terraform.tfstate
├── terraform.tfstate.backup
├── variables.tf
└── vpc.tf

现在是我的security_group_ec2内容:

main.tf:

resource "aws_security_group" "sg" {
  name = "${var.name}"
  description = "${var.description}"
  vpc_id = "${var.vpc_id}"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port       = 0
    to_port         = 0
    protocol        = "-1"
    cidr_blocks     = ["0.0.0.0/0"]
  }
}

variables.tf:

variable "name" {
  description = "Name of security group"
}

variable "description" {
  description = "Description of security group"
}
variable "vpc_id" {
  description = "Virtual Private Cloud ID to assign"
}

输出:

output "sg_id" {
  value = "${aws_security_group.sg.id}"
}

这是一个调用模块创建两个安全组的文件。

security_groups.tf:

# EC2
module "security_group_staging_ec2" {
  source = "modules/security_group_ec2"
  name = "ec2_staging_sg"
  description = "EC2 Staging Security Group"
  vpc_id = "${aws_default_vpc.default.id}"
}

module "security_group_prod_ec2" {
  source = "modules/security_group_ec2"
  name = "ec2_prod_sg"
  description = "EC2 Production Security Group"
  vpc_id = "${aws_default_vpc.default.id}"
}

运行terraform apply时,出现了以下错误输出:

module.security_group_staging.aws_security_group.sg: Destruction complete after 1s
module.security_group_prod.aws_security_group.sg: Destruction complete after 1s

Error: Error applying plan:

2 error(s) occurred:

* module.security_group_staging_ec2.aws_security_group.sg: 1 error(s) occurred:

* aws_security_group.sg: Error creating Security Group: InvalidGroup.Duplicate: The security group 'ec2_staging_sg' already exists for VPC 'vpc-2a84a741'
    status code: 400, request id: 835004f0-d8a1-4ed5-8e21-17f01eb18a23
* module.security_group_prod_ec2.aws_security_group.sg: 1 error(s) occurred:

* aws_security_group.sg: Error creating Security Group: InvalidGroup.Duplicate: The security group 'ec2_prod_sg' already exists for VPC 'vpc-2a84a741'
    status code: 400, request id: 953b23e8-20cb-4ccb-940a-6a9ddab54d53

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

顺便提一下,我可能需要在调用模块时指示资源是如何创建的?


问题可能是您的本地状态没有正确更新,或者以某种方式被修改为先前的状态。 Terraform 在很大程度上依赖于其本地状态文件来描述基础架构的当前状态。 - Sorabh Mendiratta
1个回答

5
这看起来像是一个竞态条件。Terraform试图并行创建不相互依赖的资源,在这种情况下,它似乎尝试在module.security_group_staging_ec2中同时使用相同的名称销毁module.security_group_staging的安全组并创建它们。您是否将security_group_staging重命名为security_group_staging_ec2
销毁成功了,但由于与销毁同时运行,创建失败了。
第二次运行时没有竞态条件,因为module.security_group_staging已经被销毁。
另外需要注意的是,通常最好不要在同一个状态文件中保留不同的环境。

是的,我确实重命名了它。谢谢你的建议。我知道将环境分开是更好的想法,尽管目前我只是在玩耍 - 那个生产环境还不是真正的。但是,是的,我需要将其分开。 - Andrius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接