为何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
相关产品推荐
相关产品推荐

