You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Terraform会创建2个AWS EC2实例而非1个?求排查方案

问题:Terraform计划创建额外的EC2实例

我编写了以下Terraform代码,用于创建绑定弹性IP的AWS EC2实例:

data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"] # Canonical
}


resource "aws_instance" "myapp_staging" {
    ami=data.aws_ami.ubuntu.id
    instance_type="t3a.micro"
    
    root_block_device {
        volume_size = 30
        volume_type = "gp3"
    }

    vpc_security_group_ids=[
      "XXXXXXXX"
    ]

    tags={
      Name="myapp_staging"
    }

    volume_tags = {
      Name="myapp_staging"
    }
}



resource "aws_eip" "myapp_staging_ip" {
  tags = {
    Environment="Staging"
    Client="Esupport"
    Type="IP"
  }
}

resource "aws_eip_association" "eip_assoc" {
  instance_id   = aws_instance.myapp_staging.id
  allocation_id = aws_eip.myapp_staging_ip.id
}

但执行计划显示会创建2个实例,其中额外的实例来自module.ec2-instance.aws_instance.this[0],执行计划片段如下:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_eip.myapp_staging_ip will be created
  + resource "aws_eip" "myapp_staging_ip" {
      + allocation_id        = (known after apply)
      + association_id       = (known after apply)
      + carrier_ip           = (known after apply)
      + customer_owned_ip    = (known after apply)
      + domain               = (known after apply)
      + id                   = (known after apply)
      + instance             = (known after apply)
      + network_border_group = (known after apply)
      + network_interface    = (known after apply)
      + private_dns          = (known after apply)
      + private_ip           = (known after apply)
      + public_dns           = (known after apply)
      + public_ip            = (known after apply)
      + public_ipv4_pool     = (known after apply)
      + tags                 = {
          + "Environment" = "Staging"
          + "Type"        = "IP"
        }
      + tags_all             = {
          + "Environment" = "Staging"
          + "Type"        = "IP"
        }
      + vpc                  = (known after apply)
    }

  # aws_eip_association.eip_assoc will be created
  + resource "aws_eip_association" "eip_assoc" {
      + allocation_id        = (known after apply)
      + id                   = (known after apply)
      + instance_id          = (known after apply)
      + network_interface_id = (known after apply)
      + private_ip_address   = (known after apply)
      + public_ip            = (known after apply)
    }

  # aws_instance.myapp_staging will be created
  + resource "aws_instance" "myapp_staging" {
      + ami                                  = "ami-0d940f23d527c3ab1"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = (known after apply)
      + availability_zone                    = (known after apply)
      + cpu_core_count                       = (known after apply)
      + cpu_threads_per_core                 = (known after apply)
      + disable_api_stop                     = (known after apply)
      + disable_api_termination              = (known after apply)
      + ebs_optimized                        = (known after apply)
      + get_password_data                    = false
      + host_id                              = (known after apply)
      + host_resource_group_arn              = (known after apply)
      + iam_instance_profile                 = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_state                       = (known after apply)
      + instance_type                        = "t3a.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = (known after apply)
      + monitoring                           = (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      + placement_partition_number           = (known after apply)
      + primary_network_interface_id         = (known after apply)
      + private_dns                          = (known after apply)
      + private_ip                           = (known after apply)
      + public_dns                           = (known after apply)
      + public_ip                            = (known after apply)
      + secondary_private_ips                = (known after apply)
      + security_groups                      = (known after apply)
      + source_dest_check                    = true
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Name" = "myapp_staging"
        }
      + tags_all                             = {
          + "Name" = "myapp_staging"
        }
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + user_data_replace_on_change          = false
      + volume_tags                          = {
          + "Name" = "myapp_staging"
        }
      + vpc_security_group_ids               = [
          + "XXXXXXXXX",
        ]

      + root_block_device {
          + delete_on_termination = true
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + throughput            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = 30
          + volume_type           = "gp3"
        }
    }

  # module.ec2-instance.aws_instance.this[0] will be created
  + resource "aws_instance" "this" {
      + ami                                  = "ami-0785f49d3c3be2037"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = (known after apply)
      + availability_zone                    = (known after apply)
      + cpu_core_count                       = (known after apply)
      + cpu_threads_per_core                 = (known after apply)
      + disable_api_stop                     = (known after apply)
      + disable_api_termination              = (known after apply)
      + ebs_optimized                        = (known after apply)
      + get_password_data                    = false
      + host_id                              = (known after apply)
      + host_resource_group_arn              = (known after apply)
      + iam_instance_profile                 = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_state                       = (known after apply)
      + instance_type                        = "t3.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = (known after apply)
      + monitoring                           = (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      + placement_partition_number           = (known after apply)
      + primary_network_interface_id         = (known after apply)
      + private_dns                          = (known after apply)
      + private_ip                           = (known after apply)
      + public_dns                           = (known after apply)
      + public_ip                            = (known after apply)
      + secondary_private_ips                = (known after apply)
      + security_groups                      = (known after apply)
      + source_dest_check                    = true
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Name" = ""
        }
      + tags_all                             = {
          + "Name" = (known after apply)
        }
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + user_data_replace_on_change          = false
      + volume_tags                          = {
          + "Name" = ""
        }
      + vpc_security_group_ids               = (known after apply)

      + credit_specification {}

      + enclave_options {
          + enabled = (known after apply)
        }

      + metadata_options {
          + http_endpoint               = "enabled"
          + http_put_response_hop_limit = 1
          + http_tokens                 = "optional"
          + instance_metadata_tags      = (known after apply)
        }

      + timeouts {}
    }

Plan: 4 to add, 0 to change, 0 to destroy.

排查步骤

  • 检查所有.tf配置文件:全局搜索module "ec2-instance",确认是否存在未察觉的模块调用,可能是之前测试遗留或误添加的代码。
  • 查看模块依赖目录:检查.terraform/modules文件夹,确认是否有ec2-instance模块被下载,溯源该模块是由哪个配置文件引入的。
  • 检查Terraform状态:执行terraform state list命令,查看状态中是否已有module.ec2-instance.aws_instance.this[0]的记录。如果是历史遗留状态,可执行terraform state rm module.ec2-instance.aws_instance.this[0]移除(操作前务必备份状态文件)。
  • 限定执行目录:如果工作目录下有子目录包含Terraform配置,执行计划时可能会被意外包含。可使用terraform plan -chdir=.明确指定仅处理当前目录的配置。
  • 检查工作区:执行terraform workspace show查看当前工作区,切换到其他工作区执行计划对比,确认是否是特定工作区的配置导致问题。
  • 排查模块源引用:检查所有配置文件中的模块source参数,确认是否误引用了包含EC2实例的公共模块。

内容的提问来源于stack exchange,提问作者Dimitrios Desyllas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 07:15:54