使用for_each创建AWS安全组规则时Terraform随机删除资源的原因是什么
问题原因
你遇到的删除行为是两个常见错误共同导致的:
- 混合使用
aws_security_group的内嵌ingress/egress块和独立的aws_security_group_rule资源。AWS Provider设计逻辑中,只要安全组资源内定义了内嵌规则块,就会默认管理该安全组的所有规则,所有未在块内声明的规则(包括你用for_each创建的独立规则)都会被判定为多余配置,触发删除。 - Egress规则参数使用错误。出站规则指定对端安全组时,应该使用
destination_security_group_id参数,你当前使用的source_security_group_id是入站规则专用参数。参数错误会导致Terraform配置和AWS实际状态不一致,每次执行计划都会触发规则的删除重建,表现为规则随机消失。
修复方案
方案1:保留安全组内嵌规则
在安全组资源中添加生命周期规则,忽略对出入站规则的变更检测:
resource "aws_security_group" "ec2_jumper_sg" { name = "${var.app_name}-private-sg" description = "Security Group for Private EC2 instance" vpc_id = var.vpc_id egress { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = [var.vpc_cidr] } lifecycle { ignore_changes = [ingress, egress] } }
方案2:全量使用独立规则管理
删除安全组内的所有内嵌ingress/egress块,将所有规则都通过aws_security_group_rule资源声明:
resource "aws_security_group" "ec2_jumper_sg" { name = "${var.app_name}-private-sg" description = "Security Group for Private EC2 instance" vpc_id = var.vpc_id # 不添加任何ingress/egress内嵌块 } # 原有443出站规则改为独立资源 resource "aws_security_group_rule" "ec2_jumper_sg_443_egress" { security_group_id = aws_security_group.ec2_jumper_sg.id type = "egress" from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = [var.vpc_cidr] }
统一修正规则参数
将数据库出站规则的source_security_group_id改为destination_security_group_id:
resource "aws_security_group_rule" "ec2_jumper_sg_databases_egress" { for_each = var.databases security_group_id = aws_security_group.ec2_jumper_sg.id from_port = each.value.port to_port = each.value.port destination_security_group_id = each.value.securityGroupId protocol = "tcp" type = "egress" }
修复完成后执行terraform plan确认没有删除已有规则的动作后,再执行terraform apply即可解决问题。
内容的提问来源于stack exchange,提问作者Matteo
相关产品推荐
相关产品推荐

