Terraform中使用aws_network_interface_sg_attachment资源时保留已添加安全组的解决方案咨询
Got it, let's break down your problem first. The issue with using aws_network_interface_sg_attachment the way you are is that each instance of this resource represents a single security group attached to an ENI. When you update your variable to switch from sg-01 to sg-02 (keeping the count the same), Terraform sees that as replacing the existing attachment resource—so it destroys the sg-01 attachment and creates the sg-02 one.
Instead of managing individual attachments, the better approach is to manage the full set of security groups directly on the network interface or EC2 instance resource. This way, Terraform will handle adding/removing groups incrementally without wiping out existing ones (as long as you include all required groups in the configuration).
Solution 1: Update EC2 Instance's Security Groups Directly
If you're managing the EC2 instances in Terraform, modify the vpc_security_group_ids argument of the aws_instance resource to combine your original SG_main with the dynamic list of additional security groups.
First, adjust your input variable to support the multi-value mapping you need:
variable "sg_attachment" { type = list(object({ attach_security_group_id = list(string) })) default = [] }
Then, update your aws_instance resource to merge the base security group with instance-specific SGs:
resource "aws_instance" "EC2" { count = length(var.sg_attachment) # ... keep your existing instance config (ami, instance_type, etc.) ... # Combine the permanent SG_main with dynamic instance-specific SGs vpc_security_group_ids = concat( ["SG_main"], # Ensure this is always included to keep it attached var.sg_attachment[count.index].attach_security_group_id ) }
With this setup, when you add new SGs to var.sg_attachment (like adding sg-03 to the first instance's list), Terraform will only add that new SG to the ENI—leaving SG_main and existing SGs (e.g., sg-01, sg-02) completely intact.
Solution 2: Update a Standalone ENI (If Managed Separately)
If you're working with a standalone ENI (not the primary one created by the EC2 instance), use the aws_network_interface resource's vpc_security_group_ids argument instead:
resource "aws_network_interface" "eni" { count = length(var.sg_attachment) # ... keep your existing ENI config (subnet_id, description, etc.) ... vpc_security_group_ids = concat( ["SG_main"], var.sg_attachment[count.index].attach_security_group_id ) } # Attach the ENI to your EC2 instance if needed resource "aws_network_interface_attachment" "eni_attach" { count = length(var.sg_attachment) instance_id = aws_instance.EC2[count.index].id network_interface_id = aws_network_interface.eni[count.index].id device_index = 1 # Adjust this based on your ENI attachment needs }
Why This Works
Terraform treats the vpc_security_group_ids list as the desired full state of security groups attached to the ENI/instance. When you add a new SG to the list, Terraform only makes the minimal change (adding that SG) instead of replacing existing attachments. As long as you always include SG_main in the list, it will never be removed.
Handling Pre-Existing ENIs with SG_main
If the ENI was created outside Terraform (and already has SG_main attached), you first need to import the ENI into your Terraform state:
terraform import aws_network_interface.eni[0] eni-1234567890abcdef0
Once imported, set vpc_security_group_ids to include SG_main plus your dynamic SGs—Terraform will reconcile the state without removing the existing SG_main attachment.
内容的提问来源于stack exchange,提问作者Abhishek Solanki

